menu.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. ///import core
  2. ///import uicore
  3. ///import ui\popup.js
  4. ///import ui\stateful.js
  5. (function (){
  6. var utils = baidu.editor.utils,
  7. domUtils = baidu.editor.dom.domUtils,
  8. uiUtils = baidu.editor.ui.uiUtils,
  9. UIBase = baidu.editor.ui.UIBase,
  10. Popup = baidu.editor.ui.Popup,
  11. Stateful = baidu.editor.ui.Stateful,
  12. Menu = baidu.editor.ui.Menu = function (options){
  13. this.initOptions(options);
  14. this.initMenu();
  15. };
  16. var menuSeparator = {
  17. renderHtml: function (){
  18. return '<div class="edui-menuitem edui-menuseparator"><div class="edui-menuseparator-inner"></div></div>';
  19. },
  20. postRender: function (){},
  21. queryAutoHide: function (){ return true; }
  22. };
  23. Menu.prototype = {
  24. items: null,
  25. uiName: 'menu',
  26. initMenu: function (){
  27. this.items = this.items || [];
  28. this.initPopup();
  29. this.initItems();
  30. },
  31. initItems: function (){
  32. for (var i=0; i<this.items.length; i++) {
  33. var item = this.items[i];
  34. if (item == '-') {
  35. this.items[i] = this.getSeparator();
  36. } else if (!(item instanceof MenuItem)) {
  37. this.items[i] = this.createItem(item);
  38. }
  39. }
  40. },
  41. getSeparator: function (){
  42. return menuSeparator;
  43. },
  44. createItem: function (item){
  45. return new MenuItem(item);
  46. },
  47. _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl,
  48. getContentHtmlTpl: function (){
  49. if (this.items.length == 0) {
  50. return this._Popup_getContentHtmlTpl();
  51. }
  52. var buff = [];
  53. for (var i=0; i<this.items.length; i++) {
  54. var item = this.items[i];
  55. buff[i] = item.renderHtml();
  56. }
  57. return ('<div class="%%-body">' + buff.join('') + '</div>');
  58. },
  59. _Popup_postRender: Popup.prototype.postRender,
  60. postRender: function (){
  61. var me = this;
  62. for (var i=0; i<this.items.length; i++) {
  63. var item = this.items[i];
  64. item.ownerMenu = this;
  65. item.postRender();
  66. }
  67. domUtils.on(this.getDom(), 'mouseover', function (evt){
  68. evt = evt || event;
  69. var rel = evt.relatedTarget || evt.fromElement;
  70. var el = me.getDom();
  71. if (!uiUtils.contains(el, rel) && el !== rel) {
  72. me.fireEvent('over');
  73. }
  74. });
  75. this._Popup_postRender();
  76. },
  77. queryAutoHide: function (el){
  78. if (el) {
  79. if (uiUtils.contains(this.getDom(), el)) {
  80. return false;
  81. }
  82. for (var i=0; i<this.items.length; i++) {
  83. var item = this.items[i];
  84. if (item.queryAutoHide(el) === false) {
  85. return false;
  86. }
  87. }
  88. }
  89. },
  90. clearItems: function (){
  91. for (var i=0; i<this.items.length; i++) {
  92. var item = this.items[i];
  93. clearTimeout(item._showingTimer);
  94. clearTimeout(item._closingTimer);
  95. if (item.subMenu) {
  96. item.subMenu.destroy();
  97. }
  98. }
  99. this.items = [];
  100. },
  101. destroy: function (){
  102. if (this.getDom()) {
  103. domUtils.remove(this.getDom());
  104. }
  105. this.clearItems();
  106. },
  107. dispose: function (){
  108. this.destroy();
  109. }
  110. };
  111. utils.inherits(Menu, Popup);
  112. var MenuItem = baidu.editor.ui.MenuItem = function (options){
  113. this.initOptions(options);
  114. this.initUIBase();
  115. this.Stateful_init();
  116. if (this.subMenu && !(this.subMenu instanceof Menu)) {
  117. this.subMenu = new Menu(this.subMenu);
  118. }
  119. };
  120. MenuItem.prototype = {
  121. label: '',
  122. subMenu: null,
  123. ownerMenu: null,
  124. uiName: 'menuitem',
  125. alwalysHoverable: true,
  126. getHtmlTpl: function (){
  127. return '<div id="##" class="%%" stateful onclick="$$._onClick(event, this);">' +
  128. '<div class="%%-body">' +
  129. this.renderLabelHtml() +
  130. '</div>' +
  131. '</div>';
  132. },
  133. postRender: function (){
  134. var me = this;
  135. this.addListener('over', function (){
  136. me.ownerMenu.fireEvent('submenuover', me);
  137. if (me.subMenu) {
  138. me.delayShowSubMenu();
  139. }
  140. });
  141. if (this.subMenu) {
  142. this.getDom().className += ' edui-hassubmenu';
  143. this.subMenu.render();
  144. this.addListener('out', function (){
  145. me.delayHideSubMenu();
  146. });
  147. this.subMenu.addListener('over', function (){
  148. clearTimeout(me._closingTimer);
  149. me._closingTimer = null;
  150. me.addState('opened');
  151. });
  152. this.ownerMenu.addListener('hide', function (){
  153. me.hideSubMenu();
  154. });
  155. this.ownerMenu.addListener('submenuover', function (t, subMenu){
  156. if (subMenu !== me) {
  157. me.delayHideSubMenu();
  158. }
  159. });
  160. this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide;
  161. this.subMenu.queryAutoHide = function (el){
  162. if (el && uiUtils.contains(me.getDom(), el)) {
  163. return false;
  164. }
  165. return this._bakQueryAutoHide(el);
  166. };
  167. }
  168. this.getDom().style.tabIndex = '-1';
  169. uiUtils.makeUnselectable(this.getDom());
  170. this.Stateful_postRender();
  171. },
  172. delayShowSubMenu: function (){
  173. var me = this;
  174. if (!me.isDisabled()) {
  175. me.addState('opened');
  176. clearTimeout(me._showingTimer);
  177. clearTimeout(me._closingTimer);
  178. me._closingTimer = null;
  179. me._showingTimer = setTimeout(function (){
  180. me.showSubMenu();
  181. }, 250);
  182. }
  183. },
  184. delayHideSubMenu: function (){
  185. var me = this;
  186. if (!me.isDisabled()) {
  187. me.removeState('opened');
  188. clearTimeout(me._showingTimer);
  189. if (!me._closingTimer) {
  190. me._closingTimer = setTimeout(function (){
  191. if (!me.hasState('opened')) {
  192. me.hideSubMenu();
  193. }
  194. me._closingTimer = null;
  195. }, 400);
  196. }
  197. }
  198. },
  199. renderLabelHtml: function (){
  200. return '<div class="edui-arrow"></div>' +
  201. '<div class="edui-box edui-icon"></div>' +
  202. '<div class="edui-box edui-label %%-label">' + (this.label || '') + '</div>';
  203. },
  204. getStateDom: function (){
  205. return this.getDom();
  206. },
  207. queryAutoHide: function (el){
  208. if (this.subMenu && this.hasState('opened')) {
  209. return this.subMenu.queryAutoHide(el);
  210. }
  211. },
  212. _onClick: function (event, this_){
  213. if (this.hasState('disabled')) return;
  214. if (this.fireEvent('click', event, this_) !== false) {
  215. if (this.subMenu) {
  216. this.showSubMenu();
  217. } else {
  218. Popup.postHide();
  219. }
  220. }
  221. },
  222. showSubMenu: function (){
  223. var rect = uiUtils.getClientRect(this.getDom());
  224. rect.right -= 5;
  225. rect.left += 2;
  226. rect.width -= 7;
  227. rect.top -= 4;
  228. rect.bottom += 4;
  229. rect.height += 8;
  230. this.subMenu.showAnchorRect(rect, true, true);
  231. },
  232. hideSubMenu: function (){
  233. this.subMenu.hide();
  234. }
  235. };
  236. utils.inherits(MenuItem, UIBase);
  237. utils.extend(MenuItem.prototype, Stateful, true);
  238. })();