listbox.js revision e808b8824ca1091c8efb5669db9129e68e5e1c14
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen DesaiYUI.add('listbox', function(Y) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen DesaiY.ListBox = Y.Base.create("listbox", Y.Widget, [Y.WidgetParent, Y.WidgetChild], {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai CONTENT_TEMPLATE : "<ul></ul>",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai bindUI: function() {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (this.isRoot()) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this.get("boundingBox").plug(Y.Plugin.NodeFocusManager, {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai descendants: ".yui3-option",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai keys: {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai next: "down:40", // Down arrow
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai previous: "down:38" // Up arrow
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai },
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai circular: true
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai });
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this.get("boundingBox").on("contextmenu", function (event) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai event.preventDefault();
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai });
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai // Setup listener to control keyboard based single/multiple item selection
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this.on("option:keydown", function (event) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai var item = event.target,
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai domEvent = event.domEvent,
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai keyCode = domEvent.keyCode,
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai direction = (keyCode == 40);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (this.get("multiple")) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (keyCode == 40 || keyCode == 38) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (domEvent.shiftKey) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this._selectNextSibling(item, direction);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai } else {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this.deselectAll();
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this._selectNextSibling(item, direction);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai } else {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (keyCode == 13 || keyCode == 32) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai domEvent.preventDefault();
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai item.set("selected", 1);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai });
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai // Setup listener to control mouse based single/multiple item selection
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this.on("option:mousedown", function (event) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai var item = event.target,
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai domEvent = event.domEvent,
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai selection;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (this.get("multiple")) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (domEvent.metaKey) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai item.set("selected", 1);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai } else {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this.deselectAll();
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai item.set("selected", 1);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai } else {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai item.set("selected", 1);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai });
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai },
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai // Helper Method, to find the correct next sibling, taking into account nested ListBoxes
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai _selectNextSibling : function(item, direction) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai var parent = item.get("parent"),
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai method = (direction) ? "next" : "previous",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai // Only go circular for the root listbox
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai circular = (parent === this),
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai sibling = item[method](circular);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (sibling) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai // If we found a sibling, it's either an Option or a ListBox
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (sibling instanceof Y.ListBox) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai // If it's a ListBox, select it's first child (in the direction we're headed)
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai sibling.selectChild((direction) ? 0 : sibling.size() - 1);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai } else {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai // If it's an Option, select it
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai sibling.set("selected", 1);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai } else {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai // If we didn't find a sibling, we're at the last leaf in a nested ListBox
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai parent[method](true).set("selected", 1);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai },
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai NESTED_TEMPLATE : '<li class="{nestedOptionClassName}"><em class="{labelClassName}">{label}</em></li>',
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai renderUI: function () {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai if (this.get("depth") > -1) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai var tokens = {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai labelClassName : this.getClassName("label"),
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai nestedOptionClassName : this.getClassName("option"),
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai label : this.get("label")
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai },
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai liHtml = Y.substitute(this.NESTED_TEMPLATE, tokens),
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai li = Y.Node.create(liHtml),
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai boundingBox = this.get("boundingBox"),
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai parent = boundingBox.get("parentNode");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai li.appendChild(boundingBox);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai parent.appendChild(li);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}, {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai ATTRS : {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai defaultChildType: {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai value: "Option"
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai },
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai label : {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai validator: Y.Lang.isString
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen DesaiY.Option = Y.Base.create("option", Y.Widget, [Y.WidgetChild], {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai CONTENT_TEMPLATE : "<em></em>",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai BOUNDING_TEMPLATE : "<li></li>",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai renderUI: function () {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai this.get("contentBox").setContent(this.get("label"));
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}, {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai ATTRS : {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai label : {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai validator: Y.Lang.isString
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai },
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai tabIndex: {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai value: -1
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}, '3.1.0' ,{requires:['substitute', 'widget', 'widget-parent', 'widget-child', 'node-focusmanager']});