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