Skip to content

Commit

Permalink
gallery-2011.09.14-20-40 Satyam gallery-makenode
Browse files Browse the repository at this point in the history
  • Loading branch information
YUI Builder committed Sep 14, 2011
1 parent 4b0cbeb commit 65d4672
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 97 deletions.
202 changes: 115 additions & 87 deletions src/gallery-makenode/js/gallery-makenode.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@
(function () { (function () {
// See: http://yuilibrary.com/projects/yui3/ticket/2531032 // See: http://yuilibrary.com/projects/yui3/ticket/2531032
var L = Y.Lang, DUMP = 'dump', SPACE = ' ', LBRACE = '{', RBRACE = '}', var L = Y.Lang, DUMP = 'dump', SPACE = ' ', LBRACE = '{', RBRACE = '}',
savedRegExp = /(~-(\d+)-~)/g; savedRegExp = /(~-(\d+)-~)/g, lBraceRegExp = /\{LBRACE\}/g, rBraceRegExp = /\{RBRACE\}/g;


Y.substitute = function(s, o, f, recurse) { Y.substitute = function(s, o, f, recurse) {
var i, j, k, key, v, meta, saved = [], token, dump, var i, j, k, key, v, meta, saved = [], token, dump,
lidx = s.length; lidx = s.length;


o = Y.merge({LBRACE:LBRACE,RBRACE:RBRACE},o); for (;;) {
for (;;) {
i = s.lastIndexOf(LBRACE, lidx); i = s.lastIndexOf(LBRACE, lidx);
if (i < 0) { if (i < 0) {
break; break;
Expand Down Expand Up @@ -72,7 +71,7 @@
} }
} }
} }
} else if (L.isUndefined(v)) { } else if (L.isUndefined(v)) {
// This {block} has no replace string. Save it for later. // This {block} has no replace string. Save it for later.
v = '~-' + saved.length + '-~'; v = '~-' + saved.length + '-~';
saved.push(token); saved.push(token);
Expand All @@ -87,13 +86,15 @@
} }


} }
// restore saved {block}s and replace escaped braces


// restore saved {block}s return s
s = s.replace(savedRegExp, function (str, p1, p2) { .replace(savedRegExp, function (str, p1, p2) {
return LBRACE + saved[parseInt(p2,10)] + RBRACE; return LBRACE + saved[parseInt(p2,10)] + RBRACE;
}); })

.replace(lBraceRegExp, LBRACE)
return s; .replace(rBraceRegExp, RBRACE)
;


}; };
})(); })();
Expand All @@ -114,18 +115,28 @@
* @constructor * @constructor
*/ */
MakeNode = function () { MakeNode = function () {
this._makeClassNames(); var self = this;
this._concatUIAttrs(); self._eventHandles = [];
this._publishEvents(); self._makeClassNames();
this.after('render', this._attachEvents, this); self._concatUIAttrs();
this.after('destroy', this._detachEvents, this); self._publishEvents();
self.after('render', self._attachEvents, self);
self.after('destroy', self._detachEvents, self);
}; };
MakeNode.prototype = { MakeNode.prototype = {
/**
* An array of event handles returned when attaching listeners to events,
* meant to detach them all when destroying the instance.
* @property _eventHandles
* @type Array
* @private
*/
_eventHandles:null,
/** /**
* Contains a hash of CSS classNames generated from the entries in <a href="#property__CLASS_NAMES"><code>_CLASS_NAMES</code></a> * Contains a hash of CSS classNames generated from the entries in <a href="#property__CLASS_NAMES"><code>_CLASS_NAMES</code></a>
* indexed by those same values. * indexed by those same values.
* It will also have the following entries added automatically: <ul> * It will also have the following entries added automatically: <ul>
* <li><code>.</code> The className for the boundingBox</li> * <li><code>boundingBox</code> The className for the boundingBox</li>
* <li><code>content</code> The className for the contentBox</li> * <li><code>content</code> The className for the contentBox</li>
* <li><code>HEADER</code> The className for the header section of a StdMod if Y.WidgetStdMod has been loaded</li> * <li><code>HEADER</code> The className for the header section of a StdMod if Y.WidgetStdMod has been loaded</li>
* <li><code>BODY</code> The className for the body section of a StdMod if Y.WidgetStdMod has been loaded</li> * <li><code>BODY</code> The className for the body section of a StdMod if Y.WidgetStdMod has been loaded</li>
Expand All @@ -139,6 +150,7 @@
/** /**
* Hash listing the template processing codes and the functions to handle each. * Hash listing the template processing codes and the functions to handle each.
* The processing functions will receive a string with the arguments that follow the processing code, * The processing functions will receive a string with the arguments that follow the processing code,
* and the extra, second argument passed on to _makeNode (or _substitute)
* and should return the replacement value for the placeholder. * and should return the replacement value for the placeholder.
* @property _templateHandlers * @property _templateHandlers
* @type Object * @type Object
Expand All @@ -160,8 +172,8 @@
'c': function (arg) { 'c': function (arg) {
return this._classNames[arg]; return this._classNames[arg];
}, },
's': function (arg) { 's': function (arg, extras) {
return this.get('strings')[arg]; return this._substitute(this.get('strings')[arg], extras);
}, },
'?': function(args) { '?': function(args) {
args = this._parseMakeNodeArgs(args); args = this._parseMakeNodeArgs(args);
Expand Down Expand Up @@ -222,6 +234,32 @@
} }
return args; return args;
}, },
/**
* Enumerates all the values and keys of a given static properties for all classes in the hierarchy,
* starting with the oldest ancestor (Base).
* @method _forAllXinClasses
* @param x {String} name of the static property to be enumerated
* @param fn {function} function to be called for each value.
* The function will receive a reference to the class where it occurs, the value of the property
* and the key or index.
* @private
*/

_forAllXinClasses: function(x, fn) {
var self = this,
cs = this._getClasses(),
l = cs.length,
i, c,
caller = function (v, k) {
fn.call(self, c, v, k);
};
for (i = l -1;i >= 0;i--) {
c = cs[i];
if (c[x]) {
Y.each(c[x], caller);
}
}
},
/** /**
* Processes the template given and returns a <code>Y.Node</code> instance. * Processes the template given and returns a <code>Y.Node</code> instance.
* @method _makeNode * @method _makeNode
Expand All @@ -245,8 +283,7 @@
/** /**
* Processes the given template and returns a string * Processes the given template and returns a string
* @method _substitute * @method _substitute
* @param template {String} (optional) Template to process. * @param template {String} Template to process.
* If missing, it will use the first static <a href="#property__TEMPLATE"><code>_TEMPLATE</code></a> property found in the inheritance chain.
* @param extras {Object} (optional) Hash of extra values to replace into the template, beyond MakeNode's processing codes. * @param extras {Object} (optional) Hash of extra values to replace into the template, beyond MakeNode's processing codes.
* @return {String} Template with the placeholders replaced. * @return {String} Template with the placeholders replaced.
* @protected * @protected
Expand All @@ -257,7 +294,7 @@
if (arg) { if (arg) {
fn = this._templateHandlers[key.toLowerCase()]; fn = this._templateHandlers[key.toLowerCase()];
if (fn) { if (fn) {
return fn.call(this, arg); return fn.call(this, arg, extras);
} }
} }
return suggested; return suggested;
Expand Down Expand Up @@ -295,7 +332,7 @@
* Looks for static properties called <a href="#property__CLASS_NAMES"><code>_CLASS_NAMES</code></a> in each of the classes of the inheritance chain * Looks for static properties called <a href="#property__CLASS_NAMES"><code>_CLASS_NAMES</code></a> in each of the classes of the inheritance chain
* and generates CSS classNames based on the <code>_cssPrefix</code> of each class and each of the suffixes listed in each them. * and generates CSS classNames based on the <code>_cssPrefix</code> of each class and each of the suffixes listed in each them.
* The classNames generated will be stored in <a href="#property__classNames"><code>this._classNames</code></a> indexed by the suffix. * The classNames generated will be stored in <a href="#property__classNames"><code>this._classNames</code></a> indexed by the suffix.
* It will also store the classNames of the boundingBox ( . )and the contentBox ( content ). * It will also store the classNames of the boundingBox ( boundingBox )and the contentBox ( content ).
* If the WidgetStdMod is used, it will also add the classNames for the three sections ( HEADER, BODY, FOOTER ) * If the WidgetStdMod is used, it will also add the classNames for the three sections ( HEADER, BODY, FOOTER )
* @method _makeClassNames * @method _makeClassNames
* @private * @private
Expand All @@ -304,20 +341,17 @@
var YCM = Y.ClassNameManager.getClassName, var YCM = Y.ClassNameManager.getClassName,
defined = {}, defined = {},
cns = this._classNames = {}; cns = this._classNames = {};
Y.each(this._getClasses(), function (c) {
if (c._CLASS_NAMES) { this._forAllXinClasses('_CLASS_NAMES', function(c, name) {
Y.each(c._CLASS_NAMES, function(name) { if (defined[name]) {
if (defined[name]) { Y.log(Y.substitute('ClassName' + DUPLICATE, {name:name, recentDef: defined[name], prevDef: c.NAME}), 'warn', 'MakeNode');
Y.log(Y.substitute('ClassName' + DUPLICATE, {name:name, recentDef: defined[name], prevDef: c.NAME}), 'warn', 'MakeNode'); } else {
} else { cns[name] = YCM(c.NAME.toLowerCase(), name);
cns[name] = YCM(c.NAME.toLowerCase(), name); defined[name] = c.NAME;
defined[name] = c.NAME;
}
});
} }
}); });


cns.content = (cns.boundingBox = YCM(this.constructor.NAME.toLowerCase())) + '-content'; cns.content = (cns[BBX] = YCM(this.constructor.NAME.toLowerCase())) + '-content';
if (this.getStdModNode) { if (this.getStdModNode) {
cns.HEADER = 'yui3-widget-hd'; cns.HEADER = 'yui3-widget-hd';
cns.BODY = 'yui3-widget-bd'; cns.BODY = 'yui3-widget-bd';
Expand Down Expand Up @@ -359,9 +393,9 @@
* @private * @private
*/ */
_attachEvents: function () { _attachEvents: function () {
var bbx = this.get(BBX), var self = this,
selector, bbx = self.get(BBX),
self = this, selector,
eh = [], eh = [],
type, fn, args, type, fn, args,
toInitialCap = function (name) { toInitialCap = function (name) {
Expand All @@ -373,53 +407,53 @@
THIS:self, THIS:self,
Y:Y Y:Y
}; };

self._forAllXinClasses('_EVENTS', function (c, handlers, key) {
Y.each(this._getClasses(), function (c) { selector = equivalents[key] || DOT + self._classNames[key];
Y.each (c._EVENTS || {}, function (handlers, key) { Y.each(Y.Array(handlers), function (handler) {
selector = equivalents[key] || DOT + this._classNames[key]; fn = null;
Y.each(Y.Array(handlers), function (handler) { if (Lang.isString(handler)) {
fn = null; type = handler;
if (Lang.isString(handler)) { args = null;
type = handler; } else if (Lang.isObject(handler)) {
args = null; type = handler.type;
} else if (Lang.isObject(handler)) { fn = handler.fn;
type = handler.type; args = handler.args;
fn = handler.fn; } else {
args = handler.args; Y.log('Bad event handler for class: ' + c.NAME + ' key: ' + key,'error','MakeNode');
}
if (type) {
fn = fn || '_after' + toInitialCap(key) + toInitialCap(type);
if (!self[fn]) {
Y.log('Listener method not found: ' + fn,'error','MakeNode');
} else { } else {
Y.log('Bad event handler for class: ' + c.NAME + ' key: ' + key,'error','MakeNode'); fn = self[fn];
} }
if (type) { if (Lang.isString(selector)) {
fn = fn || '_after' + toInitialCap(key) + toInitialCap(type); // All the classNames are processed here:
if (!self[fn]) { if (type==='key') {
Y.log('Listener method not found: ' + fn,'error','MakeNode'); eh.push(bbx.delegate(type, fn, args, selector, self));
} else { } else {
fn = self[fn]; eh.push(bbx.delegate(type, fn, selector, self, args));
} }
if (Lang.isString(selector)) { } else {
if (type==='key') { if (selector === self || selector === Y) {
eh.push(bbx.delegate(type, fn, args, selector, self)); // the Y and THIS selectors here
} else { eh.push(selector.after(type, fn, self, args));
eh.push(bbx.delegate(type, fn, selector, self, args));
}
} else { } else {
if (selector === self || selector === Y) { // The document and boundingBox here
eh.push(selector.after(type, fn, self, args)); if (type==='key') {
eh.push(Y.after(type, fn, selector, args, self));
} else { } else {
if (type==='key') { eh.push(Y.after(type, fn, selector, self, args));
eh.push(Y.after(type, fn, selector, args, self));
} else {
eh.push(Y.after(type, fn, selector, self, args));
}
} }
} }
} else {
Y.log('No type found in: ' + c.NAME + ', key: ' + key, 'error', 'MakeNode');
} }
}); } else {
}, this); Y.log('No type found in: ' + c.NAME + ', key: ' + key, 'error', 'MakeNode');
}, this); }
this._eventHandles = eh; });
});
this._eventHandles = this._eventHandles.concat(eh);
}, },


/** /**
Expand All @@ -429,19 +463,13 @@
* @private * @private
*/ */
_publishEvents: function () { _publishEvents: function () {
var cs = this._getClasses(), this._forAllXinClasses('_PUBLISH', function (c, options, name) {
l = cs.length, var opts = {};
i, Y.each(options || {}, function (value, opt) {
publisher = function (options, name) { opts[opt] =opt.substr(-2) === 'Fn'?this[value]:value;
var opts = {}; },this);
Y.each(options || {}, function (value, opt) { this.publish(name,opts);
opts[opt] =opt.substr(-2) === 'Fn'?this[value]:value; });
},this);
this.publish(name,opts);
};
for (i = l -1;i >= 0;i--) {
Y.each (cs[i]._PUBLISH || {}, publisher, this);
}
}, },
/** /**
* Detaches all the events created by <a href="method__attachEvents"><code>_attachEvents</code></a> * Detaches all the events created by <a href="method__attachEvents"><code>_attachEvents</code></a>
Expand Down
32 changes: 22 additions & 10 deletions src/gallery-makenode/tests/index.html
Original file line number Original file line Diff line number Diff line change
@@ -1,4 +1,3 @@

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html> <html>
<head> <head>
Expand Down Expand Up @@ -48,15 +47,6 @@


var suite = new Y.Test.Suite("TestSuite Name"); var suite = new Y.Test.Suite("TestSuite Name");


// restore saved {block}s
/* for (i = saved.length - 1; i >= 0; i = i - 1) {
s = s.replace(new RegExp('~-' + i + '-~'), LBRACE +
saved[i] + RBRACE, 'g');
}
*/ var saved = ['one','two'];
console.log('asdfasdf asdf ~-0-~ 1234 ~-1-~');

suite.add(new Y.Test.Case({ suite.add(new Y.Test.Case({
name: "tests template processor", name: "tests template processor",
setUp : function () { setUp : function () {
Expand All @@ -79,6 +69,13 @@
testNode.setContent(''); testNode.setContent('');
MN = mn = null; MN = mn = null;
}, },
testConstants : function () {
MN._TEMPLATE = '==={LBRACE}p prop{RBRACE}===';
mn = new MN();
mn.prop = 42;
mn.render(testNode);
A.areEqual('==={p prop}===',mn.get(CBX).getContent());
},
testP : function () { testP : function () {
MN._TEMPLATE = '==={p prop}==='; MN._TEMPLATE = '==={p prop}===';
mn = new MN(); mn = new MN();
Expand Down Expand Up @@ -134,6 +131,21 @@
A.areEqual('===this is a test===',mn.get(CBX).getContent()); A.areEqual('===this is a test===',mn.get(CBX).getContent());
delete MN.ATTRS; delete MN.ATTRS;
}, },
testSNested: function () {
MN._TEMPLATE = '==={s text}===';
MN.ATTRS = {
strings: {
value: {
text: 'My favorite number is {p prop}, the answer to all'
}
}
};
mn = new MN();
mn.prop = 42;
mn.render(testNode);
A.areEqual('===My favorite number is 42, the answer to all===',mn.get(CBX).getContent());
delete MN.ATTRS;
},
testWithIntl: function () { testWithIntl: function () {


Y.use('intl', function (Y) { Y.use('intl', function (Y) {
Expand Down

0 comments on commit 65d4672

Please sign in to comment.