PageRenderTime 21ms CodeModel.GetById 4ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/js/yii/zii/widgets/CMenu.js

http://github.com/phpnode/YiiJS
JavaScript | 292 lines | 142 code | 4 blank | 146 comment | 45 complexity | df762f186334d9f412bd859bcc00c13e MD5 | raw file
  1/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  2/**
  3 * CMenu displays a multi-level menu using nested HTML lists.
  4 * 
  5 * The main property of CMenu is {@link items}, which specifies the possible items in the menu.
  6 * A menu item has three main properties: visible, active and items. The "visible" property
  7 * specifies whether the menu item is currently visible. The "active" property specifies whether
  8 * the menu item is currently selected. And the "items" property specifies the child menu items.
  9 * 
 10 * The following example shows how to use CMenu:
 11 * <pre>
 12 * this.widget('zii.widgets.CMenu', {
 13 *     'items':{
 14 *         // Important: you need to specify url as 'controller/action',
 15 *         // not just as 'controller' even if default acion is used.
 16 *         {'label':'Home', 'url':{'site/index'}),
 17 *         {'label':'Products', 'url':{'product/index'}, 'items':{
 18 *             {'label':'New Arrivals', 'url':{'product/new', 'tag':'new'}),
 19 *             {'label':'Most Popular', 'url':{'product/index', 'tag':'popular'}),
 20 *         )),
 21 *         {'label':'Login', 'url':{'site/login'}, 'visible':Yii.app().user.isGuest),
 22 *     ),
 23 * });
 24 * </pre>
 25 * 
 26 * 
 27 * @originalAuthor Jonah Turnquist <poppitypop@gmail.com>
 28 * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
 29 * @version $Id: CMenu.php 3034 2011-03-08 18:22:29Z qiang.xue $
 30 * @package zii.widgets
 31 * @since 1.1
 32 * @author Charles Pick
 33 * @class
 34 * @extends Yii.CWidget
 35 */
 36Yii.CMenu = function CMenu () {
 37	
 38};
 39Yii.CMenu.prototype = new Yii.CWidget(false);
 40Yii.CMenu.prototype.constructor =  Yii.CMenu;
 41/**
 42 * @var {Array} list of menu items. Each menu item is specified as an array of name-value pairs.
 43 * Possible option names include the following:
 44 * <ul>
 45 * <li>label: string, optional, specifies the menu item label. When {@link encodeLabel} is true, the label
 46 * will be HTML-encoded. If the label is not specified, it defaults to an empty string.</li>
 47 * <li>url: string or array, optional, specifies the URL of the menu item. It is passed to {@link CHtml::normalizeUrl}
 48 * to generate a valid URL. If this is not set, the menu item will be rendered as a span text.</li>
 49 * <li>visible: boolean, optional, whether this menu item is visible. Defaults to true.
 50 * This can be used to control the visibility of menu items based on user permissions.</li>
 51 * <li>items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.</li>
 52 * <li>active: boolean, optional, whether this menu item is in active state (currently selected).
 53 * If a menu item is active and {@link activeClass} is not empty, its CSS class will be appended with {@link activeClass}.
 54 * If this option is not set, the menu item will be set active automatically when the current request
 55 * is triggered by {@link url}. Note that the GET parameters not specified in the 'url' option will be ignored.</li>
 56 * <li>template: string, optional, the template used to render this menu item.
 57 * When this option is set, it will override the global setting {@link itemTemplate}.
 58 * Please see {@link itemTemplate} for more details. This option has been available since version 1.1.1.</li>
 59 * <li>linkOptions: array, optional, additional HTML attributes to be rendered for the link or span tag of the menu item.</li>
 60 * <li>itemOptions: array, optional, additional HTML attributes to be rendered for the container tag of the menu item.</li>
 61 * <li>submenuOptions: array, optional, additional HTML attributes to be rendered for the container of the submenu if this menu item has one.
 62 * When this option is set, the {@link submenuHtmlOptions} property will be ignored for this particular submenu.
 63 * This option has been available since version 1.1.6.</li>
 64 * </ul>
 65 */
 66Yii.CMenu.prototype.items = [];
 67/**
 68 * @var {String} the template used to render an individual menu item. In this template,
 69 * the token "{menu}" will be replaced with the corresponding menu link or text.
 70 * If this property is not set, each menu will be rendered without any decoration.
 71 * This property will be overridden by the 'template' option set in individual menu items via {@items}.
 72 * @since 1.1.1
 73 */
 74Yii.CMenu.prototype.itemTemplate = undefined;
 75/**
 76 * @var {Boolean} whether the labels for menu items should be HTML-encoded. Defaults to true.
 77 */
 78Yii.CMenu.prototype.encodeLabel = true;
 79/**
 80 * @var {String} the CSS class to be appended to the active menu item. Defaults to 'active'.
 81 * If empty, the CSS class of menu items will not be changed.
 82 */
 83Yii.CMenu.prototype.activeCssClass = 'active';
 84/**
 85 * @var {Boolean} whether to automatically activate items according to whether their route setting
 86 * matches the currently requested route. Defaults to true.
 87 * @since 1.1.3
 88 */
 89Yii.CMenu.prototype.activateItems = true;
 90/**
 91 * @var {Boolean} whether to activate parent menu items when one of the corresponding child menu items is active.
 92 * The activated parent menu items will also have its CSS classes appended with {@link activeCssClass}.
 93 * Defaults to false.
 94 */
 95Yii.CMenu.prototype.activateParents = false;
 96/**
 97 * @var {Boolean} whether to hide empty menu items. An empty menu item is one whose 'url' option is not
 98 * set and which doesn't contain visible child menu items. Defaults to true.
 99 */
100Yii.CMenu.prototype.hideEmptyItems = true;
101/**
102 * @var {Object} HTML attributes for the menu's root container tag
103 */
104Yii.CMenu.prototype.htmlOptions = {};
105/**
106 * @var {Object} HTML attributes for the submenu's container tag.
107 */
108Yii.CMenu.prototype.submenuHtmlOptions = {};
109/**
110 * @var {String} the HTML element name that will be used to wrap the label of all menu links.
111 * For example, if this property is set as 'span', a menu item may be rendered as
112 * &lt;li&gt;&lt;a href="url"&gt;&lt;span&gt;label&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
113 * This is useful when implementing menu items using the sliding window technique.
114 * Defaults to null, meaning no wrapper tag will be generated.
115 * @since 1.1.4
116 */
117Yii.CMenu.prototype.linkLabelWrapper = null;
118/**
119 * @var {String} the CSS class that will be assigned to the first item in the main menu or each submenu.
120 * Defaults to null, meaning no such CSS class will be assigned.
121 * @since 1.1.4
122 */
123Yii.CMenu.prototype.firstItemCssClass = null;
124/**
125 * @var {String} the CSS class that will be assigned to the last item in the main menu or each submenu.
126 * Defaults to null, meaning no such CSS class will be assigned.
127 * @since 1.1.4
128 */
129Yii.CMenu.prototype.lastItemCssClass = null;
130
131/**
132 * Calls {@link renderMenu} to render the menu.
133 */
134Yii.CMenu.prototype.run = function () {
135		var route, hasActiveChild;
136		this.htmlOptions.id=this.getId();
137		route=this.getController().getRoute();
138		this.items=this.normalizeItems(this.items,route,hasActiveChild);
139		return this.renderMenu(this.items);
140	};
141/**
142 * Renders the menu items.
143 * @param {Array} items menu items. Each menu item will be an array with at least two elements: 'label' and 'active'.
144 * It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'.
145 */
146Yii.CMenu.prototype.renderMenu = function (items) {
147		var ret = "";
148		if(items !== undefined && items !== null && items.length > 0) {
149			ret += Yii.CHtml.openTag('ul',this.htmlOptions)+"\n";
150			ret += this.renderMenuRecursive(items);
151			ret += Yii.CHtml.closeTag('ul');
152		}
153		return ret;
154	};
155/**
156 * Recursively renders the menu items.
157 * @param {Array} items the menu items to be rendered recursively
158 */
159Yii.CMenu.prototype.renderMenuRecursive = function (items) {
160		var count, n, i, limit, options, item, classVar, menu, template, ret = "";
161		count=0;
162		
163		n=items.length;
164		limit = items.length;
165		for (i = 0; i < limit; i++) {
166			item = items[i];
167			count++;
168			options=item.itemOptions !== undefined ? item.itemOptions : {};
169			classVar=[];
170			if(item['active'] && this.activeCssClass!='') {
171				classVar.push(this.activeCssClass);
172			}
173			if(count===1 && this.firstItemCssClass!='') {
174				classVar.push(this.firstItemCssClass);
175			}
176			if(count===n && this.lastItemCssClass!='') {
177				classVar.push(this.lastItemCssClass);
178			}	
179			if(classVar!==[]) {
180				if(php.empty(options['class'])) {
181					options['class']=classVar.join(' ');
182				}
183				else {
184					options['class']+=' '+classVar.join(' ');
185				}
186			}
187			ret += Yii.CHtml.openTag('li', options);
188			menu=this.renderMenuItem(item);
189			if(this.itemTemplate !== undefined || item.template !== undefined) {
190				template=item.template !== undefined ? item.template : this.itemTemplate;
191				ret += php.strtr(template,{'{menu}':menu});
192			}
193			else {
194				ret += menu;
195			}
196			if(item.items !== undefined && php.count(item.items)) {
197				ret += "\n"+Yii.CHtml.openTag('ul',item.submenuOptions !== undefined ? item.submenuOptions : this.submenuHtmlOptions)+"\n";
198				this.renderMenuRecursive(item.items);
199				ret += Yii.CHtml.closeTag('ul')+"\n";
200			}
201			ret += Yii.CHtml.closeTag('li')+"\n";
202		}
203		return ret;
204	};
205/**
206 * Renders the content of a menu item.
207 * Note that the container and the sub-menus are not rendered here.
208 * @param {Array} item the menu item to be rendered. Please see {@link items} on what data might be in the item.
209 * @since 1.1.6
210 */
211Yii.CMenu.prototype.renderMenuItem = function (item) {
212		var label;
213		if(item.url !== undefined) {
214			label=this.linkLabelWrapper===null ? item.label : '<'+this.linkLabelWrapper+'>'+item.label+'</'+this.linkLabelWrapper+'>';
215			return Yii.CHtml.link(label,item.url,item.linkOptions !== undefined ? item.linkOptions : {});
216		}
217		else {
218			return Yii.CHtml.tag('span',item.linkOptions !== undefined ? item.linkOptions : {}, item.label);
219		}
220	};
221/**
222 * Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
223 * @param {Array} items the items to be normalized.
224 * @param {String} route the route of the current request.
225 * @param {Boolean} active whether there is an active child menu item.
226 * @returns {Array} the normalized menu items
227 */
228Yii.CMenu.prototype.normalizeItems = function (items, route, active) {
229		var item, i, hasActiveChild;
230		for (i in items) {
231			if (items.hasOwnProperty(i)) {
232				item = items[i];
233				if(item.visible !== undefined && !item.visible) {
234					delete items[i];
235					continue;
236				}
237				if(item.label === undefined) {
238					item.label='';
239				}
240				if(this.encodeLabel) {
241					items[i].label=Yii.CHtml.encode(item.label);
242				}
243				hasActiveChild=false;
244				if(item.items !== undefined) {
245					items[i].items=this.normalizeItems(item.items,route,hasActiveChild);
246					if(php.empty(items[i].items) && this.hideEmptyItems) {
247						delete items[i].items;
248					}
249				}
250				if(item.active === undefined) {
251					if(this.activateParents && hasActiveChild || this.activateItems && this.isItemActive(item,route)) {
252						active=items[i].active=true;
253					}
254					else {
255						items[i].active=false;
256					}
257				}
258				else if(item.active) {
259					active=true;
260				}
261			}
262		}
263		return items;
264		//return php.array_values(items);
265	};
266/**
267 * Checks whether a menu item is active.
268 * This is done by checking if the currently requested URL is generated by the 'url' option
269 * of the menu item. Note that the GET parameters not specified in the 'url' option will be ignored.
270 * @param {Array} item the menu item to be checked
271 * @param {String} route the route of the current request
272 * @returns {Boolean} whether the menu item is active
273 */
274Yii.CMenu.prototype.isItemActive = function (item, route) {
275		var nameValue, name, value;
276		if(item.url !== undefined && Object.prototype.toString.call(item.url) === '[object Array]' && !php.strcasecmp(php.trim(item.url[0],'/'),route)) {
277			
278			if(php.count(item.url)>1) {
279				nameValue = php.array_splice(item.url,1);
280				for (name in nameValue) {
281					if (nameValue.hasOwnProperty(name)) {
282						value = nameValue[name];
283						if(Yii.app().getRequest().params[name] === undefined || Yii.app().getRequest().params[name]!=value) {
284							return false;
285						}
286					}
287				}
288			}
289			return true;
290		}
291		return false;
292	};