Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: moodle/moodle
...
head fork: samhemelryk/moodle
compare: output_prototype_3
Checking mergeability… Don't worry, you can still create the pull request.
  • 1 commit
  • 54 files changed
  • 0 commit comments
  • 1 contributor
Showing with 10,666 additions and 2 deletions.
  1. +10 −2 lib/outputrenderers.php
  2. +220 −0 lib/yuilib/gallery/gallery-sm-menu-base/gallery-sm-menu-base-debug.js
  3. +1 −0  lib/yuilib/gallery/gallery-sm-menu-base/gallery-sm-menu-base-min.js
  4. +220 −0 lib/yuilib/gallery/gallery-sm-menu-base/gallery-sm-menu-base.js
  5. +137 −0 lib/yuilib/gallery/gallery-sm-menu-item/gallery-sm-menu-item-debug.js
  6. +1 −0  lib/yuilib/gallery/gallery-sm-menu-item/gallery-sm-menu-item-min.js
  7. +137 −0 lib/yuilib/gallery/gallery-sm-menu-item/gallery-sm-menu-item.js
  8. +222 −0 lib/yuilib/gallery/gallery-sm-menu-plugin/gallery-sm-menu-plugin-debug.js
  9. +1 −0  lib/yuilib/gallery/gallery-sm-menu-plugin/gallery-sm-menu-plugin-min.js
  10. +222 −0 lib/yuilib/gallery/gallery-sm-menu-plugin/gallery-sm-menu-plugin.js
  11. +49 −0 lib/yuilib/gallery/gallery-sm-menu-templates/gallery-sm-menu-templates-debug.js
  12. +1 −0  lib/yuilib/gallery/gallery-sm-menu-templates/gallery-sm-menu-templates-min.js
  13. +49 −0 lib/yuilib/gallery/gallery-sm-menu-templates/gallery-sm-menu-templates.js
  14. +63 −0 lib/yuilib/gallery/gallery-sm-menu/assets/gallery-sm-menu-core.css
  15. +50 −0 lib/yuilib/gallery/gallery-sm-menu/assets/skins/sam/gallery-sm-menu-skin.css
  16. +1 −0  lib/yuilib/gallery/gallery-sm-menu/assets/skins/sam/gallery-sm-menu.css
  17. +1,282 −0 lib/yuilib/gallery/gallery-sm-menu/gallery-sm-menu-debug.js
  18. +2 −0  lib/yuilib/gallery/gallery-sm-menu/gallery-sm-menu-min.js
  19. +1,282 −0 lib/yuilib/gallery/gallery-sm-menu/gallery-sm-menu.js
  20. +166 −0 local/output/classes/atom.php
  21. +12 −0 local/output/classes/component.php
  22. +23 −0 local/output/classes/element.php
  23. +41 −0 local/output/classes/link.php
  24. +75 −0 local/output/classes/menu.php
  25. +64 −0 local/output/classes/menu_dropdown.php
  26. +12 −0 local/output/classes/span.php
  27. +45 −0 local/output/index.php
  28. +15 −0 local/output/lang/en/local_output.php
  29. +62 −0 local/output/locallib.php
  30. +235 −0 local/output/renderer.php
  31. +10 −0 theme/output_bs3/config.php
  32. +6 −0 theme/output_bs3/javascript/bootstrap.js
  33. +4 −0 theme/output_bs3/javascript/jquery.min.js
  34. 0  theme/output_bs3/lang/en/theme_output_bs3.php
  35. +5 −0 theme/output_bs3/lib.php
  36. +41 −0 theme/output_bs3/renderers.php
  37. +7 −0 theme/output_bs3/style/bootstrap.css
  38. +10 −0 theme/output_pureio/config.php
  39. +18 −0 theme/output_pureio/javascript/menu.js
  40. 0  theme/output_pureio/lang/en/theme_output_pureio.php
  41. +5 −0 theme/output_pureio/lib.php
  42. +47 −0 theme/output_pureio/renderers.php
  43. +11 −0 theme/output_pureio/style/pure.css
  44. +11 −0 theme/output_zurb/config.php
  45. +9 −0 theme/output_zurb/javascript/fastclick.js
  46. +10 −0 theme/output_zurb/javascript/foundation.min.js
  47. +1 −0  theme/output_zurb/javascript/init.js
  48. +8 −0 theme/output_zurb/javascript/jquery.cookie.js
  49. +26 −0 theme/output_zurb/javascript/jquery.js
  50. +8 −0 theme/output_zurb/javascript/modernizr.js
  51. +42 −0 theme/output_zurb/renderers.php
  52. +5,263 −0 theme/output_zurb/style/foundation.css
  53. +1 −0  theme/output_zurb/style/foundation.min.css
  54. +423 −0 theme/output_zurb/style/normalize.css
View
12 lib/outputrenderers.php
@@ -96,7 +96,11 @@ public function __construct(moodle_page $page, $target) {
* @return string
*/
public function render(renderable $widget) {
- $rendermethod = 'render_'.get_class($widget);
+ if ($widget instanceof core_ui_element) {
+ $rendermethod = 'render_'.substr(get_class($widget), strlen('core_ui_'));
+ } else {
+ $rendermethod = 'render_'.get_class($widget);
+ }
if (method_exists($this, $rendermethod)) {
return $this->$rendermethod($widget);
}
@@ -216,7 +220,11 @@ public function __construct(moodle_page $page, $target) {
* @return string
*/
public function render(renderable $widget) {
- $rendermethod = 'render_'.get_class($widget);
+ if ($widget instanceof core_ui_element) {
+ $rendermethod = 'render_'.substr(get_class($widget), strlen('core_ui_'));
+ } else {
+ $rendermethod = 'render_'.get_class($widget);
+ }
if (method_exists($this, $rendermethod)) {
return $this->$rendermethod($widget);
}
View
220 lib/yuilib/gallery/gallery-sm-menu-base/gallery-sm-menu-base-debug.js
@@ -0,0 +1,220 @@
+YUI.add('gallery-sm-menu-base', function (Y, NAME) {
+
+/*jshint expr:true, onevar:false */
+
+/**
+Provides `Menu.Base`.
+
+@module gallery-sm-menu
+@submodule gallery-sm-menu-base
+**/
+
+/**
+Base menu functionality.
+
+@class Menu.Base
+@constructor
+@param {Object} [config] Config options.
+ @param {Menu.Item[]|Object[]} [config.items] Array of `Menu.Item` instances
+ or menu item config objects to add to this menu.
+@extends Tree
+**/
+
+/**
+Fired when a menu item is disabled.
+
+@event disable
+@param {Menu.Item} item Menu item that was disabled.
+@preventable _defDisableFn
+**/
+var EVT_DISABLE = 'disable';
+
+/**
+Fired when a menu item is enabled.
+
+@event enable
+@param {Menu.Item} item Menu item that was enabled.
+@preventable _defEnableFn
+**/
+var EVT_ENABLE = 'enable';
+
+/**
+Fired when a menu item is hidden.
+
+@event hide
+@param {Menu.Item} item Menu item that was hidden.
+@preventable _defHideFn
+**/
+var EVT_HIDE = 'hide';
+
+/**
+Fired when a menu item is shown.
+
+@event show
+@param {Menu.Item} item Menu item that was shown.
+@preventable _defShowFn
+**/
+var EVT_SHOW = 'show';
+
+var MenuBase = Y.Base.create('menuBase', Y.Tree, [Y.Tree.Labelable, Y.Tree.Openable], {
+ nodeClass: Y.Menu.Item,
+
+ // -- Lifecycle ------------------------------------------------------------
+ initializer: function (config) {
+ if (config) {
+ config.nodes = config.items;
+ }
+ },
+
+ // -- Public Methods -------------------------------------------------------
+
+ /**
+ Closes all open submenus of this menu.
+
+ @method closeSubMenus
+ @chainable
+ **/
+ closeSubMenus: function () {
+ // Close all open submenus.
+ Y.Object.each(this._openMenus, function (item) {
+ item.close();
+ }, this);
+
+ return this;
+ },
+
+ /**
+ Disables the specified menu item.
+
+ @method disableItem
+ @param {Menu.Item} item Menu item to disable.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `disable` event
+ will be suppressed.
+ @chainable
+ **/
+ disableItem: function (item, options) {
+ if (!item.isDisabled()) {
+ this._fireTreeEvent(EVT_DISABLE, {item: item}, {
+ defaultFn: this._defDisableFn,
+ silent : options && options.silent
+ });
+ }
+
+ return this;
+ },
+
+ /**
+ Enables the specified menu item.
+
+ @method enableItem
+ @param {Menu.Item} item Menu item to enable.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `enable` event
+ will be suppressed.
+ @chainable
+ **/
+ enableItem: function (item, options) {
+ if (item.isDisabled()) {
+ this._fireTreeEvent(EVT_ENABLE, {item: item}, {
+ defaultFn: this._defEnableFn,
+ silent : options && options.silent
+ });
+ }
+
+ return this;
+ },
+
+ /**
+ Hides the specified menu item.
+
+ @method hideItem
+ @param {Menu.Item} item Menu item to hide.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `hide` event
+ will be suppressed.
+ @chainable
+ **/
+ hideItem: function (item, options) {
+ if (!item.isHidden()) {
+ this._fireTreeEvent(EVT_HIDE, {item: item}, {
+ defaultFn: this._defHideFn,
+ silent : options && options.silent
+ });
+ }
+
+ return this;
+ },
+
+ /**
+ Shows the specified menu item.
+
+ @method showItem
+ @param {Menu.Item} item Menu item to show.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `show` event
+ will be suppressed.
+ @chainable
+ **/
+ showItem: function (item, options) {
+ if (item.isHidden()) {
+ this._fireTreeEvent(EVT_SHOW, {item: item}, {
+ defaultFn: this._defShowFn,
+ silent : options && options.silent
+ });
+ }
+
+ return this;
+ },
+
+ // -- Default Event Handlers -----------------------------------------------
+
+ /**
+ Default handler for the `disable` event.
+
+ @method _defDisableFn
+ @param {EventFacade} e
+ @protected
+ **/
+ _defDisableFn: function (e) {
+ e.item.state.disabled = true;
+ },
+
+ /**
+ Default handler for the `enable` event.
+
+ @method _defEnableFn
+ @param {EventFacade} e
+ @protected
+ **/
+ _defEnableFn: function (e) {
+ delete e.item.state.disabled;
+ },
+
+ /**
+ Default handler for the `hide` event.
+
+ @method _defHideFn
+ @param {EventFacade} e
+ @protected
+ **/
+ _defHideFn: function (e) {
+ e.item.state.hidden = true;
+ },
+
+ /**
+ Default handler for the `show` event.
+
+ @method _defShowFn
+ @param {EventFacade} e
+ @protected
+ **/
+ _defShowFn: function (e) {
+ delete e.item.state.hidden;
+ }
+});
+
+Y.namespace('Menu').Base = MenuBase;
+
+
+}, '@VERSION@', {"requires": ["gallery-sm-menu-item", "tree-labelable", "tree-openable"]});
View
1  lib/yuilib/gallery/gallery-sm-menu-base/gallery-sm-menu-base-min.js
@@ -0,0 +1 @@
+YUI.add("gallery-sm-menu-base",function(e,t){var n="disable",r="enable",i="hide",s="show",o=e.Base.create("menuBase",e.Tree,[e.Tree.Labelable,e.Tree.Openable],{nodeClass:e.Menu.Item,initializer:function(e){e&&(e.nodes=e.items)},closeSubMenus:function(){return e.Object.each(this._openMenus,function(e){e.close()},this),this},disableItem:function(e,t){return e.isDisabled()||this._fireTreeEvent(n,{item:e},{defaultFn:this._defDisableFn,silent:t&&t.silent}),this},enableItem:function(e,t){return e.isDisabled()&&this._fireTreeEvent(r,{item:e},{defaultFn:this._defEnableFn,silent:t&&t.silent}),this},hideItem:function(e,t){return e.isHidden()||this._fireTreeEvent(i,{item:e},{defaultFn:this._defHideFn,silent:t&&t.silent}),this},showItem:function(e,t){return e.isHidden()&&this._fireTreeEvent(s,{item:e},{defaultFn:this._defShowFn,silent:t&&t.silent}),this},_defDisableFn:function(e){e.item.state.disabled=!0},_defEnableFn:function(e){delete e.item.state.disabled},_defHideFn:function(e){e.item.state.hidden=!0},_defShowFn:function(e){delete e.item.state.hidden}});e.namespace("Menu").Base=o},"@VERSION@",{requires:["gallery-sm-menu-item","tree-labelable","tree-openable"]});
View
220 lib/yuilib/gallery/gallery-sm-menu-base/gallery-sm-menu-base.js
@@ -0,0 +1,220 @@
+YUI.add('gallery-sm-menu-base', function (Y, NAME) {
+
+/*jshint expr:true, onevar:false */
+
+/**
+Provides `Menu.Base`.
+
+@module gallery-sm-menu
+@submodule gallery-sm-menu-base
+**/
+
+/**
+Base menu functionality.
+
+@class Menu.Base
+@constructor
+@param {Object} [config] Config options.
+ @param {Menu.Item[]|Object[]} [config.items] Array of `Menu.Item` instances
+ or menu item config objects to add to this menu.
+@extends Tree
+**/
+
+/**
+Fired when a menu item is disabled.
+
+@event disable
+@param {Menu.Item} item Menu item that was disabled.
+@preventable _defDisableFn
+**/
+var EVT_DISABLE = 'disable';
+
+/**
+Fired when a menu item is enabled.
+
+@event enable
+@param {Menu.Item} item Menu item that was enabled.
+@preventable _defEnableFn
+**/
+var EVT_ENABLE = 'enable';
+
+/**
+Fired when a menu item is hidden.
+
+@event hide
+@param {Menu.Item} item Menu item that was hidden.
+@preventable _defHideFn
+**/
+var EVT_HIDE = 'hide';
+
+/**
+Fired when a menu item is shown.
+
+@event show
+@param {Menu.Item} item Menu item that was shown.
+@preventable _defShowFn
+**/
+var EVT_SHOW = 'show';
+
+var MenuBase = Y.Base.create('menuBase', Y.Tree, [Y.Tree.Labelable, Y.Tree.Openable], {
+ nodeClass: Y.Menu.Item,
+
+ // -- Lifecycle ------------------------------------------------------------
+ initializer: function (config) {
+ if (config) {
+ config.nodes = config.items;
+ }
+ },
+
+ // -- Public Methods -------------------------------------------------------
+
+ /**
+ Closes all open submenus of this menu.
+
+ @method closeSubMenus
+ @chainable
+ **/
+ closeSubMenus: function () {
+ // Close all open submenus.
+ Y.Object.each(this._openMenus, function (item) {
+ item.close();
+ }, this);
+
+ return this;
+ },
+
+ /**
+ Disables the specified menu item.
+
+ @method disableItem
+ @param {Menu.Item} item Menu item to disable.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `disable` event
+ will be suppressed.
+ @chainable
+ **/
+ disableItem: function (item, options) {
+ if (!item.isDisabled()) {
+ this._fireTreeEvent(EVT_DISABLE, {item: item}, {
+ defaultFn: this._defDisableFn,
+ silent : options && options.silent
+ });
+ }
+
+ return this;
+ },
+
+ /**
+ Enables the specified menu item.
+
+ @method enableItem
+ @param {Menu.Item} item Menu item to enable.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `enable` event
+ will be suppressed.
+ @chainable
+ **/
+ enableItem: function (item, options) {
+ if (item.isDisabled()) {
+ this._fireTreeEvent(EVT_ENABLE, {item: item}, {
+ defaultFn: this._defEnableFn,
+ silent : options && options.silent
+ });
+ }
+
+ return this;
+ },
+
+ /**
+ Hides the specified menu item.
+
+ @method hideItem
+ @param {Menu.Item} item Menu item to hide.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `hide` event
+ will be suppressed.
+ @chainable
+ **/
+ hideItem: function (item, options) {
+ if (!item.isHidden()) {
+ this._fireTreeEvent(EVT_HIDE, {item: item}, {
+ defaultFn: this._defHideFn,
+ silent : options && options.silent
+ });
+ }
+
+ return this;
+ },
+
+ /**
+ Shows the specified menu item.
+
+ @method showItem
+ @param {Menu.Item} item Menu item to show.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `show` event
+ will be suppressed.
+ @chainable
+ **/
+ showItem: function (item, options) {
+ if (item.isHidden()) {
+ this._fireTreeEvent(EVT_SHOW, {item: item}, {
+ defaultFn: this._defShowFn,
+ silent : options && options.silent
+ });
+ }
+
+ return this;
+ },
+
+ // -- Default Event Handlers -----------------------------------------------
+
+ /**
+ Default handler for the `disable` event.
+
+ @method _defDisableFn
+ @param {EventFacade} e
+ @protected
+ **/
+ _defDisableFn: function (e) {
+ e.item.state.disabled = true;
+ },
+
+ /**
+ Default handler for the `enable` event.
+
+ @method _defEnableFn
+ @param {EventFacade} e
+ @protected
+ **/
+ _defEnableFn: function (e) {
+ delete e.item.state.disabled;
+ },
+
+ /**
+ Default handler for the `hide` event.
+
+ @method _defHideFn
+ @param {EventFacade} e
+ @protected
+ **/
+ _defHideFn: function (e) {
+ e.item.state.hidden = true;
+ },
+
+ /**
+ Default handler for the `show` event.
+
+ @method _defShowFn
+ @param {EventFacade} e
+ @protected
+ **/
+ _defShowFn: function (e) {
+ delete e.item.state.hidden;
+ }
+});
+
+Y.namespace('Menu').Base = MenuBase;
+
+
+}, '@VERSION@', {"requires": ["gallery-sm-menu-item", "tree-labelable", "tree-openable"]});
View
137 lib/yuilib/gallery/gallery-sm-menu-item/gallery-sm-menu-item-debug.js
@@ -0,0 +1,137 @@
+YUI.add('gallery-sm-menu-item', function (Y, NAME) {
+
+/*jshint expr:true, onevar:false */
+
+/**
+Provides the `Menu.Item` class.
+
+@module gallery-sm-menu
+@submodule gallery-sm-menu-item
+**/
+
+/**
+Represents a single menu item in a `Menu`.
+
+@class Menu.Item
+@constructor
+@param {Menu} menu `Menu` instance with which this node should be associated.
+@param {Object} [config] Configuration hash for this menu item. Supports all the
+ config properties of `Tree.Node` in addition to the following.
+
+ @param {Object} [config.state] State hash for this menu item.
+
+ @param {Boolean} [config.state.disabled=false] If `true`, this menu item
+ will be disabled, and will not be clickable or selectable.
+
+ @param {Boolean} [config.state.hidden=false] If `true`, this menu item
+ will be hidden.
+
+ @param {String} [config.type='item'] Type of this menu item. May be 'item',
+ 'heading', or 'separator'.
+
+ @param {String} [config.url='#'] URL associated with this item. If this item
+ is of type 'item', clicking on the item will navigate to this URL.
+
+@extends Tree.Node
+**/
+
+function MenuItem(menu, config) {
+ config || (config = {});
+
+ this.id = this._yuid = config.id || Y.guid('menuItem-');
+ this.type = config.type || 'item';
+ this.url = config.url || '#';
+
+ MenuItem.superclass.constructor.call(this, menu, config);
+}
+
+Y.extend(MenuItem, Y.Tree.Node, {
+ _serializable: Y.Tree.Node.prototype._serializable.concat('type', 'url'),
+
+ /**
+ Disables this menu item. Disabled items are not clickable or selectable.
+
+ @method disable
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `disable` event
+ will be suppressed.
+ @chainable
+ **/
+ disable: function (options) {
+ this.tree.disableItem(this, options);
+ return this;
+ },
+
+ /**
+ Enables this menu item.
+
+ @method enable
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `enable` event
+ will be suppressed.
+ @chainable
+ **/
+ enable: function (options) {
+ this.tree.enableItem(this, options);
+ return this;
+ },
+
+ /**
+ Hides this menu item.
+
+ @method hide
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `hide` event
+ will be suppressed.
+ @chainable
+ **/
+ hide: function (options) {
+ this.tree.hideItem(this, options);
+ return this;
+ },
+
+ /**
+ Returns `true` if this menu item or one of its ancestors is currently
+ disabled.
+
+ @method isDisabled
+ @return {Boolean} `true` if this menu item or one of its ancestors is
+ currently disabled, `false` otherwise.
+ **/
+ isDisabled: function () {
+ return !!this.state.disabled ||
+ (this.parent ? this.parent.isDisabled() : false);
+ },
+
+ /**
+ Returns `true` if this menu item or one of its ancestors is currently
+ hidden.
+
+ @method isHidden
+ @return {Boolean} `true` if this menu item or one of its ancestors is
+ currently hidden, `false` otherwise.
+ **/
+ isHidden: function () {
+ return !!this.state.hidden ||
+ (this.parent ? this.parent.isHidden() : false);
+ },
+
+ /**
+ Shows this menu item.
+
+ @method show
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `show` event
+ will be suppressed.
+ @chainable
+ **/
+ show: function (options) {
+ this.tree.showItem(this, options);
+ return this;
+ }
+});
+
+Y.namespace('Menu').Item = MenuItem;
+
+
+}, '@VERSION@', {"requires": ["tree-node", "oop"]});
View
1  lib/yuilib/gallery/gallery-sm-menu-item/gallery-sm-menu-item-min.js
@@ -0,0 +1 @@
+YUI.add("gallery-sm-menu-item",function(e,t){function n(t,r){r||(r={}),this.id=this._yuid=r.id||e.guid("menuItem-"),this.type=r.type||"item",this.url=r.url||"#",n.superclass.constructor.call(this,t,r)}e.extend(n,e.Tree.Node,{_serializable:e.Tree.Node.prototype._serializable.concat("type","url"),disable:function(e){return this.tree.disableItem(this,e),this},enable:function(e){return this.tree.enableItem(this,e),this},hide:function(e){return this.tree.hideItem(this,e),this},isDisabled:function(){return!!this.state.disabled||(this.parent?this.parent.isDisabled():!1)},isHidden:function(){return!!this.state.hidden||(this.parent?this.parent.isHidden():!1)},show:function(e){return this.tree.showItem(this,e),this}}),e.namespace("Menu").Item=n},"@VERSION@",{requires:["tree-node","oop"]});
View
137 lib/yuilib/gallery/gallery-sm-menu-item/gallery-sm-menu-item.js
@@ -0,0 +1,137 @@
+YUI.add('gallery-sm-menu-item', function (Y, NAME) {
+
+/*jshint expr:true, onevar:false */
+
+/**
+Provides the `Menu.Item` class.
+
+@module gallery-sm-menu
+@submodule gallery-sm-menu-item
+**/
+
+/**
+Represents a single menu item in a `Menu`.
+
+@class Menu.Item
+@constructor
+@param {Menu} menu `Menu` instance with which this node should be associated.
+@param {Object} [config] Configuration hash for this menu item. Supports all the
+ config properties of `Tree.Node` in addition to the following.
+
+ @param {Object} [config.state] State hash for this menu item.
+
+ @param {Boolean} [config.state.disabled=false] If `true`, this menu item
+ will be disabled, and will not be clickable or selectable.
+
+ @param {Boolean} [config.state.hidden=false] If `true`, this menu item
+ will be hidden.
+
+ @param {String} [config.type='item'] Type of this menu item. May be 'item',
+ 'heading', or 'separator'.
+
+ @param {String} [config.url='#'] URL associated with this item. If this item
+ is of type 'item', clicking on the item will navigate to this URL.
+
+@extends Tree.Node
+**/
+
+function MenuItem(menu, config) {
+ config || (config = {});
+
+ this.id = this._yuid = config.id || Y.guid('menuItem-');
+ this.type = config.type || 'item';
+ this.url = config.url || '#';
+
+ MenuItem.superclass.constructor.call(this, menu, config);
+}
+
+Y.extend(MenuItem, Y.Tree.Node, {
+ _serializable: Y.Tree.Node.prototype._serializable.concat('type', 'url'),
+
+ /**
+ Disables this menu item. Disabled items are not clickable or selectable.
+
+ @method disable
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `disable` event
+ will be suppressed.
+ @chainable
+ **/
+ disable: function (options) {
+ this.tree.disableItem(this, options);
+ return this;
+ },
+
+ /**
+ Enables this menu item.
+
+ @method enable
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `enable` event
+ will be suppressed.
+ @chainable
+ **/
+ enable: function (options) {
+ this.tree.enableItem(this, options);
+ return this;
+ },
+
+ /**
+ Hides this menu item.
+
+ @method hide
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `hide` event
+ will be suppressed.
+ @chainable
+ **/
+ hide: function (options) {
+ this.tree.hideItem(this, options);
+ return this;
+ },
+
+ /**
+ Returns `true` if this menu item or one of its ancestors is currently
+ disabled.
+
+ @method isDisabled
+ @return {Boolean} `true` if this menu item or one of its ancestors is
+ currently disabled, `false` otherwise.
+ **/
+ isDisabled: function () {
+ return !!this.state.disabled ||
+ (this.parent ? this.parent.isDisabled() : false);
+ },
+
+ /**
+ Returns `true` if this menu item or one of its ancestors is currently
+ hidden.
+
+ @method isHidden
+ @return {Boolean} `true` if this menu item or one of its ancestors is
+ currently hidden, `false` otherwise.
+ **/
+ isHidden: function () {
+ return !!this.state.hidden ||
+ (this.parent ? this.parent.isHidden() : false);
+ },
+
+ /**
+ Shows this menu item.
+
+ @method show
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `show` event
+ will be suppressed.
+ @chainable
+ **/
+ show: function (options) {
+ this.tree.showItem(this, options);
+ return this;
+ }
+});
+
+Y.namespace('Menu').Item = MenuItem;
+
+
+}, '@VERSION@', {"requires": ["tree-node", "oop"]});
View
222 lib/yuilib/gallery/gallery-sm-menu-plugin/gallery-sm-menu-plugin-debug.js
@@ -0,0 +1,222 @@
+YUI.add('gallery-sm-menu-plugin', function (Y, NAME) {
+
+/**
+Provides the `Y.Plugin.Menu` Node plugin.
+
+@module gallery-sm-menu
+@submodule gallery-sm-menu-plugin
+**/
+
+/**
+Node plugin that toggles a dropdown menu when the host node is clicked.
+
+### Example
+
+ YUI().use('menu-plugin', function (Y) {
+ var button = Y.one('#button');
+
+ // Plug a dropdown menu into the button.
+ button.plug(Y.Plugin.Menu, {
+ items: [
+ {label: 'Item One'},
+ {label: 'Item Two'},
+ {label: 'Item Three'}
+ ]
+ });
+
+ // The menu will automatically be displayed whenever the button is
+ // clicked, but you can also toggle it manually.
+ button.menu.toggleVisible();
+ });
+
+@class Plugin.Menu
+@constructor
+@extends Menu
+@uses Plugin.Base
+**/
+
+Y.namespace('Plugin').Menu = Y.Base.create('menuPlugin', Y.Menu, [Y.Plugin.Base], {
+ // -- Lifecycle Methods ----------------------------------------------------
+ initializer: function (config) {
+ this._host = config.host;
+ this._hostIsBody = this._host === Y.one('body');
+
+ this._attachMenuPluginEvents();
+ },
+
+ destructor: function () {
+ clearTimeout(this._pluginHideTimeout);
+ },
+
+ // -- Public Methods -------------------------------------------------------
+
+ /**
+ Repositions this menu so that it is anchored to a specified node, region, or
+ set of pixel coordinates.
+
+ The menu will be displayed at the most advantageous position relative to the
+ anchor point to ensure that as much of the menu as possible is visible
+ within the viewport.
+
+ If no anchor point is specified, the menu will be positioned relative to its
+ host node.
+
+ @method reposition
+ @param {Node|Number[]|Object} [anchorPoint] Anchor point at which this menu
+ should be positioned. The point may be specified as a `Y.Node`
+ reference, a region object, or an array of X and Y pixel coordinates.
+ @chainable
+ **/
+ reposition: function (anchorPoint) {
+ return Y.Menu.prototype.reposition.call(this, anchorPoint || this._host);
+ },
+
+ // -- Protected Methods ----------------------------------------------------
+ _attachMenuPluginEvents: function () {
+ // Events added to this._menuEvents will be cleaned up by Y.Menu.
+
+ if (this.get('showOnClick')) {
+ this.afterHostEvent('click', this._afterHostClick);
+ }
+
+ if (this.get('showOnContext')) {
+ // If the host node is the <body> element, we need to listen on the
+ // document.
+ if (this._hostIsBody) {
+ this._menuEvents.push(Y.one('doc').on('contextmenu', this._onHostContext, this));
+ } else {
+ this.onHostEvent('contextmenu', this._onHostContext);
+ }
+ }
+
+ if (this.get('showOnHover')) {
+ this.afterHostEvent({
+ blur : this._afterHostBlur,
+ focus : this._afterHostFocus,
+ mouseenter: this._afterHostMouseEnter,
+ mouseleave: this._afterHostMouseLeave
+ });
+ }
+ },
+
+ /**
+ Returns an efficient test function that can be passed to `Y.Node#ancestor()`
+ to test whether a node is this menu's container or its plugin host.
+
+ This is broken out to make overriding easier in subclasses.
+
+ @method _getAncestorTestFn
+ @return {Function} Test function.
+ @protected
+ **/
+ _getAncestorTestFn: function () {
+ var container = this.get('container'),
+ host = this._host;
+
+ return function (node) {
+ return node === container || node === host;
+ };
+ },
+
+ // -- Protected Event Handlers ---------------------------------------------
+ _afterHostBlur: function () {
+ this.hide();
+ },
+
+ _afterHostClick: function () {
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.toggleVisible({anchorPoint: this._host});
+ },
+
+ _afterHostFocus: function () {
+ clearTimeout(this._timeouts.menu);
+
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.show({anchorPoint: this._host});
+ },
+
+ _afterHostMouseEnter: function () {
+ clearTimeout(this._timeouts.menu);
+
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.show({anchorPoint: this._host});
+ },
+
+ _afterHostMouseLeave: function () {
+ var self = this;
+
+ this._timeouts.menu = setTimeout(function () {
+ self.hide();
+ }, 300);
+ },
+
+ _onHostContext: function (e) {
+ e.preventDefault();
+
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.show({anchorPoint: [e.clientX, e.clientY]});
+ }
+}, {
+ NS: 'menu',
+
+ ATTRS: {
+ /**
+ If `true`, this menu will be shown when the host node is clicked with
+ the left mouse button or (in the case of `<button>`, `<input>`, and
+ `<a>` elements) activated with the Return key.
+
+ @attribute {Boolean} showOnClick
+ @default true
+ @initOnly
+ **/
+ showOnClick: {
+ value: true,
+ writeOnce: 'initOnly'
+ },
+
+ /**
+ If `true`, this menu will be shown when the host node's `contextmenu`
+ event occurs, which happens when the user takes an action that would
+ normally display the browser's context menu (such as right-clicking).
+
+ When `true`, the browser's default context menu will be prevented from
+ appearing.
+
+ @attribute {Boolean} showOnContext
+ @default false
+ @initOnly
+ **/
+ showOnContext: {
+ value: false,
+ writeOnce: 'initOnly'
+ },
+
+ /**
+ If `true`, this menu will be shown when the host node is hovered or
+ receives focus instead of only being shown when it's clicked.
+
+ @attribute {Boolean} showOnHover
+ @default false
+ @initOnly
+ **/
+ showOnHover: {
+ value: false,
+ writeOnce: 'initOnly'
+ }
+ }
+});
+
+
+}, '@VERSION@', {"requires": ["event-focus", "gallery-sm-menu", "node-pluginhost", "plugin"]});
View
1  lib/yuilib/gallery/gallery-sm-menu-plugin/gallery-sm-menu-plugin-min.js
@@ -0,0 +1 @@
+YUI.add("gallery-sm-menu-plugin",function(e,t){e.namespace("Plugin").Menu=e.Base.create("menuPlugin",e.Menu,[e.Plugin.Base],{initializer:function(t){this._host=t.host,this._hostIsBody=this._host===e.one("body"),this._attachMenuPluginEvents()},destructor:function(){clearTimeout(this._pluginHideTimeout)},reposition:function(t){return e.Menu.prototype.reposition.call(this,t||this._host)},_attachMenuPluginEvents:function(){this.get("showOnClick")&&this.afterHostEvent("click",this._afterHostClick),this.get("showOnContext")&&(this._hostIsBody?this._menuEvents.push(e.one("doc").on("contextmenu",this._onHostContext,this)):this.onHostEvent("contextmenu",this._onHostContext)),this.get("showOnHover")&&this.afterHostEvent({blur:this._afterHostBlur,focus:this._afterHostFocus,mouseenter:this._afterHostMouseEnter,mouseleave:this._afterHostMouseLeave})},_getAncestorTestFn:function(){var e=this.get("container"),t=this._host;return function(n){return n===e||n===t}},_afterHostBlur:function(){this.hide()},_afterHostClick:function(){this.rendered||this.render(),this.toggleVisible({anchorPoint:this._host})},_afterHostFocus:function(){clearTimeout(this._timeouts.menu),this.rendered||this.render(),this.show({anchorPoint:this._host})},_afterHostMouseEnter:function(){clearTimeout(this._timeouts.menu),this.rendered||this.render(),this.show({anchorPoint:this._host})},_afterHostMouseLeave:function(){var e=this;this._timeouts.menu=setTimeout(function(){e.hide()},300)},_onHostContext:function(e){e.preventDefault(),this.rendered||this.render(),this.show({anchorPoint:[e.clientX,e.clientY]})}},{NS:"menu",ATTRS:{showOnClick:{value:!0,writeOnce:"initOnly"},showOnContext:{value:!1,writeOnce:"initOnly"},showOnHover:{value:!1,writeOnce:"initOnly"}}})},"@VERSION@",{requires:["event-focus","gallery-sm-menu","node-pluginhost","plugin"]});
View
222 lib/yuilib/gallery/gallery-sm-menu-plugin/gallery-sm-menu-plugin.js
@@ -0,0 +1,222 @@
+YUI.add('gallery-sm-menu-plugin', function (Y, NAME) {
+
+/**
+Provides the `Y.Plugin.Menu` Node plugin.
+
+@module gallery-sm-menu
+@submodule gallery-sm-menu-plugin
+**/
+
+/**
+Node plugin that toggles a dropdown menu when the host node is clicked.
+
+### Example
+
+ YUI().use('menu-plugin', function (Y) {
+ var button = Y.one('#button');
+
+ // Plug a dropdown menu into the button.
+ button.plug(Y.Plugin.Menu, {
+ items: [
+ {label: 'Item One'},
+ {label: 'Item Two'},
+ {label: 'Item Three'}
+ ]
+ });
+
+ // The menu will automatically be displayed whenever the button is
+ // clicked, but you can also toggle it manually.
+ button.menu.toggleVisible();
+ });
+
+@class Plugin.Menu
+@constructor
+@extends Menu
+@uses Plugin.Base
+**/
+
+Y.namespace('Plugin').Menu = Y.Base.create('menuPlugin', Y.Menu, [Y.Plugin.Base], {
+ // -- Lifecycle Methods ----------------------------------------------------
+ initializer: function (config) {
+ this._host = config.host;
+ this._hostIsBody = this._host === Y.one('body');
+
+ this._attachMenuPluginEvents();
+ },
+
+ destructor: function () {
+ clearTimeout(this._pluginHideTimeout);
+ },
+
+ // -- Public Methods -------------------------------------------------------
+
+ /**
+ Repositions this menu so that it is anchored to a specified node, region, or
+ set of pixel coordinates.
+
+ The menu will be displayed at the most advantageous position relative to the
+ anchor point to ensure that as much of the menu as possible is visible
+ within the viewport.
+
+ If no anchor point is specified, the menu will be positioned relative to its
+ host node.
+
+ @method reposition
+ @param {Node|Number[]|Object} [anchorPoint] Anchor point at which this menu
+ should be positioned. The point may be specified as a `Y.Node`
+ reference, a region object, or an array of X and Y pixel coordinates.
+ @chainable
+ **/
+ reposition: function (anchorPoint) {
+ return Y.Menu.prototype.reposition.call(this, anchorPoint || this._host);
+ },
+
+ // -- Protected Methods ----------------------------------------------------
+ _attachMenuPluginEvents: function () {
+ // Events added to this._menuEvents will be cleaned up by Y.Menu.
+
+ if (this.get('showOnClick')) {
+ this.afterHostEvent('click', this._afterHostClick);
+ }
+
+ if (this.get('showOnContext')) {
+ // If the host node is the <body> element, we need to listen on the
+ // document.
+ if (this._hostIsBody) {
+ this._menuEvents.push(Y.one('doc').on('contextmenu', this._onHostContext, this));
+ } else {
+ this.onHostEvent('contextmenu', this._onHostContext);
+ }
+ }
+
+ if (this.get('showOnHover')) {
+ this.afterHostEvent({
+ blur : this._afterHostBlur,
+ focus : this._afterHostFocus,
+ mouseenter: this._afterHostMouseEnter,
+ mouseleave: this._afterHostMouseLeave
+ });
+ }
+ },
+
+ /**
+ Returns an efficient test function that can be passed to `Y.Node#ancestor()`
+ to test whether a node is this menu's container or its plugin host.
+
+ This is broken out to make overriding easier in subclasses.
+
+ @method _getAncestorTestFn
+ @return {Function} Test function.
+ @protected
+ **/
+ _getAncestorTestFn: function () {
+ var container = this.get('container'),
+ host = this._host;
+
+ return function (node) {
+ return node === container || node === host;
+ };
+ },
+
+ // -- Protected Event Handlers ---------------------------------------------
+ _afterHostBlur: function () {
+ this.hide();
+ },
+
+ _afterHostClick: function () {
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.toggleVisible({anchorPoint: this._host});
+ },
+
+ _afterHostFocus: function () {
+ clearTimeout(this._timeouts.menu);
+
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.show({anchorPoint: this._host});
+ },
+
+ _afterHostMouseEnter: function () {
+ clearTimeout(this._timeouts.menu);
+
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.show({anchorPoint: this._host});
+ },
+
+ _afterHostMouseLeave: function () {
+ var self = this;
+
+ this._timeouts.menu = setTimeout(function () {
+ self.hide();
+ }, 300);
+ },
+
+ _onHostContext: function (e) {
+ e.preventDefault();
+
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.show({anchorPoint: [e.clientX, e.clientY]});
+ }
+}, {
+ NS: 'menu',
+
+ ATTRS: {
+ /**
+ If `true`, this menu will be shown when the host node is clicked with
+ the left mouse button or (in the case of `<button>`, `<input>`, and
+ `<a>` elements) activated with the Return key.
+
+ @attribute {Boolean} showOnClick
+ @default true
+ @initOnly
+ **/
+ showOnClick: {
+ value: true,
+ writeOnce: 'initOnly'
+ },
+
+ /**
+ If `true`, this menu will be shown when the host node's `contextmenu`
+ event occurs, which happens when the user takes an action that would
+ normally display the browser's context menu (such as right-clicking).
+
+ When `true`, the browser's default context menu will be prevented from
+ appearing.
+
+ @attribute {Boolean} showOnContext
+ @default false
+ @initOnly
+ **/
+ showOnContext: {
+ value: false,
+ writeOnce: 'initOnly'
+ },
+
+ /**
+ If `true`, this menu will be shown when the host node is hovered or
+ receives focus instead of only being shown when it's clicked.
+
+ @attribute {Boolean} showOnHover
+ @default false
+ @initOnly
+ **/
+ showOnHover: {
+ value: false,
+ writeOnce: 'initOnly'
+ }
+ }
+});
+
+
+}, '@VERSION@', {"requires": ["event-focus", "gallery-sm-menu", "node-pluginhost", "plugin"]});
View
49 lib/yuilib/gallery/gallery-sm-menu-templates/gallery-sm-menu-templates-debug.js
@@ -0,0 +1,49 @@
+YUI.add('gallery-sm-menu-templates', function (Y, NAME) {
+
+/**
+Provides templates for `Menu`.
+
+@module gallery-sm-menu
+@submodule gallery-sm-menu-templates
+**/
+
+/**
+Templates for `Menu`.
+
+@class Menu.Templates
+**/
+
+var Micro = Y.Template.Micro;
+
+Y.namespace('Menu').Templates = {
+ children: Micro.compile(
+ '<ul class="<%= data.classNames.children %>"></ul>'
+ ),
+
+ item: Micro.compile(
+ '<% switch (data.item.type) { %>' +
+ '<% case "item": %>' +
+ '<li id="<%= data.item.id %>" class="<%= data.classNames.item %>">' +
+ '<a href="<%= data.item.url %>" class="<%= data.classNames.label %>" data-item-id="<%= data.item.id %>"' +
+ '<% if (data.item.title) { %>' +
+ ' title="<%= data.item.title %>"' +
+ '<% } %>' +
+ '></a>' +
+ '</li>' +
+ '<% break; %>' +
+
+ '<% case "heading": %>' +
+ '<li class="<%= data.classNames.heading %>">' +
+ '<span class="<%= data.classNames.label %>"></span>' +
+ '</li>' +
+ '<% break; %>' +
+
+ '<% case "separator": %>' +
+ '<li class="<%= data.classNames.separator %>"></li>' +
+ '<% break; %>' +
+ '<% } %>'
+ )
+};
+
+
+}, '@VERSION@', {"requires": ["template-micro"]});
View
1  lib/yuilib/gallery/gallery-sm-menu-templates/gallery-sm-menu-templates-min.js
@@ -0,0 +1 @@
+YUI.add("gallery-sm-menu-templates",function(e,t){var n=e.Template.Micro;e.namespace("Menu").Templates={children:n.compile('<ul class="<%= data.classNames.children %>"></ul>'),item:n.compile('<% switch (data.item.type) { %><% case "item": %><li id="<%= data.item.id %>" class="<%= data.classNames.item %>"><a href="<%= data.item.url %>" class="<%= data.classNames.label %>" data-item-id="<%= data.item.id %>"<% if (data.item.title) { %> title="<%= data.item.title %>"<% } %>></a></li><% break; %><% case "heading": %><li class="<%= data.classNames.heading %>"><span class="<%= data.classNames.label %>"></span></li><% break; %><% case "separator": %><li class="<%= data.classNames.separator %>"></li><% break; %><% } %>')}},"@VERSION@",{requires:["template-micro"]});
View
49 lib/yuilib/gallery/gallery-sm-menu-templates/gallery-sm-menu-templates.js
@@ -0,0 +1,49 @@
+YUI.add('gallery-sm-menu-templates', function (Y, NAME) {
+
+/**
+Provides templates for `Menu`.
+
+@module gallery-sm-menu
+@submodule gallery-sm-menu-templates
+**/
+
+/**
+Templates for `Menu`.
+
+@class Menu.Templates
+**/
+
+var Micro = Y.Template.Micro;
+
+Y.namespace('Menu').Templates = {
+ children: Micro.compile(
+ '<ul class="<%= data.classNames.children %>"></ul>'
+ ),
+
+ item: Micro.compile(
+ '<% switch (data.item.type) { %>' +
+ '<% case "item": %>' +
+ '<li id="<%= data.item.id %>" class="<%= data.classNames.item %>">' +
+ '<a href="<%= data.item.url %>" class="<%= data.classNames.label %>" data-item-id="<%= data.item.id %>"' +
+ '<% if (data.item.title) { %>' +
+ ' title="<%= data.item.title %>"' +
+ '<% } %>' +
+ '></a>' +
+ '</li>' +
+ '<% break; %>' +
+
+ '<% case "heading": %>' +
+ '<li class="<%= data.classNames.heading %>">' +
+ '<span class="<%= data.classNames.label %>"></span>' +
+ '</li>' +
+ '<% break; %>' +
+
+ '<% case "separator": %>' +
+ '<li class="<%= data.classNames.separator %>"></li>' +
+ '<% break; %>' +
+ '<% } %>'
+ )
+};
+
+
+}, '@VERSION@', {"requires": ["template-micro"]});
View
63 lib/yuilib/gallery/gallery-sm-menu/assets/gallery-sm-menu-core.css
@@ -0,0 +1,63 @@
+.yui3-menu,
+.yui3-menu-children {
+ left: -10000px;
+ position: absolute;
+ top: -10000px;
+ visibility: hidden;
+}
+
+.yui3-menu.yui3-menu-open {
+ left: auto;
+ top: auto;
+ visibility: visible;
+ z-index: 2;
+}
+
+.yui3-menu-children {
+ left: -10000px;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ top: -10000px;
+ z-index: 1;
+}
+
+.yui3-menu > .yui3-menu-children { position: relative; }
+
+.yui3-menu-open > .yui3-menu-children {
+ left: 0;
+ top: 0;
+ visibility: visible;
+}
+
+.yui3-menu-item { position: relative; }
+
+.yui3-menu-label {
+ display: block;
+ color: inherit;
+ line-height: 1.5;
+ padding: 0 20px;
+ text-decoration: none;
+ white-space: nowrap;
+}
+
+a.yui3-menu-label { padding-right: 30px; }
+
+.yui3-menu-can-have-children > .yui3-menu-label:after {
+ content: '\25B8';
+ float: right;
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'DejaVu Sans', sans-serif; /* These specific fonts have the Unicode char we need. */
+ margin-right: -20px;
+ margin-top: -1px;
+}
+
+.yui3-menu-separator {
+ background-color: #dfdfdf;
+ display: block;
+ height: 1px;
+ font-size: 0;
+ margin: 7px 2px;
+ overflow: hidden;
+}
+
+.yui3-menu-hidden { display: none; }
View
50 lib/yuilib/gallery/gallery-sm-menu/assets/skins/sam/gallery-sm-menu-skin.css
@@ -0,0 +1,50 @@
+.yui3-skin-sam .yui3-menu-children {
+ background: #fff;
+ border: 1px solid #b7b7b7;
+ border-radius: 3px;
+ box-shadow: 0 3px 6px #afafaf;
+ padding: 5px 0;
+}
+
+.yui3-skin-sam .yui3-menu-label {
+ border: 1px solid transparent;
+ border-left: none;
+ border-right: none;
+}
+
+.yui3-skin-sam .yui3-menu-label,
+.yui3-skin-sam .yui3-menu-can-have-children > .yui3-menu-label:after {
+ color: #333;
+}
+
+.yui3-skin-sam .yui3-menu-can-have-children > .yui3-menu-label:hover:after {
+ color: #fff;
+}
+
+.yui3-skin-sam a.yui3-menu-label:hover {
+ background: rgb(81, 113, 235);
+ background: -moz-linear-gradient(rgba(81, 113, 235, 1), rgba(26, 67, 244, 1));
+ background: -ms-linear-gradient(rgba(81, 113, 235, 1), rgba(26, 67, 244, 1));
+ background: -o-linear-gradient(rgba(81, 113, 235, 1), rgba(26, 67, 244, 1));
+ background: -webkit-linear-gradient(rgba(81, 113, 235, 1), rgba(26, 67, 244, 1));
+ background: linear-gradient(rgba(81, 113, 235, 1), rgba(26, 67, 244, 1));
+ border-bottom-color: #0d36e7;
+ border-top-color: #4767ea;
+ color: #fff;
+}
+
+.yui3-skin-sam .yui3-menu-disabled > a.yui3-menu-label {
+ background-image: none;
+ border-color: transparent;
+ cursor: default;
+}
+
+.yui3-skin-sam .yui3-menu-disabled > a.yui3-menu-label,
+.yui3-skin-sam .yui3-menu-can-have-children.yui3-menu-disabled > .yui3-menu-label:after {
+ color: #bfbfbf;
+}
+
+.yui3-skin-sam .yui3-menu-heading .yui3-menu-label {
+ color: #888;
+ text-transform: uppercase;
+}
View
1  lib/yuilib/gallery/gallery-sm-menu/assets/skins/sam/gallery-sm-menu.css
@@ -0,0 +1 @@
+.yui3-menu,.yui3-menu-children{left:-10000px;position:absolute;top:-10000px;visibility:hidden}.yui3-menu.yui3-menu-open{left:auto;top:auto;visibility:visible;z-index:2}.yui3-menu-children{left:-10000px;list-style:none;margin:0;padding:0;top:-10000px;z-index:1}.yui3-menu>.yui3-menu-children{position:relative}.yui3-menu-open>.yui3-menu-children{left:0;top:0;visibility:visible}.yui3-menu-item{position:relative}.yui3-menu-label{display:block;color:inherit;line-height:1.5;padding:0 20px;text-decoration:none;white-space:nowrap}a.yui3-menu-label{padding-right:30px}.yui3-menu-can-have-children>.yui3-menu-label:after{content:'\25B8';float:right;font-family:'Lucida Grande','Lucida Sans Unicode','DejaVu Sans',sans-serif;margin-right:-20px;margin-top:-1px}.yui3-menu-separator{background-color:#dfdfdf;display:block;height:1px;font-size:0;margin:7px 2px;overflow:hidden}.yui3-menu-hidden{display:none}.yui3-skin-sam .yui3-menu-children{background:#fff;border:1px solid #b7b7b7;border-radius:3px;box-shadow:0 3px 6px #afafaf;padding:5px 0}.yui3-skin-sam .yui3-menu-label{border:1px solid transparent;border-left:none;border-right:0}.yui3-skin-sam .yui3-menu-label,.yui3-skin-sam .yui3-menu-can-have-children>.yui3-menu-label:after{color:#333}.yui3-skin-sam .yui3-menu-can-have-children>.yui3-menu-label:hover:after{color:#fff}.yui3-skin-sam a.yui3-menu-label:hover{background:#5171eb;background:-moz-linear-gradient(rgba(81,113,235,1),rgba(26,67,244,1));background:-ms-linear-gradient(rgba(81,113,235,1),rgba(26,67,244,1));background:-o-linear-gradient(rgba(81,113,235,1),rgba(26,67,244,1));background:-webkit-linear-gradient(rgba(81,113,235,1),rgba(26,67,244,1));background:linear-gradient(rgba(81,113,235,1),rgba(26,67,244,1));border-bottom-color:#0d36e7;border-top-color:#4767ea;color:#fff}.yui3-skin-sam .yui3-menu-disabled>a.yui3-menu-label{background-image:none;border-color:transparent;cursor:default}.yui3-skin-sam .yui3-menu-disabled>a.yui3-menu-label,.yui3-skin-sam .yui3-menu-can-have-children.yui3-menu-disabled>.yui3-menu-label:after{color:#bfbfbf}.yui3-skin-sam .yui3-menu-heading .yui3-menu-label{color:#888;text-transform:uppercase}#yui3-css-stamp.skin-sam-gallery-sm-menu{display:none}
View
1,282 lib/yuilib/gallery/gallery-sm-menu/gallery-sm-menu-debug.js
@@ -0,0 +1,1282 @@
+YUI.add('gallery-sm-menu', function (Y, NAME) {
+
+/*jshint expr:true, onevar:false */
+
+/**
+Provides the `Y.Menu` widget.
+
+@module gallery-sm-menu
+@main gallery-sm-menu
+**/
+
+/**
+Menu widget.
+
+@class Menu
+@constructor
+@param {Object} [config] Config options.
+@param {HTMLElement|Node|String} [config.sourceNode] Node instance, HTML
+ element, or selector string for a node (usually a `<ul>` or `<ol>`) whose
+ structure should be parsed and used to generate this menu's contents. This
+ node will be removed from the DOM after being parsed.
+@extends Menu.Base
+@uses View
+**/
+
+var doc = Y.config.doc,
+ getClassName = Y.ClassNameManager.getClassName;
+
+/**
+Fired when any clickable menu item is clicked.
+
+You can subscribe to clicks on a specific menu item by subscribing to
+"itemClick#id", where "id" is the item id of the item you want to subscribe to.
+
+@event itemClick
+@param {Menu.Item} item Menu item that was clicked.
+@param {EventFacade} originEvent Original click event.
+@preventable _defItemClickFn
+**/
+var EVT_ITEM_CLICK = 'itemClick';
+
+var Menu = Y.Base.create('menu', Y.Menu.Base, [Y.View], {
+
+ /**
+ CSS class names used by this menu.
+
+ @property {Object} classNames
+ **/
+ classNames: {
+ canHaveChildren: getClassName('menu-can-have-children'),
+ children : getClassName('menu-children'),
+ disabled : getClassName('menu-disabled'),
+ hasChildren : getClassName('menu-has-children'),
+ heading : getClassName('menu-heading'),
+ hidden : getClassName('menu-hidden'),
+ horizontal : getClassName('menu-horizontal'),
+ item : getClassName('menu-item'),
+ label : getClassName('menu-label'),
+ menu : getClassName('menu'),
+ noTouch : getClassName('menu-notouch'),
+ open : getClassName('menu-open'),
+ selected : getClassName('menu-selected'),
+ separator : getClassName('menu-separator'),
+ touch : getClassName('menu-touch'),
+ vertical : getClassName('menu-vertical')
+ },
+
+ /**
+ Whether or not this menu has been rendered.
+
+ @property {Boolean} rendered
+ @default false
+ **/
+ rendered: false,
+
+ /**
+ Selectors to use when parsing a menu structure from a DOM structure via
+ `parseHTML()`.
+
+ @property {Object} sourceSelectors
+ **/
+ sourceSelectors: {
+ item : '> li',
+ label : '> a, > span',
+ subtree: '> ul, > ol'
+ },
+
+ // -- Lifecycle Methods ----------------------------------------------------
+
+ initializer: function (config) {
+ this._openMenus = {};
+ this._published = {};
+ this._timeouts = {};
+
+ if (config && config.sourceNode) {
+ config.nodes = (config.nodes || []).concat(
+ this.parseHTML(config.sourceNode));
+
+ Y.one(config.sourceNode).remove(true);
+ }
+
+ this._attachMenuEvents();
+ },
+
+ destructor: function () {
+ this._detachMenuEvents();
+
+ delete this._openMenus;
+ delete this._published;
+
+ Y.Object.each(this._timeouts, function (timeout) {
+ clearTimeout(timeout);
+ }, this);
+
+ delete this._timeouts;
+ },
+
+ // -- Public Methods -------------------------------------------------------
+
+ /**
+ Returns the HTML node (as a `Y.Node` instance) associated with the specified
+ menu item, if any.
+
+ @method getHTMLNode
+ @param {Menu.Item} item Menu item.
+ @return {Node} `Y.Node` instance associated with the given tree node, or
+ `undefined` if one was not found.
+ **/
+ getHTMLNode: function (item) {
+ if (!item._htmlNode) {
+ item._htmlNode = this.get('container').one('#' + item.id);
+ }
+
+ return item._htmlNode;
+ },
+
+ /**
+ Hides this menu.
+
+ @method hide
+ @chainable
+ **/
+ hide: function () {
+ this.set('visible', false);
+ return this;
+ },
+
+ /**
+ Parses the specified HTML _sourceNode_ as a menu structure and returns an
+ array of menu item objects that can be used to generate a menu with that
+ structure.
+
+ By default, _sourceNode_ is expected to contain one `<li>` element per
+ menu item, and submenus are expected to be represented by `<ul>` or `<ol>`
+ elements.
+
+ The selector queries used to parse the menu structure are contained in the
+ `sourceSelectors` property, and may be customized. Class names specified in
+ the `classNames` property are used to determine whether a menu item should
+ be disabled, hidden, or treated as a heading or separator.
+
+ @method parseHTML
+ @param {HTMLElement|Node|String} sourceNode Node instance, HTML element, or
+ selector string for the node (usually a `<ul> or `<ol>` element) to
+ parse.
+ @return {Object[]} Array of menu item objects.
+ **/
+ parseHTML: function (sourceNode) {
+ sourceNode = Y.one(sourceNode);
+
+ var classNames = this.classNames,
+ items = [],
+ sel = this.sourceSelectors,
+ self = this;
+
+ sourceNode.all(sel.item).each(function (itemNode) {
+ var item = {},
+ itemEl = itemNode._node,
+ labelNode = itemNode.one(sel.label),
+ subTreeNode = itemNode.one(sel.subtree);
+
+ if (itemNode.hasClass(classNames.heading)) {
+ item.type = 'heading';
+ } else if (itemNode.hasClass(classNames.separator)) {
+ item.type = 'separator';
+ }
+
+ if (itemNode.hasClass(classNames.disabled)) {
+ item.state || (item.state = {});
+ item.state.disabled = true;
+ }
+
+ if (itemNode.hasClass(classNames.hidden)) {
+ item.state || (item.state = {});
+ item.state.hidden = true;
+ }
+
+ if (labelNode) {
+ var href = labelNode.getAttribute('href');
+
+ item.label = labelNode.getHTML();
+
+ if (href && href !== '#') {
+ item.url = href;
+ }
+ } else {
+ // The selector didn't find a label node, so look for the first
+ // text child of the item element.
+ var childEl;
+
+ for (var i = 0, len = itemEl.childNodes.length; i < len; i++) {
+ childEl = itemEl.childNodes[i];
+
+ if (childEl.nodeType === doc.TEXT_NODE) {
+ item.label = Y.Escape.html(childEl.nodeValue);
+ break;
+ }
+ }
+ }
+
+ if (subTreeNode) {
+ item.children = self.parseHTML(subTreeNode);
+ }
+
+ items.push(item);
+ });
+
+ return items;
+ },
+
+ /**
+ Renders this menu into its container.
+
+ If the container hasn't already been added to the current document, it will
+ be appended to the `<body>` element.
+
+ @method render
+ @chainable
+ **/
+ render: function () {
+ var classNames = this.classNames,
+ container = this.get('container');
+
+ container.addClass(classNames.menu);
+ container.addClass(classNames[this.get('orientation')]);
+
+ // Detect touchscreen devices.
+ if ('ontouchstart' in Y.config.win) {
+ container.addClass(classNames.touch);
+ } else {
+ container.addClass(classNames.noTouch);
+ }
+
+ this._childrenNode = this.renderChildren(this.rootNode, {
+ container: container
+ });
+
+ if (!container.inDoc()) {
+ Y.one('body').append(container);
+ }
+
+ this.rendered = true;
+
+ return this;
+ },
+
+ /**
+ Renders the children of the specified menu item.
+
+ If a container is specified, it will be assumed to be an existing rendered
+ menu item, and the children will be rendered (or re-rendered) inside it.
+
+ @method renderChildren
+ @param {Menu.Item} menuItem Menu item whose children should be rendered.
+ @param {Object} [options] Options.
+ @param {Node} [options.container] `Y.Node` instance of a container into
+ which the children should be rendered. If the container already
+ contains rendered children, they will be re-rendered in place.
+ @return {Node} `Y.Node` instance containing the rendered children.
+ **/
+ renderChildren: function (treeNode, options) {
+ options || (options = {});
+
+ var container = options.container,
+ childrenNode = container && container.one('.' + this.classNames.children);
+
+ if (!childrenNode) {
+ childrenNode = Y.Node.create(Menu.Templates.children({
+ classNames: this.classNames,
+ menu : this,
+ item : treeNode
+ }));
+ }
+
+ if (treeNode.isRoot()) {
+ childrenNode.set('tabIndex', 0); // Add the root list to the tab order.
+ childrenNode.set('role', 'menu');
+ }
+
+ if (treeNode.hasChildren()) {
+ childrenNode.set('aria-expanded', treeNode.isOpen());
+ }
+
+ for (var i = 0, len = treeNode.children.length; i < len; i++) {
+ this.renderNode(treeNode.children[i], {
+ container : childrenNode,
+ renderChildren: true
+ });
+ }
+
+ if (container) {
+ container.append(childrenNode);
+ }
+
+ return childrenNode;
+ },
+
+ /**
+ Renders the specified menu item and its children (if any).
+
+ If a container is specified, the rendered node will be appended to it.
+
+ @method renderNode
+ @param {Menu.Item} menuItem Tree node to render.
+ @param {Object} [options] Options.
+ @param {Node} [options.container] `Y.Node` instance of a container to
+ which the rendered tree node should be appended.
+ @param {Boolean} [options.renderChildren=false] Whether or not to render
+ this node's children.
+ @return {Node} `Y.Node` instance of the rendered menu item.
+ **/
+ renderNode: function (item, options) {
+ options || (options = {});
+
+ var classNames = this.classNames,
+ htmlNode = item._htmlNode,
+ isHidden = item.isHidden();
+
+ // Create an HTML node for this menu item if one doesn't already exist.
+ if (!htmlNode) {
+ htmlNode = item._htmlNode = Y.Node.create(Menu.Templates.item({
+ classNames: classNames,
+ item : item,
+ menu : this
+ }));
+ }
+
+ // Mark the HTML node as hidden if the item is hidden.
+ htmlNode.set('aria-hidden', isHidden);
+ htmlNode.toggleClass(classNames.hidden, isHidden);
+
+ switch (item.type) {
+ case 'separator':
+ htmlNode.set('role', 'separator');
+ break;
+
+ case 'item':
+ case 'heading':
+ var labelNode = htmlNode.one('.' + classNames.label),
+ labelId = labelNode.get('id');
+
+ labelNode.setHTML(item.label);
+
+ if (!labelId) {
+ labelId = Y.guid();
+ labelNode.set('id', labelId);
+ }
+
+ htmlNode.set('aria-labelledby', labelId);
+
+ if (item.type === 'heading') {
+ htmlNode.set('role', 'heading');
+ } else {
+ htmlNode.set('role', 'menuitem');
+
+ htmlNode.toggleClass(classNames.disabled, item.isDisabled());
+
+ if (item.canHaveChildren) {
+ htmlNode.addClass(classNames.canHaveChildren);
+ htmlNode.toggleClass(classNames.open, item.isOpen());
+
+ if (item.hasChildren()) {
+ htmlNode.addClass(classNames.hasChildren);
+
+ if (options.renderChildren) {
+ this.renderChildren(item, {
+ container: htmlNode
+ });
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ if (options.container) {
+ options.container.append(htmlNode);
+ }
+
+ return htmlNode;
+ },
+
+ /**
+ Repositions this menu so that it is anchored to a specified node, region, or
+ set of pixel coordinates.
+
+ The menu will be displayed at the most advantageous position relative to the
+ anchor point to ensure that as much of the menu as possible is visible
+ within the viewport.
+
+ @method reposition
+ @param {Node|Number[]|Object} anchorPoint Anchor point at which this menu
+ should be positioned. The point may be specified as a `Y.Node`
+ reference, a region object, or an array of X and Y pixel coordinates.
+ @chainable
+ **/
+ reposition: function (anchorPoint) {
+ var container = this.get('container'),
+ anchorRegion, menuRegion;
+
+ if (Y.Lang.isArray(anchorPoint)) {
+ anchorRegion = {
+ bottom: anchorPoint[1],
+ left : anchorPoint[0],
+ right : anchorPoint[0],
+ top : anchorPoint[1]
+ };
+ } else if (anchorPoint._node) {
+ anchorRegion = anchorPoint.get('region');
+ } else {
+ anchorRegion = anchorPoint;
+ }
+
+ menuRegion = this._getSortedAnchorRegions(
+ this.get('alignments'),
+ container.get('region'),
+ anchorRegion
+ )[0].region;
+
+ container.setXY([menuRegion.left, menuRegion.top]);
+
+ return this;
+ },
+
+ /**
+ Shows this menu.
+
+ The menu will be rendered if it hasn't been rendered already.
+
+ @method show
+ @param {Object} [options] Options.
+ @param {Node|Number[]|Object} [options.anchorPoint] Anchor point at
+ which this menu should be positioned when shown. The point may be
+ specified as a `Y.Node` reference, a region object, or an array of X
+ and Y pixel coordinates.
+ @chainable
+ **/
+ show: function (options) {
+ if (!this.rendered) {
+ this.render();
+ }
+
+ if (options && options.anchorPoint) {
+ this.reposition(options.anchorPoint);
+ }
+
+ this.set('visible', true);
+ return this;
+ },
+
+ /**
+ Toggles the visibility of this menu, showing it if it's currently hidden or
+ hiding it if it's currently visible.
+
+ @method toggleVisible
+ @param {Object} [options] Options.
+ @param {Node|Number[]|Object} [options.anchorPoint] Anchor point at
+ which this menu should be positioned when shown. The point may be
+ specified as a `Y.Node` reference, a region object, or an array of X
+ and Y pixel coordinates.
+ @chainable
+ **/
+ toggleVisible: function (options) {
+ return this[this.get('visible') ? 'hide' : 'show'](options);
+ },
+
+ // -- Protected Methods ----------------------------------------------------
+
+ /**
+ Attaches menu events.
+
+ @method _attachMenuEvents
+ @protected
+ **/
+ _attachMenuEvents: function () {
+ this._menuEvents || (this._menuEvents = []);
+
+ var classNames = this.classNames,
+ container = this.get('container');
+
+ this._menuEvents.push(
+ this.after({
+ add : this._afterAdd,
+ clear : this._afterClear,
+ close : this._afterClose,
+ disable : this._afterDisable,
+ enable : this._afterEnable,
+ hide : this._afterHide,
+ open : this._afterOpen,
+ orientationChange: this._afterOrientationChange,
+ remove : this._afterRemove,
+ show : this._afterShow,
+ visibleChange : this._afterVisibleChange
+ }),
+
+ container.on('hover', this._onMenuMouseEnter, this._onMenuMouseLeave, this),
+
+ container.delegate('click', this._onItemClick, '.' + classNames.item + '>.' + classNames.label, this),
+ container.delegate('hover', this._onItemMouseEnter, this._onItemMouseLeave, '.' + classNames.canHaveChildren, this),
+
+ Y.one('doc').after('mousedown', this._afterDocMouseDown, this)
+ );
+ },
+
+ /**
+ Detaches menu events.
+
+ @method _detachMenuEvents
+ @protected
+ **/
+ _detachMenuEvents: function () {
+ (new Y.EventHandle(this._menuEvents)).detach();
+ },
+
+ /**
+ Returns an efficient test function that can be passed to `Y.Node#ancestor()`
+ to test whether a node is this menu's container.
+
+ This is broken out to make overriding easier in subclasses.
+
+ @method _getAncestorTestFn
+ @return {Function} Test function.
+ @protected
+ **/
+ _getAncestorTestFn: function () {
+ var container = this.get('container');
+