Source: menubar.js

  1. /**
  2. * Menubar Component<BR>
  3. * <BR><BR><img src=/tk/lib/components/w/img/menubar.png width=30% style="border:1px lime dashed;padding:20px">
  4. * <BR><BR><a href="/tk/lib/components/w/html/menubar.html">DEMO</a>
  5. */
  6. class Menubar extends HTMLElement {
  7. constructor() {
  8. wc.group("Menubar.constructor")
  9. super();
  10. wc.groupEnd();
  11. };
  12. /**
  13. * Set observable values here. When Changed, attributeChangedCallback is invoked
  14. * @observedAttributes
  15. */
  16. static get observedAttributes() {
  17. wc.group("Menubar.observedAttributes");
  18. this.observables = [];
  19. wc.groupEnd();
  20. return this.observables;
  21. };
  22. /**
  23. * Initial Markup
  24. * @private
  25. * @_template
  26. */
  27. _template() {
  28. wc.group("Menubar.template");
  29. var temp = this.dom.content;
  30. wc.groupEnd();
  31. return temp;
  32. };
  33. /**
  34. * Called when this is attached to DOM
  35. * @connectedCallback.
  36. */
  37. connectedCallback() {
  38. wc.group("Menubar.connectedCallback")
  39. // GET PROPERTIES AND INTERESTING ELEMENTS
  40. this._initialize();
  41. // ADD COMPONENT MARKTOP
  42. this.innerHTML = this._template()
  43. $('.menu > ul > li:has( > ul)').addClass('menu-dropdown-icon');
  44. //Checks if li has sub (ul) and adds class for toggle icon - just an UI
  45. $('.menu > ul > li > ul:not(:has(ul))').addClass('normal-sub');
  46. //Checks if drodown menu's li elements have anothere level (ul), if not the dropdown is shown as regular dropdown, not a mega menu (thanks Luka Kladaric)
  47. $(".menu > ul").before("<a href=\"#\" class=\"menu-mobile\">Navigation</a>");
  48. //Adds menu-mobile class (for mobile toggle menu) before the normal menu
  49. //Mobile menu is hidden if width is more then 959px, but normal menu is displayed
  50. //Normal menu is hidden if width is below 959px, and jquery adds mobile menu
  51. //Done this way so it can be used with wordpress without any trouble
  52. $(".menu > ul > li").hover(function(e) {
  53. if ($(window).width() > 943) {
  54. $(this).children("ul").stop(true, false).fadeToggle(150);
  55. e.preventDefault();
  56. }
  57. });
  58. //If width is more than 943px dropdowns are displayed on hover
  59. $(".menu > ul > li").click(function() {
  60. if ($(window).width() <= 943) {
  61. $(this).children("ul").fadeToggle(150);
  62. }
  63. });
  64. //If width is less or equal to 943px dropdowns are displayed on click (thanks Aman Jain from stackoverflow)
  65. $(".menu-mobile").click(function(e) {
  66. $(".menu > ul").toggleClass('show-on-mobile');
  67. e.preventDefault();
  68. });
  69. //when clicked on mobile-menu, normal menu is shown as a list, classic rwd menu story (thanks mwl from stackoverflow)
  70. // MEL: SET WIDTH OF EACH <UL>
  71. $(".menu-dropdown-icon").each(function() {
  72. let len = $(this).find("> ul > li > ul").length;
  73. if (len) {
  74. $(this).find("> ul > li").width(100/len+"%");
  75. // EACH COLUMN IS 300PX WIDE
  76. //$(this).find("> ul").width(len*300+"px");
  77. }
  78. });
  79. // PUBLISH EVENTS
  80. this._publish();
  81. // ADD STATS AND OTHER FINAL STUFF
  82. this._finalize();
  83. wc.groupEnd();
  84. };
  85. /**
  86. * Publish all events of interest
  87. * @private
  88. * @_publish
  89. */
  90. _publish() {
  91. wc.group("Menubar.publish");
  92. let self = this;
  93. $(this).find("a").on("click", function() {
  94. let id = $(this).attr("id");
  95. wc.publish("wc-menubar", {
  96. time: new Date().getTime(),
  97. action: "click",
  98. id: id
  99. });
  100. });
  101. wc.groupEnd();
  102. }
  103. /**
  104. * Called with .setAttribute(...) function call
  105. * @attributeChangedCallback
  106. */
  107. attributeChangedCallback(attr, oldval, newval) {
  108. wc.group("Menubar.attributeChangedCallback:", attr, oldval, newval);
  109. this.properties = this.properties || [];
  110. let obs = Menubar.observedAttributes;
  111. for (let i = 0; i < obs.length; i++) {
  112. if (newval) {
  113. this.properties[obs[i]] = newval;
  114. }
  115. }
  116. // YOUR CODE FOR CHANGES GO HERE (MAYBE NULL FIRST TIME THROUGH)
  117. try {
  118. switch(attr)
  119. {
  120. case "header":
  121. break;
  122. default:
  123. break;
  124. }
  125. } catch(e) {
  126. wc.warn(e.name + ' > ' + e.message);
  127. }
  128. wc.groupEnd();
  129. };
  130. /**
  131. * Stores DOM elements of interest for future use
  132. * @private
  133. * @_fetchElements
  134. */
  135. _fetchElements() {
  136. wc.group("Menubar._fetchElements");
  137. this.dom = this.dom || [];
  138. this.dom.content = this.innerHTML;
  139. wc.groupEnd();
  140. };
  141. /**
  142. * Component attributes are _fetched and defaults are set if undefined
  143. * @private
  144. * @_fetchAttributes
  145. */
  146. _fetchAttributes() {
  147. wc.group("Menubar._fetchAttributes");
  148. this.properties = {
  149. cname : "Menubar",
  150. author : "Mel M. Heravi",
  151. version : "1.0"
  152. };
  153. // SAVE WIDGET SPECIFIC PROPERTIES
  154. this.propertiesW = [];
  155. // SAVE ALL OTHER PROPERTIES
  156. let attrs = wc.getAttributes(this)
  157. for (var key in attrs) {
  158. let attr = this.getAttribute(key) || this.properties.key;
  159. this.properties[key] = this.getAttribute(key);
  160. this.propertiesW[key] = this.getAttribute(key);
  161. wc.log(key + ": " + attrs[key]);
  162. }
  163. // SET ALL INITIAL ATTRIBUTES
  164. for (var key in this.properties) {
  165. switch(key)
  166. {
  167. case "header":
  168. break;
  169. default:
  170. break;
  171. }
  172. }
  173. wc.log("ATTRIBUTES: ", this.properties);
  174. wc.groupEnd();
  175. };
  176. /**
  177. * configure the instance object and artifacts
  178. * @configure
  179. */
  180. configure(options) {
  181. wc.group("Menubar.configure:", JSON.stringify(options));
  182. // PROCESS ALL OPTIONS HERE
  183. wc.groupEnd();
  184. };
  185. /**
  186. * Initialize component
  187. * @private
  188. * @_initialize
  189. */
  190. _initialize() {
  191. wc.group("Menubar._initialize:", this.id);
  192. // FETCH ALL INTERESTING ELEMENTS
  193. this._fetchElements();
  194. // FETCH ALL ATTRIBUTES
  195. this._fetchAttributes();
  196. wc.groupEnd();
  197. };
  198. /**
  199. * Save data for analytics and final wrap up
  200. * @private
  201. * @_finalize
  202. */
  203. _finalize() {
  204. wc.group("Menubar._finalize:", this.id);
  205. this.classList.add("wc");
  206. // ADD ANALYTICS HERE
  207. wc.setStats(this, this.properties.cname, this.properties.version);
  208. // SHOW IT NOW (NO FLICKERS)
  209. this.style.visibility = "visible";
  210. wc.groupEnd();
  211. };
  212. /**
  213. * Invoked When component is removed. Usually with a .remove() function call
  214. * @disconnectedCallback
  215. */
  216. disconnectedCallback() {
  217. wc.group("Menubar.disconnectedCallback")
  218. // FREE MEMORY AND CLEANUP
  219. wc.groupEnd();
  220. };
  221. }
  222. window.customElements.define('wc-menubar', Menubar);