Re: SproutCore--over 20000 lines of new code!



On Jan 1, 12:47 am, Charles Jolley <u...@xxxxxxxxxxxxxx/> wrote:
Hi I am the creator of sproutcore.  If you had taken the time to look at the rest of sproutcore you might have noticed that corequery is not used very often because our view layer has a more powerful system called the rendercontext.  


//
==========================================================================
// Project: SproutCore - JavaScript Application Framework
// Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
// Portions ©2008-2009 Apple Inc. All rights reserved.
// License: Licened under MIT license (see license.js)
//
==========================================================================

sc_require('system/builder');

/** set update mode on context to replace content (preferred) */
SC.MODE_REPLACE = 'replace';

/** set update mode on context to append content */
SC.MODE_APPEND = 'append';

/** set update mode on context to prepend content */
SC.MODE_PREPEND = 'prepend';

/**
@namespace

A RenderContext is a builder that can be used to generate HTML for
views or
to update an existing element. Rather than making changes to an
element
directly, you use a RenderContext to queue up changes to the
element,
finally applying those changes or rendering the new element when you
are
finished.

You will not usually create a render context yourself but you will
be passed
a render context as the first parameter of your render() method on
custom
views.

Render contexts are essentially arrays of strings. You can add a
string to
the context by calling push(). You can retrieve the entire array as
a
single string using join(). This is basically the way the context
is used
for views. You are passed a render context and expected to add
strings of
HTML to the context like a normal array. Later, the context will be
joined
into a single string and converted into real HTML for display on
screen.

In addition to the core push and join methods, the render context
also
supports some extra methods that make it easy to build tags.

context.begin() <-- begins a new tag context
context.end() <-- ends the tag context...
*/
SC.RenderContext = SC.Builder.create(/** SC.RenderContext.fn */ {

SELF_CLOSING: SC.CoreSet.create().addEach('area base basefront br hr
input img link meta'.w()),


basefont (and it is long deprecated)



/**
When you create a context you should pass either a tag name or an
element
that should be used as the basis for building the context. If you
pass
an element, then the element will be inspected for class names,
styles
and other attributes. You can also call update() or replace() to
modify the element with you context contents.

If you do not pass any parameters, then we assume the tag name is
'div'.

A second parameter, parentContext, is used internally for
chaining. You
should never pass a second argument.

@param {String|DOMElement} tagNameOrElement
@returns {SC.RenderContext} receiver
*/
init: function(tagNameOrElement, prevContext) {
if (tagNameOrElement === undefined) tagNameOrElement = 'div';

// if a prevContext was passed, setup with that first...
if (prevContext) {
this.prevObject = prevContext ;
this.strings = prevContext.strings ;
this.offset = prevContext.length + prevContext.offset ;
}

if (!this.strings) this.strings = [] ;

// if tagName is string, just setup for rendering new tagName
this.needsContent = YES ;
if (SC.typeOf(tagNameOrElement) === SC.T_STRING) {
this._tagName = tagNameOrElement.toLowerCase();
this._needsTag = YES ; // used to determine if end() needs to
wrap tag

// increase length of all contexts to leave space for opening
tag
var c = this;
while(c) { c.length++; c = c.prevObject; }

this.strings.push(null);
this._selfClosing = this.SELF_CLOSING.contains(this._tagName);
} else {
this._elem = tagNameOrElement ;
this._needsTag = NO ;
this.length = 0 ;
this.needsContent = NO ;
}

return this ;
},

// ..........................................................
// PROPERTIES
//

// NOTE: We store this as an actual array of strings so that
browsers that
// support dense arrays will use them.
/**
The current working array of strings.

@property {Array}
*/
strings: null,

/**
this initial offset into the strings array where this context
instance
has its opening tag.

@property {Number}
*/
offset: 0,

/**
the current number of strings owned by the context, including the
opening
tag.

@property {Number}
*/
length: 0,

/**
Specify the method that should be used to update content on the
element.
In almost all cases you want to replace the content. Very
carefully
managed code (such as in CollectionView) can append or prepend
content
instead.

You probably do not want to change this propery unless you know
what you
are doing.

@property {String}
*/
updateMode: SC.MODE_REPLACE,

/**
YES if the context needs its content filled in, not just its
outer
attributes edited. This will be set to YES anytime you push
strings into
the context or if you don't create it with an element to start
with.
*/
needsContent: NO,

// ..........................................................
// CORE STRING API
//

/**
Returns the string at the designated index. If you do not pass
anything
returns the string array. This index is an offset from the start
of the
strings owned by this context.

@param {Number} idx the index
@returns {String|Array}
*/
get: function(idx) {
var strings = this.strings || [];
return (idx === undefined) ? strings.slice(this.offset,
this.length) : strings[idx+this.offset];
},

/**
Adds a string to the render context for later joining. Note that
you can
pass multiple arguments to this method and each item will be
pushed.

@param {String} line the liene to add to the string.


Liene?


@returns {SC.RenderContext} receiver
*/
push: function(line) {
var strings = this.strings, len = arguments.length;
if (!strings) this.strings = strings = []; // create array lazily

if (len > 1) {
strings.push.apply(strings, arguments) ;
} else strings.push(line);

// adjust string length for context and all parents...
var c = this;
while(c) { c.length += len; c = c.prevObject; }

this.needsContent = YES;

return this;
},

/**
Pushes the passed string onto the array, but first escapes the
string
to ensure that no user-entered HTML is processed as HTML.

@param {String} line one or mroe lines of text to add
@returns {SC.RenderContext} receiver
*/
text: function(line) {
var len = arguments.length, idx=0;
for(idx=0;idx<len;idx++) {
this.push(SC.RenderContext.escapeHTML(arguments[idx]));
}
return this ;
},

/**
Joins the strings together, returning the result. But first, this
will
end any open tags.

@param {String} joinChar optional string to use in joins. def
empty string
@returns {String} joined string
*/
join: function(joinChar) {

// generate tag if needed...
if (this._needsTag) this.end();

var strings = this.strings;
return strings ? strings.join(joinChar || '') : '' ;
},

// ..........................................................
// GENERATING
//

/**
Begins a new render context based on the passed tagName or
element.
Generate said context using end().

@returns {SC.RenderContext} new context
*/
begin: function(tagNameOrElement) {
// console.log('%@.begin(%@) called'.fmt(this, tagNameOrElement));


Delete debugging code.


return SC.RenderContext(tagNameOrElement, this);
},

/**
If the current context targets an element, this method returns
the
element. If the context does not target an element, this method
will
render the context into an offscreen element and return it.

@returns {DOMElement} the element
*/
element: function() {
if (this._elem) return this._elem;
// create factory div if needed
var ret, child;
if (!SC.RenderContext.factory) {
SC.RenderContext.factory = document.createElement('div');
}
SC.RenderContext.factory.innerHTML = this.join();

// In IE something weird happens when reusing the same element.


That doesn't inspire confidence. ;)


// After setting innerHTML, the innerHTML of the element in the
previous view
// turns blank. Seems that there is something weird with their
garbage
// collection algorithm.


No. There is something weird going on with your script(s).


// I tried just removing the nodes after keeping a
// reference to the first child, but it didnt work.
// Ended up cloning the first child.


http://www.jibbering.com/faq/faq_notes/clj_posts.html#ps1DontWork


if(SC.RenderContext.factory.innerHTML.length>0){
child = SC.RenderContext.factory.firstChild.cloneNode(true);
SC.RenderContext.factory.innerHTML = '';
} else {
child = null;
}
return child ;
},

/**
Removes an element with the passed id in the currently managed
element.
*/
remove: function(elementId) {
// console.log('remove('+elementId+')');
if (!elementId) return ;


Delete the above two lines. If the calling code is broken, let it
break so you can see the problem(s). ;)


var el, elem = this._elem ;
if (!elem || !elem.removeChild) return ;


Huh? No removeChild method featured, so fail silently?


el = document.getElementById(elementId) ;
if (el) {
el = elem.removeChild(el) ;
el = null;
}
},

/**
If an element was set on this context when it was created, this
method
will actually apply any changes to the element itself. If you
have not
written any inner html into the context, then the innerHTML of
the
element will not be changed, otherwise it will be replaced with
the new
innerHTML.

Also, any attributes, id, classNames or styles you've set will be
updated as well. This also ends the editing context session and
cleans
up.

@returns {SC.RenderContext} previous context or null if top
*/
update: function() {
var elem = this._elem,
mode = this.updateMode,
key, value, styles, factory, cur, next, before;

this._innerHTMLReplaced = NO;

if (!elem) {
// throw "Cannot update context because there is no source
element";
return ;


*Sigh* See above.


}

// console.log('%@#update() called'.fmt(this));
// if (this.length>0) console.log(this.join());
// else console.log('<no length>');
// replace innerHTML
if (this.length>0) {
this._innerHTMLReplaced = YES;
if (mode === SC.MODE_REPLACE) {
elem.innerHTML = this.join();
} else {
factory = elem.cloneNode(false);
factory.innerHTML = this.join() ;
before = (mode === SC.MODE_APPEND) ? null : elem.firstChild;
cur = factory.firstChild ;
while(cur) {
next = cur.nextSibling ;
elem.insertBefore(cur, next);
cur = next ;
}
cur = next = factory = before = null ; // cleanup
}
}

// note: each of the items below only apply if the private
variable has
// been set to something other than null (indicating they were
used at
// some point during the build)

// if we have attrs, apply them
if (this._attrsDidChange && (value = this._attrs)) {
for(key in value) {
if (!value.hasOwnProperty(key)) continue;


You just sank Safari 2. See previous post.


if (value[key] === null) { // remove empty attrs
elem.removeAttribute(key);

LOL. You are making the same mistakes as jQuery, Prototype, YUI, etc.

http://www.cinsoft.net/attributes.html


} else {
SC.$(elem).attr(key, value[key]);

You can't be a little pregnant. Thank you very much for wasting my
time. :)
.



Relevant Pages

  • Re: IPostBackDataHandler.LoadPostData
    ... string, or should just write directly to the writer. ... Here is the HtmlTextWriter way to render this code. ... tag is send to the browser, you add the inner html and then on to the EndTag ... > No it still doesnt call it for the control on the user controls. ...
    (microsoft.public.dotnet.framework.aspnet)
  • RE: Custom Control that accepts Inline Code
    ... I was having a similar problem - for me, I had a special title control - ... I wanted to render the contents between the tags using a text randomizer ... control to the "contents string". ... As soon as you throw in an inline tag - boom, ...
    (microsoft.public.dotnet.framework.aspnet.buildingcontrols)
  • Re: SQL
    ... Just a naked string. ... also that in this case it is not the context which determines the types, ... I.e. it is dynamic typing, ... interesting than math libraries IMO. ...
    (comp.object)
  • Re: SQL
    ... Just a naked string. ... Note that different libraries may accept different inputs. ... In context typing, "typing is in the mind and only in the ...
    (comp.object)
  • Re: Test first as specification
    ... >>> the only valid input string is an infinite string of a's? ... Without some additional knowledge about the language we ... The context you mention below. ... correctness may be a matter of degree. ...
    (comp.object)