Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix for issue #601: Unexpected Y.WidgetStdMod + Y.WidgetButtons behavior #602

Open
wants to merge 7 commits into from

5 participants

@jslayer

Suggested changed to fix an issues described in #601 .

@jslayer jslayer closed this
@jslayer jslayer reopened this
src/widget-stdmod/js/Widget-StdMod.js
@@ -266,17 +266,17 @@
_syncUIStdMod : function() {
var stdModParsed = this._stdModParsed;
- if (!stdModParsed || !stdModParsed[HEADER_CONTENT]) {
- this._uiSetStdMod(STD_HEADER, this.get(HEADER_CONTENT));
- }
+ Y.each([STD_HEADER, STD_BODY, STD_FOOTER], function(section) {
@rgrove
rgrove added a note

Can you change this to Y.Array.each()? We're trying to discourage the use of Y.each() since it can lead to ambiguity when code is being read, and results in many more function calls for little benefit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@rgrove

@jslayer: Thanks for this! We'll need unit tests before we can pull this change, though. Would you mind adding some?

I'd also like to have this reviewed by someone more familiar with WidgetStdMod and WidgetButtons than I am, just for sanity.

@jslayer

@rgrove, thank for the answer.

I have replaced Y.each with Y.Array.each (dbe5626)

And change they way of how the _getButtonContainer (Y.WidgetButtons module) search an existing container. My previous suggestion pass the tests, but I understood, that there could be the cases, when previous code (written by someone else) could stop working like before.

I think, that there are at least two cases which didn't covered:

  • my example of nested widgets (update fiddle)
  • having buttons container node which isn't the child of section node (in example when the existing html markup is used, and this container is wrapped )

If the current suggestions are usefull, in order of covering the described utilization, I can write the tests for the cases above by myself.


can't understand why the travis build of 42b1b39 is failed

@rgrove

@jslayer Thanks! It looks like the Travis failure is an unrelated error, so that's not your fault.

If you can add tests to cover the two cases you described, that would be perfect.

src/widget-buttons/js/widget-buttons.js
@@ -602,7 +602,19 @@ WidgetButtons.prototype = {
// Search for an existing buttons container within the section.
containerSelector = '.' + sectionClassName + ' .' + buttonsClassName;
- container = contentBox.one(containerSelector);
+
+ // Search only inside the current widget
+ contentBox.all(containerSelector).each(function(node, index) {
@ericf Owner
ericf added a note

NodeList#some() can be used here instead of each().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jslayer

@ericf you are right, it is much better. Thank you. Did you mean to do that in this way bac20cb ?

@rgrove I'm not yet prepared the tests, but they will be finished soon.

@jslayer

@rgrove I have added a couple of tests to cover #601

@rgrove

@jslayer Thanks!

@sdesai and @ericf, would you mind looking this over when you have a chance? I'm not super familiar with WidgetStdMod or WidgetButtons, so I'd like your feedback before I merge this in.

@sdesai

I'll let @ericf take this one, once he's back in the office Monday, since he authored the WidgetButtons stuff. If he doesn't get to it, I'll take a look once I'm done with the broader attrs stuff for Sprint 8.

@jslayer jslayer referenced this pull request from a commit
@jslayer jslayer merge #602 4d005f5
@triptych

Ping @ericf @clarle for comments. See @rgrove 's earlier request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 11, 2013
  1. @jslayer

    yui/yui3 #601 issue

    jslayer authored
Commits on Apr 12, 2013
  1. @jslayer

    #601 - fix content replacement

    jslayer authored
Commits on Apr 19, 2013
  1. @jslayer
  2. @jslayer
Commits on May 7, 2013
  1. @jslayer

    #601 - replace with

    jslayer authored
Commits on Jun 17, 2013
  1. @jslayer
  2. @jslayer
This page is out of date. Refresh to see the latest.
View
4 build/widget-buttons/widget-buttons-coverage.js
2 additions, 2 deletions not shown
View
12 build/widget-buttons/widget-buttons-debug.js
@@ -604,7 +604,17 @@ WidgetButtons.prototype = {
// Search for an existing buttons container within the section.
containerSelector = '.' + sectionClassName + ' .' + buttonsClassName;
- container = contentBox.one(containerSelector);
+
+ // Search only inside the current widget
+ contentBox.all(containerSelector).some(function(node){
+ var widget = Y.Widget.getByNode(node),
+ isBelongs = !widget || widget === this;
+
+ if (isBelongs) {
+ container = node;
+ }
+ return isBelongs;
+ }, this);
// Create the `container` if it doesn't already exist.
if (!container && create) {
View
4 build/widget-buttons/widget-buttons-min.js
@@ -1,2 +1,2 @@
-YUI.add("widget-buttons",function(e,t){function p(e){return!!e.getDOMNode}function d(){this._stdModNode||e.error("WidgetStdMod must be added to a Widget before WidgetButtons."),this._buttonsHandles={}}var n=e.Array,r=e.Lang,i=e.Object,s=e.Plugin.Button,o=e.Widget,u=e.WidgetStdMod,a=e.ClassNameManager.getClassName,f=r.isArray,l=r.isNumber,c=r.isString,h=r.isValue;d.ATTRS={buttons:{getter:"_getButtons",setter:"_setButtons",value:{}},defaultButton:{readOnly:!0,value:null}},d.CLASS_NAMES={button:a("button"),buttons:o.getClassName("buttons"),primary:a("button","primary")},d.HTML_PARSER={buttons:function(e){return this._parseButtons(e)}},d.NON_BUTTON_NODE_CFG=["action","classNames","context","events","isDefault","section"],d.prototype={BUTTONS:{},BUTTONS_TEMPLATE:"<span />",DEFAULT_BUTTONS_SECTION:u.FOOTER,initializer:function(){this._mapButtons(this.get("buttons")),this._updateDefaultButton(),this.after({buttonsChange:e.bind("_afterButtonsChange",this),defaultButtonChange:e.bind("_afterDefaultButtonChange",this)}),e.after(this._bindUIButtons,this,"bindUI"),e.after(this._syncUIButtons,this,"syncUI")},destructor:function(){i.each(this._buttonsHandles,function(e){e.detach()}),delete this._buttonsHandles,delete this._buttonsMap,delete this._defaultButton},addButton:function(e,t,r){var i=this.get("buttons"),s,o;return p(e)||(e=this._mergeButtonConfig(e),t||(t=e.section)),t||(t=this.DEFAULT_BUTTONS_SECTION),s=i[t]||(i[t]=[]),l(r)||(r=s.length),s.splice(r,0,e),o=n.indexOf(s,e),this.set("buttons",i,{button:e,section:t,index:o,src:"add"}),this},getButton:function(e,t){if(!h(e))return;var n=this._buttonsMap,r;return t||(t=this.DEFAULT_BUTTONS_SECTION),l(e)?(r=this.get("buttons"),r[t]&&r[t][e]):arguments.length>1?n[t+":"+e]:n[e]},removeButton:function(e,t){if(!h(e))return this;var r=this.get("buttons"),s;return l(e)?(t||(t=this.DEFAULT_BUTTONS_SECTION),s=e,e=r[t][s]):(c(e)&&(e=this.getButton.apply(this,arguments)),i.some(r,function(r,i){s=n.indexOf(r,e);if(s>-1)return t=i,!0})),e&&s>-1&&(r[t].splice(s,1),this.set("buttons",r,{button:e,section:t,index:s,src:"remove"})),this},_bindUIButtons:function(){var t=e.bind("_afterContentChangeButtons",this);this.after({visibleChange:e.bind("_afterVisibleChangeButtons",this),headerContentChange:t,bodyContentChange:t,footerContentChange:t})},_createButton:function(t){var r,i,o,u,a,f,l,h;if(p(t))return e.one(t.getDOMNode()).plug(s);r=e.merge({context:this,events:"click",label:t.value},t),i=e.merge(r),o=d.NON_BUTTON_NODE_CFG;for(u=0,a=o.length;u<a;u+=1)delete i[o[u]];return t=s.createNode(i),l=r.context,f=r.action,c(f)&&(f=e.bind(f,l)),h=t.on(r.events,f,l),this._buttonsHandles[e.stamp(t,!0)]=h,t.setData("name",this._getButtonName(r)),t.setData("default",this._getButtonDefault(r)),n.each(n(r.classNames),t.addClass,t),t},_getButtonContainer:function(t,n){var r=u.SECTION_CLASS_NAMES[t],i=d.CLASS_NAMES.buttons,s=this.get("contentBox"),o,a;return o="."+r+" ."+i,a=s.one(o),!a&&n&&(a=e.Node.create(this.BUTTONS_TEMPLATE),a.addClass(i)),a},_getButtonDefault:function(e){var t=p(e)?e.getData("default"):e.isDefault;return c(t)?t.toLowerCase()==="true":!!t},_getButtonName:function(e){var t;return p(e)?t=e.getData("name")||e.get("name"):t=e&&(e.name||e.type),t},_getButtons:function(e){var t={};return i.each(e,function(e,n){t[n]=e.concat()}),t},_mapButton:function(e,t){var n=this._buttonsMap,r=this._getButtonName(e),i=this._getButtonDefault(e);r&&(n[r]=e,n[t+":"+r]=e),i&&(this._defaultButton=e)},_mapButtons:function(e){this._buttonsMap={},this._defaultButton=null,i.each(e,function(e,t){var n,r;for(n=0,r=e.length;n<r;n+=1)this._mapButton(e[n],t)},this)},_mergeButtonConfig:function(t){var n,r,i,s,o,u;return t=c(t)?{name:t}:e.merge(t),t.srcNode&&(s=t.srcNode,o=s.get("tagName").toLowerCase(),u=s.get(o==="input"?"value":"text"),n={disabled:!!s.get("disabled"),isDefault:this._getButtonDefault(s),name:this._getButtonName(s)},u&&(n.label=u),e.mix(t,n,!1,null,0,!0)),i=this._getButtonName(t),r=this.BUTTONS&&this.BUTTONS[i],r&&e.mix(t,r,!1,null,0,!0),t},_parseButtons:function(e){var t="."+d.CLASS_NAMES.button,r=["header","body","footer"],i=null;return n.each(r,function(e){var n=this._getButtonContainer(e),r=n&&n.all(t),s;if(!r||r.isEmpty())return;s=[],r.each(function(e){s.push({srcNode:e})}),i||(i={}),i[e]=s},this),i},_setButtons:function(e){function r(e,r){if(!f(e))return;var i,s,o,u;for(i=0,s=e.length;i<s;i+=1)o=e[i],u=r,p(o)||(o=this._mergeButtonConfig(o),u||(u=o.section)),o=this._createButton(o),u||(u=t),(n[u]||(n[u]=[])).push(o)}var t=this.DEFAULT_BUTTONS_SECTION,n={};return f(e)?r.call(this,e):i.each(e,r,this),n},_syncUIButtons:function(){this._uiSetButtons(this.get("buttons")),this._uiSetDefaultButton(this.get("defaultButton")),this._uiSetVisibleButtons(this.get("visible"))},_uiInsertButton:function(e,t,n){var r=d.CLASS_NAMES.button,i=this._getButtonContainer(t,!0),s=i.all("."+r);i.insertBefore(e,s.item(n)),this.setStdModContent(t,i,"after")},_uiRemoveButton:function(t,n,r){var i=e.stamp(t,this),s=this._buttonsHandles,o=s[i],u,a;o&&o.detach(),delete s[i],t.remove(),r||(r={}),r.preserveContent||(u=this._getButtonContainer(n),a=d.CLASS_NAMES.button,u&&u.all("."+a).isEmpty()&&(u.remove(),this._updateContentButtons(n)))},_uiSetButtons:function(e){var t=d.CLASS_NAMES.button,r=["header","body","footer"];n.each(r,function(n){var r=e[n]||[],i=r.length,s=this._getButtonContainer(n,i),o=!1,u,a,f,l;if(!s)return;u=s.all("."+t);for(a=0;a<i;a+=1)f=r[a],l=u.indexOf(f),l>-1?(u.splice(l,1),l!==a&&(s.insertBefore(f,a+1),o=!0)):(s.appendChild(f),o=!0);u.each(function(e){this._uiRemoveButton(e,n,{preserveContent:!0}),o=!0},this);if(i===0){s.remove(),this._updateContentButtons(n);return}o&&this.setStdModContent(n,s,"after")},this)},_uiSetDefaultButton:function(e,t){var n=d.CLASS_NAMES.primary;e&&e.addClass(n),t&&t.removeClass(n)},_uiSetVisibleButtons:function(e){if(!e)return;var t=this.get("defaultButton");t&&t.focus()},_unMapButton:function(e,t){var n=this._buttonsMap,r=this._getButtonName(e),i;r&&(n[r]===e&&delete
-n[r],i=t+":"+r,n[i]===e&&delete n[i]),this._defaultButton===e&&(this._defaultButton=null)},_updateDefaultButton:function(){var e=this._defaultButton;this.get("defaultButton")!==e&&this._set("defaultButton",e)},_updateContentButtons:function(e){var t=this.getStdModNode(e).get("childNodes");this.set(e+"Content",t.isEmpty()?null:t,{src:"buttons"})},_afterButtonsChange:function(e){var t=e.newVal,n=e.section,r=e.index,i=e.src,s;if(i==="add"){s=t[n][r],this._mapButton(s,n),this._updateDefaultButton(),this._uiInsertButton(s,n,r);return}if(i==="remove"){s=e.button,this._unMapButton(s,n),this._updateDefaultButton(),this._uiRemoveButton(s,n);return}this._mapButtons(t),this._updateDefaultButton(),this._uiSetButtons(t)},_afterContentChangeButtons:function(e){var t=e.src,n=e.stdModPosition,r=!n||n===u.REPLACE;r&&t!=="buttons"&&t!==o.UI_SRC&&this._uiSetButtons(this.get("buttons"))},_afterDefaultButtonChange:function(e){this._uiSetDefaultButton(e.newVal,e.prevVal)},_afterVisibleChangeButtons:function(e){this._uiSetVisibleButtons(e.newVal)}},e.WidgetButtons=d},"@VERSION@",{requires:["button-plugin","cssbutton","widget-stdmod"]});
+YUI.add("widget-buttons",function(e,t){function p(e){return!!e.getDOMNode}function d(){this._stdModNode||e.error("WidgetStdMod must be added to a Widget before WidgetButtons."),this._buttonsHandles={}}var n=e.Array,r=e.Lang,i=e.Object,s=e.Plugin.Button,o=e.Widget,u=e.WidgetStdMod,a=e.ClassNameManager.getClassName,f=r.isArray,l=r.isNumber,c=r.isString,h=r.isValue;d.ATTRS={buttons:{getter:"_getButtons",setter:"_setButtons",value:{}},defaultButton:{readOnly:!0,value:null}},d.CLASS_NAMES={button:a("button"),buttons:o.getClassName("buttons"),primary:a("button","primary")},d.HTML_PARSER={buttons:function(e){return this._parseButtons(e)}},d.NON_BUTTON_NODE_CFG=["action","classNames","context","events","isDefault","section"],d.prototype={BUTTONS:{},BUTTONS_TEMPLATE:"<span />",DEFAULT_BUTTONS_SECTION:u.FOOTER,initializer:function(){this._mapButtons(this.get("buttons")),this._updateDefaultButton(),this.after({buttonsChange:e.bind("_afterButtonsChange",this),defaultButtonChange:e.bind("_afterDefaultButtonChange",this)}),e.after(this._bindUIButtons,this,"bindUI"),e.after(this._syncUIButtons,this,"syncUI")},destructor:function(){i.each(this._buttonsHandles,function(e){e.detach()}),delete this._buttonsHandles,delete this._buttonsMap,delete this._defaultButton},addButton:function(e,t,r){var i=this.get("buttons"),s,o;return p(e)||(e=this._mergeButtonConfig(e),t||(t=e.section)),t||(t=this.DEFAULT_BUTTONS_SECTION),s=i[t]||(i[t]=[]),l(r)||(r=s.length),s.splice(r,0,e),o=n.indexOf(s,e),this.set("buttons",i,{button:e,section:t,index:o,src:"add"}),this},getButton:function(e,t){if(!h(e))return;var n=this._buttonsMap,r;return t||(t=this.DEFAULT_BUTTONS_SECTION),l(e)?(r=this.get("buttons"),r[t]&&r[t][e]):arguments.length>1?n[t+":"+e]:n[e]},removeButton:function(e,t){if(!h(e))return this;var r=this.get("buttons"),s;return l(e)?(t||(t=this.DEFAULT_BUTTONS_SECTION),s=e,e=r[t][s]):(c(e)&&(e=this.getButton.apply(this,arguments)),i.some(r,function(r,i){s=n.indexOf(r,e);if(s>-1)return t=i,!0})),e&&s>-1&&(r[t].splice(s,1),this.set("buttons",r,{button:e,section:t,index:s,src:"remove"})),this},_bindUIButtons:function(){var t=e.bind("_afterContentChangeButtons",this);this.after({visibleChange:e.bind("_afterVisibleChangeButtons",this),headerContentChange:t,bodyContentChange:t,footerContentChange:t})},_createButton:function(t){var r,i,o,u,a,f,l,h;if(p(t))return e.one(t.getDOMNode()).plug(s);r=e.merge({context:this,events:"click",label:t.value},t),i=e.merge(r),o=d.NON_BUTTON_NODE_CFG;for(u=0,a=o.length;u<a;u+=1)delete i[o[u]];return t=s.createNode(i),l=r.context,f=r.action,c(f)&&(f=e.bind(f,l)),h=t.on(r.events,f,l),this._buttonsHandles[e.stamp(t,!0)]=h,t.setData("name",this._getButtonName(r)),t.setData("default",this._getButtonDefault(r)),n.each(n(r.classNames),t.addClass,t),t},_getButtonContainer:function(t,n){var r=u.SECTION_CLASS_NAMES[t],i=d.CLASS_NAMES.buttons,s=this.get("contentBox"),o,a;return o="."+r+" ."+i,s.all(o).some(function(t){var n=e.Widget.getByNode(t),r=!n||n===this;return r&&(a=t),r},this),!a&&n&&(a=e.Node.create(this.BUTTONS_TEMPLATE),a.addClass(i)),a},_getButtonDefault:function(e){var t=p(e)?e.getData("default"):e.isDefault;return c(t)?t.toLowerCase()==="true":!!t},_getButtonName:function(e){var t;return p(e)?t=e.getData("name")||e.get("name"):t=e&&(e.name||e.type),t},_getButtons:function(e){var t={};return i.each(e,function(e,n){t[n]=e.concat()}),t},_mapButton:function(e,t){var n=this._buttonsMap,r=this._getButtonName(e),i=this._getButtonDefault(e);r&&(n[r]=e,n[t+":"+r]=e),i&&(this._defaultButton=e)},_mapButtons:function(e){this._buttonsMap={},this._defaultButton=null,i.each(e,function(e,t){var n,r;for(n=0,r=e.length;n<r;n+=1)this._mapButton(e[n],t)},this)},_mergeButtonConfig:function(t){var n,r,i,s,o,u;return t=c(t)?{name:t}:e.merge(t),t.srcNode&&(s=t.srcNode,o=s.get("tagName").toLowerCase(),u=s.get(o==="input"?"value":"text"),n={disabled:!!s.get("disabled"),isDefault:this._getButtonDefault(s),name:this._getButtonName(s)},u&&(n.label=u),e.mix(t,n,!1,null,0,!0)),i=this._getButtonName(t),r=this.BUTTONS&&this.BUTTONS[i],r&&e.mix(t,r,!1,null,0,!0),t},_parseButtons:function(e){var t="."+d.CLASS_NAMES.button,r=["header","body","footer"],i=null;return n.each(r,function(e){var n=this._getButtonContainer(e),r=n&&n.all(t),s;if(!r||r.isEmpty())return;s=[],r.each(function(e){s.push({srcNode:e})}),i||(i={}),i[e]=s},this),i},_setButtons:function(e){function r(e,r){if(!f(e))return;var i,s,o,u;for(i=0,s=e.length;i<s;i+=1)o=e[i],u=r,p(o)||(o=this._mergeButtonConfig(o),u||(u=o.section)),o=this._createButton(o),u||(u=t),(n[u]||(n[u]=[])).push(o)}var t=this.DEFAULT_BUTTONS_SECTION,n={};return f(e)?r.call(this,e):i.each(e,r,this),n},_syncUIButtons:function(){this._uiSetButtons(this.get("buttons")),this._uiSetDefaultButton(this.get("defaultButton")),this._uiSetVisibleButtons(this.get("visible"))},_uiInsertButton:function(e,t,n){var r=d.CLASS_NAMES.button,i=this._getButtonContainer(t,!0),s=i.all("."+r);i.insertBefore(e,s.item(n)),this.setStdModContent(t,i,"after")},_uiRemoveButton:function(t,n,r){var i=e.stamp(t,this),s=this._buttonsHandles,o=s[i],u,a;o&&o.detach(),delete s[i],t.remove(),r||(r={}),r.preserveContent||(u=this._getButtonContainer(n),a=d.CLASS_NAMES.button,u&&u.all("."+a).isEmpty()&&(u.remove(),this._updateContentButtons(n)))},_uiSetButtons:function(e){var t=d.CLASS_NAMES.button,r=["header","body","footer"];n.each(r,function(n){var r=e[n]||[],i=r.length,s=this._getButtonContainer(n,i),o=!1,u,a,f,l;if(!s)return;u=s.all("."+t);for(a=0;a<i;a+=1)f=r[a],l=u.indexOf(f),l>-1?(u.splice(l,1),l!==a&&(s.insertBefore(f,a+1),o=!0)):(s.appendChild(f),o=!0);u.each(function(e){this._uiRemoveButton(e,n,{preserveContent:!0}),o=!0},this);if(i===0){s.remove(),this._updateContentButtons(n);return}o&&this.setStdModContent(n,s,"after")},this)},_uiSetDefaultButton:function(e,t){var n=d.CLASS_NAMES.primary;e&&e.addClass(n),t&&t.removeClass(n)},_uiSetVisibleButtons:function(e){if(!e)return;var t=this.get("defaultButton");t&&t.focus()},_unMapButton
+:function(e,t){var n=this._buttonsMap,r=this._getButtonName(e),i;r&&(n[r]===e&&delete n[r],i=t+":"+r,n[i]===e&&delete n[i]),this._defaultButton===e&&(this._defaultButton=null)},_updateDefaultButton:function(){var e=this._defaultButton;this.get("defaultButton")!==e&&this._set("defaultButton",e)},_updateContentButtons:function(e){var t=this.getStdModNode(e).get("childNodes");this.set(e+"Content",t.isEmpty()?null:t,{src:"buttons"})},_afterButtonsChange:function(e){var t=e.newVal,n=e.section,r=e.index,i=e.src,s;if(i==="add"){s=t[n][r],this._mapButton(s,n),this._updateDefaultButton(),this._uiInsertButton(s,n,r);return}if(i==="remove"){s=e.button,this._unMapButton(s,n),this._updateDefaultButton(),this._uiRemoveButton(s,n);return}this._mapButtons(t),this._updateDefaultButton(),this._uiSetButtons(t)},_afterContentChangeButtons:function(e){var t=e.src,n=e.stdModPosition,r=!n||n===u.REPLACE;r&&t!=="buttons"&&t!==o.UI_SRC&&this._uiSetButtons(this.get("buttons"))},_afterDefaultButtonChange:function(e){this._uiSetDefaultButton(e.newVal,e.prevVal)},_afterVisibleChangeButtons:function(e){this._uiSetVisibleButtons(e.newVal)}},e.WidgetButtons=d},"@VERSION@",{requires:["button-plugin","cssbutton","widget-stdmod"]});
View
12 build/widget-buttons/widget-buttons.js
@@ -604,7 +604,17 @@ WidgetButtons.prototype = {
// Search for an existing buttons container within the section.
containerSelector = '.' + sectionClassName + ' .' + buttonsClassName;
- container = contentBox.one(containerSelector);
+
+ // Search only inside the current widget
+ contentBox.all(containerSelector).some(function(node){
+ var widget = Y.Widget.getByNode(node),
+ isBelongs = !widget || widget === this;
+
+ if (isBelongs) {
+ container = node;
+ }
+ return isBelongs;
+ }, this);
// Create the `container` if it doesn't already exist.
if (!container && create) {
View
4 build/widget-stdmod/widget-stdmod-coverage.js
2 additions, 2 deletions not shown
View
23 build/widget-stdmod/widget-stdmod-debug.js
@@ -268,17 +268,17 @@ YUI.add('widget-stdmod', function (Y, NAME) {
_syncUIStdMod : function() {
var stdModParsed = this._stdModParsed;
- if (!stdModParsed || !stdModParsed[HEADER_CONTENT]) {
- this._uiSetStdMod(STD_HEADER, this.get(HEADER_CONTENT));
- }
+ Y.Array.each([STD_HEADER, STD_BODY, STD_FOOTER], function(section) {
+ var content;
- if (!stdModParsed || !stdModParsed[BODY_CONTENT]) {
- this._uiSetStdMod(STD_BODY, this.get(BODY_CONTENT));
- }
+ if (!stdModParsed || !stdModParsed[section + CONTENT_SUFFIX]) {
+ content = this.get(section + CONTENT_SUFFIX);
- if (!stdModParsed || !stdModParsed[FOOTER_CONTENT]) {
- this._uiSetStdMod(STD_FOOTER, this.get(FOOTER_CONTENT));
- }
+ if (content) {
+ this._uiSetStdMod(section, content, this._getStdModContent(section) ? Y.WidgetStdMod.BEFORE : false);
+ }
+ }
+ }, this);
this._uiSetFillHeight(this.get(FILL_HEIGHT));
},
@@ -460,7 +460,10 @@ YUI.add('widget-stdmod', function (Y, NAME) {
this.set(section + CONTENT_SUFFIX, this._getStdModContent(section), {src:UI});
} else {
- this._eraseStdMod(section);
+ if (!this._getStdModContent(section)) {
+ //remove the section if it is empty
+ this._eraseStdMod(section);
+ }
}
this.fire(ContentUpdate);
},
View
2  build/widget-stdmod/widget-stdmod-min.js
@@ -1 +1 @@
-YUI.add("widget-stdmod",function(e,t){function H(t){this._stdModNode=this.get(w),e.before(this._renderUIStdMod,this,O),e.before(this._bindUIStdMod,this,M),e.before(this._syncUIStdMod,this,_)}var n=e.Lang,r=e.Node,i=e.UA,s=e.Widget,o="",u="hd",a="bd",f="ft",l="header",c="body",h="footer",p="fillHeight",d="stdmod",v="Node",m="Content",g="firstChild",y="childNodes",b="ownerDocument",w="contentBox",E="height",S="offsetHeight",x="auto",T="headerContentChange",N="bodyContentChange",C="footerContentChange",k="fillHeightChange",L="heightChange",A="contentUpdate",O="renderUI",M="bindUI",_="syncUI",D="_applyParsedConfig",P=e.Widget.UI_SRC;H.HEADER=l,H.BODY=c,H.FOOTER=h,H.AFTER="after",H.BEFORE="before",H.REPLACE="replace";var B=H.HEADER,j=H.BODY,F=H.FOOTER,I=B+m,q=F+m,R=j+m;H.ATTRS={headerContent:{value:null},footerContent:{value:null},bodyContent:{value:null},fillHeight:{value:H.BODY,validator:function(e){return this._validateFillHeight(e)}}},H.HTML_PARSER={headerContent:function(e){return this._parseStdModHTML(B)},bodyContent:function(e){return this._parseStdModHTML(j)},footerContent:function(e){return this._parseStdModHTML(F)}},H.SECTION_CLASS_NAMES={header:s.getClassName(u),body:s.getClassName(a),footer:s.getClassName(f)},H.TEMPLATES={header:'<div class="'+H.SECTION_CLASS_NAMES[B]+'"></div>',body:'<div class="'+H.SECTION_CLASS_NAMES[j]+'"></div>',footer:'<div class="'+H.SECTION_CLASS_NAMES[F]+'"></div>'},H.prototype={_syncUIStdMod:function(){var e=this._stdModParsed;(!e||!e[I])&&this._uiSetStdMod(B,this.get(I)),(!e||!e[R])&&this._uiSetStdMod(j,this.get(R)),(!e||!e[q])&&this._uiSetStdMod(F,this.get(q)),this._uiSetFillHeight(this.get(p))},_renderUIStdMod:function(){this._stdModNode.addClass(s.getClassName(d)),this._renderStdModSections(),this.after(T,this._afterHeaderChange),this.after(N,this._afterBodyChange),this.after(C,this._afterFooterChange)},_renderStdModSections:function(){n.isValue(this.get(I))&&this._renderStdMod(B),n.isValue(this.get(R))&&this._renderStdMod(j),n.isValue(this.get(q))&&this._renderStdMod(F)},_bindUIStdMod:function(){this.after(k,this._afterFillHeightChange),this.after(L,this._fillHeight),this.after(A,this._fillHeight)},_afterHeaderChange:function(e){e.src!==P&&this._uiSetStdMod(B,e.newVal,e.stdModPosition)},_afterBodyChange:function(e){e.src!==P&&this._uiSetStdMod(j,e.newVal,e.stdModPosition)},_afterFooterChange:function(e){e.src!==P&&this._uiSetStdMod(F,e.newVal,e.stdModPosition)},_afterFillHeightChange:function(e){this._uiSetFillHeight(e.newVal)},_validateFillHeight:function(e){return!e||e==H.BODY||e==H.HEADER||e==H.FOOTER},_uiSetFillHeight:function(e){var t=this.getStdModNode(e),n=this._currFillNode;n&&t!==n&&n.setStyle(E,o),t&&(this._currFillNode=t),this._fillHeight()},_fillHeight:function(){if(this.get(p)){var e=this.get(E);e!=o&&e!=x&&this.fillHeight(this._currFillNode)}},_uiSetStdMod:function(e,t,r){if(n.isValue(t)){var i=this.getStdModNode(e,!0);this._addStdModContent(i,t,r),this.set(e+m,this._getStdModContent(e),{src:P})}else this._eraseStdMod(e);this.fire(A)},_renderStdMod:function(e){var t=this.get(w),n=this._findStdModSection(e);return n||(n=this._getStdModTemplate(e)),this._insertStdModSection(t,e,n),this[e+v]=n,this[e+v]},_eraseStdMod:function(e){var t=this.getStdModNode(e);t&&(t.remove(!0),delete this[e+v])},_insertStdModSection:function(e,t,n){var r=e.get(g);if(t===F||!r)e.appendChild(n);else if(t===B)e.insertBefore(n,r);else{var i=this[F+v];i?e.insertBefore(n,i):e.appendChild(n)}},_getStdModTemplate:function(e){return r.create(H.TEMPLATES[e],this._stdModNode.get(b))},_addStdModContent:function(e,t,n){switch(n){case H.BEFORE:n=0;break;case H.AFTER:n=undefined;break;default:n=H.REPLACE}e.insert(t,n)},_getPreciseHeight:function(e){var t=e?e.get(S):0,n="getBoundingClientRect";if(e&&e.hasMethod(n)){var r=e.invoke(n);r&&(t=r.bottom-r.top)}return t},_findStdModSection:function(e){return this.get(w).one("> ."+H.SECTION_CLASS_NAMES[e])},_parseStdModHTML:function(t){var n=this._findStdModSection(t);return n?(this._stdModParsed||(this._stdModParsed={},e.before(this._applyStdModParsedConfig,this,D)),this._stdModParsed[t+m]=1,n.get("innerHTML")):null},_applyStdModParsedConfig:function(e,t,n){var r=this._stdModParsed;r&&(r[I]=!(I in t)&&I in r,r[R]=!(R in t)&&R in r,r[q]=!(q in t)&&q in r)},_getStdModContent:function(e){return this[e+v]?this[e+v].get(y):null},setStdModContent:function(e,t,n){this.set(e+m,t,{stdModPosition:n})},getStdModNode:function(e,t){var n=this[e+v]||null;return!n&&t&&(n=this._renderStdMod(e)),n},fillHeight:function(e){if(e){var t=this.get(w),r=[this.headerNode,this.bodyNode,this.footerNode],s,o,u=0,a=0,f=!1;for(var l=0,c=r.length;l<c;l++)s=r[l],s&&(s!==e?u+=this._getPreciseHeight(s):f=!0);f&&((i.ie||i.opera)&&e.set(S,0),o=t.get(S)-parseInt(t.getComputedStyle("paddingTop"),10)-parseInt(t.getComputedStyle("paddingBottom"),10)-parseInt(t.getComputedStyle("borderBottomWidth"),10)-parseInt(t.getComputedStyle("borderTopWidth"),10),n.isNumber(o)&&(a=o-u,a>=0&&e.set(S,a)))}}},e.WidgetStdMod=H},"@VERSION@",{requires:["base-build","widget"]});
+YUI.add("widget-stdmod",function(e,t){function H(t){this._stdModNode=this.get(w),e.before(this._renderUIStdMod,this,O),e.before(this._bindUIStdMod,this,M),e.before(this._syncUIStdMod,this,_)}var n=e.Lang,r=e.Node,i=e.UA,s=e.Widget,o="",u="hd",a="bd",f="ft",l="header",c="body",h="footer",p="fillHeight",d="stdmod",v="Node",m="Content",g="firstChild",y="childNodes",b="ownerDocument",w="contentBox",E="height",S="offsetHeight",x="auto",T="headerContentChange",N="bodyContentChange",C="footerContentChange",k="fillHeightChange",L="heightChange",A="contentUpdate",O="renderUI",M="bindUI",_="syncUI",D="_applyParsedConfig",P=e.Widget.UI_SRC;H.HEADER=l,H.BODY=c,H.FOOTER=h,H.AFTER="after",H.BEFORE="before",H.REPLACE="replace";var B=H.HEADER,j=H.BODY,F=H.FOOTER,I=B+m,q=F+m,R=j+m;H.ATTRS={headerContent:{value:null},footerContent:{value:null},bodyContent:{value:null},fillHeight:{value:H.BODY,validator:function(e){return this._validateFillHeight(e)}}},H.HTML_PARSER={headerContent:function(e){return this._parseStdModHTML(B)},bodyContent:function(e){return this._parseStdModHTML(j)},footerContent:function(e){return this._parseStdModHTML(F)}},H.SECTION_CLASS_NAMES={header:s.getClassName(u),body:s.getClassName(a),footer:s.getClassName(f)},H.TEMPLATES={header:'<div class="'+H.SECTION_CLASS_NAMES[B]+'"></div>',body:'<div class="'+H.SECTION_CLASS_NAMES[j]+'"></div>',footer:'<div class="'+H.SECTION_CLASS_NAMES[F]+'"></div>'},H.prototype={_syncUIStdMod:function(){var t=this._stdModParsed;e.Array.each([B,j,F],function(n){var r;if(!t||!t[n+m])r=this.get(n+m),r&&this._uiSetStdMod(n,r,this._getStdModContent(n)?e.WidgetStdMod.BEFORE:!1)},this),this._uiSetFillHeight(this.get(p))},_renderUIStdMod:function(){this._stdModNode.addClass(s.getClassName(d)),this._renderStdModSections(),this.after(T,this._afterHeaderChange),this.after(N,this._afterBodyChange),this.after(C,this._afterFooterChange)},_renderStdModSections:function(){n.isValue(this.get(I))&&this._renderStdMod(B),n.isValue(this.get(R))&&this._renderStdMod(j),n.isValue(this.get(q))&&this._renderStdMod(F)},_bindUIStdMod:function(){this.after(k,this._afterFillHeightChange),this.after(L,this._fillHeight),this.after(A,this._fillHeight)},_afterHeaderChange:function(e){e.src!==P&&this._uiSetStdMod(B,e.newVal,e.stdModPosition)},_afterBodyChange:function(e){e.src!==P&&this._uiSetStdMod(j,e.newVal,e.stdModPosition)},_afterFooterChange:function(e){e.src!==P&&this._uiSetStdMod(F,e.newVal,e.stdModPosition)},_afterFillHeightChange:function(e){this._uiSetFillHeight(e.newVal)},_validateFillHeight:function(e){return!e||e==H.BODY||e==H.HEADER||e==H.FOOTER},_uiSetFillHeight:function(e){var t=this.getStdModNode(e),n=this._currFillNode;n&&t!==n&&n.setStyle(E,o),t&&(this._currFillNode=t),this._fillHeight()},_fillHeight:function(){if(this.get(p)){var e=this.get(E);e!=o&&e!=x&&this.fillHeight(this._currFillNode)}},_uiSetStdMod:function(e,t,r){if(n.isValue(t)){var i=this.getStdModNode(e,!0);this._addStdModContent(i,t,r),this.set(e+m,this._getStdModContent(e),{src:P})}else this._getStdModContent(e)||this._eraseStdMod(e);this.fire(A)},_renderStdMod:function(e){var t=this.get(w),n=this._findStdModSection(e);return n||(n=this._getStdModTemplate(e)),this._insertStdModSection(t,e,n),this[e+v]=n,this[e+v]},_eraseStdMod:function(e){var t=this.getStdModNode(e);t&&(t.remove(!0),delete this[e+v])},_insertStdModSection:function(e,t,n){var r=e.get(g);if(t===F||!r)e.appendChild(n);else if(t===B)e.insertBefore(n,r);else{var i=this[F+v];i?e.insertBefore(n,i):e.appendChild(n)}},_getStdModTemplate:function(e){return r.create(H.TEMPLATES[e],this._stdModNode.get(b))},_addStdModContent:function(e,t,n){switch(n){case H.BEFORE:n=0;break;case H.AFTER:n=undefined;break;default:n=H.REPLACE}e.insert(t,n)},_getPreciseHeight:function(e){var t=e?e.get(S):0,n="getBoundingClientRect";if(e&&e.hasMethod(n)){var r=e.invoke(n);r&&(t=r.bottom-r.top)}return t},_findStdModSection:function(e){return this.get(w).one("> ."+H.SECTION_CLASS_NAMES[e])},_parseStdModHTML:function(t){var n=this._findStdModSection(t);return n?(this._stdModParsed||(this._stdModParsed={},e.before(this._applyStdModParsedConfig,this,D)),this._stdModParsed[t+m]=1,n.get("innerHTML")):null},_applyStdModParsedConfig:function(e,t,n){var r=this._stdModParsed;r&&(r[I]=!(I in t)&&I in r,r[R]=!(R in t)&&R in r,r[q]=!(q in t)&&q in r)},_getStdModContent:function(e){return this[e+v]?this[e+v].get(y):null},setStdModContent:function(e,t,n){this.set(e+m,t,{stdModPosition:n})},getStdModNode:function(e,t){var n=this[e+v]||null;return!n&&t&&(n=this._renderStdMod(e)),n},fillHeight:function(e){if(e){var t=this.get(w),r=[this.headerNode,this.bodyNode,this.footerNode],s,o,u=0,a=0,f=!1;for(var l=0,c=r.length;l<c;l++)s=r[l],s&&(s!==e?u+=this._getPreciseHeight(s):f=!0);f&&((i.ie||i.opera)&&e.set(S,0),o=t.get(S)-parseInt(t.getComputedStyle("paddingTop"),10)-parseInt(t.getComputedStyle("paddingBottom"),10)-parseInt(t.getComputedStyle("borderBottomWidth"),10)-parseInt(t.getComputedStyle("borderTopWidth"),10),n.isNumber(o)&&(a=o-u,a>=0&&e.set(S,a)))}}},e.WidgetStdMod=H},"@VERSION@",{requires:["base-build","widget"]});
View
23 build/widget-stdmod/widget-stdmod.js
@@ -268,17 +268,17 @@ YUI.add('widget-stdmod', function (Y, NAME) {
_syncUIStdMod : function() {
var stdModParsed = this._stdModParsed;
- if (!stdModParsed || !stdModParsed[HEADER_CONTENT]) {
- this._uiSetStdMod(STD_HEADER, this.get(HEADER_CONTENT));
- }
+ Y.Array.each([STD_HEADER, STD_BODY, STD_FOOTER], function(section) {
+ var content;
- if (!stdModParsed || !stdModParsed[BODY_CONTENT]) {
- this._uiSetStdMod(STD_BODY, this.get(BODY_CONTENT));
- }
+ if (!stdModParsed || !stdModParsed[section + CONTENT_SUFFIX]) {
+ content = this.get(section + CONTENT_SUFFIX);
- if (!stdModParsed || !stdModParsed[FOOTER_CONTENT]) {
- this._uiSetStdMod(STD_FOOTER, this.get(FOOTER_CONTENT));
- }
+ if (content) {
+ this._uiSetStdMod(section, content, this._getStdModContent(section) ? Y.WidgetStdMod.BEFORE : false);
+ }
+ }
+ }, this);
this._uiSetFillHeight(this.get(FILL_HEIGHT));
},
@@ -460,7 +460,10 @@ YUI.add('widget-stdmod', function (Y, NAME) {
this.set(section + CONTENT_SUFFIX, this._getStdModContent(section), {src:UI});
} else {
- this._eraseStdMod(section);
+ if (!this._getStdModContent(section)) {
+ //remove the section if it is empty
+ this._eraseStdMod(section);
+ }
}
this.fire(ContentUpdate);
},
View
12 src/widget-buttons/js/widget-buttons.js
@@ -602,7 +602,17 @@ WidgetButtons.prototype = {
// Search for an existing buttons container within the section.
containerSelector = '.' + sectionClassName + ' .' + buttonsClassName;
- container = contentBox.one(containerSelector);
+
+ // Search only inside the current widget
+ contentBox.all(containerSelector).some(function(node){
+ var widget = Y.Widget.getByNode(node),
+ isBelongs = !widget || widget === this;
+
+ if (isBelongs) {
+ container = node;
+ }
+ return isBelongs;
+ }, this);
// Create the `container` if it doesn't already exist.
if (!container && create) {
View
122 src/widget-buttons/tests/unit/assets/widget-buttons-test.js
@@ -1155,6 +1155,128 @@ suite.add(new Y.Test.Case({
}
}));
+suite.add(new Y.Test.Case({
+ name: 'Nested rendering',
+
+ tearDown : function() {
+ if (this.widget) {
+ this.widget.destroy();
+ }
+ if (this.child) {
+ this.child.destroy();
+ }
+ Y.one('#test').empty();
+ },
+ 'Child widget should be rendered into existing sections in `renderUI` of main widget' : function() {
+ var Main,
+ buttons,
+ test = this;
+
+ Main = Y.Base.create('main', Y.Widget, [Y.WidgetStdMod, Y.WidgetButtons], {
+ renderUI : function() {
+ var body = this.getStdModNode('body', true);
+
+ test.child = new TestWidget({
+ render : body,
+ buttons : [{
+ label: 'CB:Body',
+ section: 'body'
+ }]
+ });
+ }
+ });
+
+ this.main = new Main({
+ render: '#test',
+ buttons : [{
+ label: 'Main:Body',
+ section: 'body'
+ }]
+ });
+
+ buttons = this.main.get('boundingBox').all('.yui3-button');
+
+ Assert.areSame(2, buttons.size(), '2 buttons should be created in total');
+ Assert.areSame(this.main.getButton(0, 'body'), buttons.item(1), 'Main body button placed incorrectly');
+ Assert.areSame('Main:Body', this.main.getButton(0, 'body').get('text'), 'Main body button did not have the text "Main:Body"');
+
+ Assert.areSame(this.child.getButton(0, 'body'), buttons.item(0), 'Child body button placed incorrectly');
+ Assert.areSame('CB:Body', this.child.getButton(0, 'body').get('text'), 'Child body button did not have the text "CB:Body"');
+ },
+ 'Child widget should be rendered into newly created header section in `renderUI` of main widget' : function() {
+ var Main,
+ buttons,
+ test = this;
+
+ Main = Y.Base.create('main', Y.Widget, [Y.WidgetStdMod, Y.WidgetButtons], {
+ renderUI : function() {
+ var header = this.getStdModNode('header', true);
+
+ test.child = new TestWidget({
+ render : header,
+ buttons : [{
+ label: 'CH:Body',
+ section: 'body'
+ }]
+ });
+ }
+ });
+
+ this.main = new Main({
+ render: '#test',
+ buttons : [{
+ label: 'Main:Body',
+ section: 'body'
+ }]
+ });
+
+ buttons = this.main.get('boundingBox').all('.yui3-button');
+
+ Assert.areSame(2, buttons.size(), '2 buttons should be created in total');
+ Assert.areSame(this.main.getButton(0, 'body'), buttons.item(1), 'Main body button placed incorrectly');
+ Assert.areSame('Main:Body', this.main.getButton(0, 'body').get('text'), 'Main body button did not have the text "Main:Body"');
+
+ Assert.areSame(this.child.getButton(0, 'body'), buttons.item(0), 'Child body button placed incorrectly');
+ Assert.areSame('CH:Body', this.child.getButton(0, 'body').get('text'), 'Child body button did not have the text "CB:Body"');
+ },
+ 'Child widget should be rendered into newly created footer section in `renderUI` of main widget' : function() {
+ var Main,
+ buttons,
+ test = this;
+
+ Main = Y.Base.create('main', Y.Widget, [Y.WidgetStdMod, Y.WidgetButtons], {
+ renderUI : function() {
+ var footer = this.getStdModNode('footer', true);
+
+ test.child = new TestWidget({
+ render : footer,
+ buttons : [{
+ label: 'CF:Body',
+ section: 'body'
+ }]
+ })
+ }
+ });
+
+ this.main = new Main({
+ render: '#test',
+ buttons : [{
+ label: 'Main:Body',
+ section: 'body'
+ }]
+ });
+
+ buttons = this.main.get('boundingBox').all('.yui3-button');
+
+ Assert.areSame(2, buttons.size(), '2 buttons should be created in total');
+ Assert.areSame(this.main.getButton(0, 'body'), buttons.item(0), 'Main body button placed incorrectly');
+ Assert.areSame('Main:Body', this.main.getButton(0, 'body').get('text'), 'Main body button did not have the text "Main:Body"');
+
+ Assert.areSame(this.child.getButton(0, 'body'), buttons.item(1), 'Child body button placed incorrectly');
+ Assert.areSame('CF:Body', this.child.getButton(0, 'body').get('text'), 'Child body button did not have the text "CB:Body"');
+ }
+}));
+
// -- Events -------------------------------------------------------------------
suite.add(new Y.Test.Case({
name: 'Events',
View
23 src/widget-stdmod/js/Widget-StdMod.js
@@ -266,17 +266,17 @@
_syncUIStdMod : function() {
var stdModParsed = this._stdModParsed;
- if (!stdModParsed || !stdModParsed[HEADER_CONTENT]) {
- this._uiSetStdMod(STD_HEADER, this.get(HEADER_CONTENT));
- }
+ Y.Array.each([STD_HEADER, STD_BODY, STD_FOOTER], function(section) {
+ var content;
- if (!stdModParsed || !stdModParsed[BODY_CONTENT]) {
- this._uiSetStdMod(STD_BODY, this.get(BODY_CONTENT));
- }
+ if (!stdModParsed || !stdModParsed[section + CONTENT_SUFFIX]) {
+ content = this.get(section + CONTENT_SUFFIX);
- if (!stdModParsed || !stdModParsed[FOOTER_CONTENT]) {
- this._uiSetStdMod(STD_FOOTER, this.get(FOOTER_CONTENT));
- }
+ if (content) {
+ this._uiSetStdMod(section, content, this._getStdModContent(section) ? Y.WidgetStdMod.BEFORE : false);
+ }
+ }
+ }, this);
this._uiSetFillHeight(this.get(FILL_HEIGHT));
},
@@ -458,7 +458,10 @@
this.set(section + CONTENT_SUFFIX, this._getStdModContent(section), {src:UI});
} else {
- this._eraseStdMod(section);
+ if (!this._getStdModContent(section)) {
+ //remove the section if it is empty
+ this._eraseStdMod(section);
+ }
}
this.fire(ContentUpdate);
},
View
21 src/widget-stdmod/tests/unit/assets/widget-stdmod-test.js
@@ -61,6 +61,27 @@ suite.add(new Y.Test.Case({
Assert.isNotNull(this.widget.getStdModNode('header', true), 'Header node was null.');
},
+ 'getStdModNode() should create the section node in `renderUI` when `forceCreate` is truthy' : function() {
+ var TestWidget,
+ header,
+ stdHeader;
+
+ TestWidget = Y.Base.create('testWidget', Y.Widget, [Y.WidgetStdMod], {
+ renderUI : function() {
+ header = this.getStdModNode('header', true);
+
+ header.set('text', 'foo');
+ }
+ });
+
+ this.widget = new TestWidget({render: '#test'});
+
+ stdHeader = this.widget.getStdModNode('header', true);
+
+ Assert.areSame(header, stdHeader, 'Header section created in `renderUI` is not correct');
+ Assert.areSame('foo', stdHeader.get('text', 'foo'), 'Header section created in `renderUI` did not have "foo" text');
+ },
+
'setStdModContent() should update the body section of the standard module': function () {
this.widget = new TestWidget({
headerContent: 'foo',
Something went wrong with that request. Please try again.