UNPKG

5.43 kBJavaScriptView Raw
1/*!
2* zeynepjs v2.2.0
3* A light-weight multi-level jQuery side menu plugin.
4* It's fully customizable and is compatible with modern browsers such as Google Chrome, Mozilla Firefox, Safari, Edge and Internet Explorer
5* MIT License
6* by Huseyin ELMAS
7*/
8(function ($, pluginName) {
9 var defaults = {
10 htmlClass: true
11 }
12
13 function Plugin (element, options) {
14 this.element = element
15 this.eventController = eventController
16 this.options = $.extend({}, defaults, options)
17 this.options.initialized = false
18
19 this.init()
20 }
21
22 Plugin.prototype.init = function () {
23 var zeynep = this.element
24 var options = this.options
25 var eventController = this.eventController.bind(this)
26
27 // exit if already initialized
28 if (options.initialized === true) return
29
30 eventController('loading')
31
32 // handle subMenu links/triggers click events
33 zeynep.find('[data-submenu]').on('click', function (event) {
34 event.preventDefault()
35
36 var self = $(this)
37 var subMenuId = self.attr('data-submenu')
38 var subMenuEl = $('#' + subMenuId)
39
40 // if subMenu not found, do nothing
41 if (!subMenuEl.length) return
42
43 var eventDetails = {
44 subMenu: true,
45 menuId: subMenuId
46 }
47
48 eventController('opening', eventDetails)
49
50 // open the subMenu
51 zeynep.find('.submenu.current').removeClass('current')
52 subMenuEl.addClass('opened current')
53 !zeynep.hasClass('submenu-opened') && zeynep.addClass('submenu-opened')
54
55 // scroll to top before submenu transition
56 zeynep[0].scrollTo({ top: 0 })
57
58 eventController('opened', eventDetails)
59 })
60
61 // handle subMenu closers click events
62 zeynep.find('[data-submenu-close]').on('click', function (event) {
63 event.preventDefault()
64
65 var self = $(this)
66 var subMenuId = self.attr('data-submenu-close')
67 var subMenuEl = $('#' + subMenuId)
68
69 // if subMenu not found, do nothing
70 if (!subMenuEl.length) return
71
72 var eventDetails = {
73 subMenu: true,
74 menuId: subMenuId
75 }
76
77 eventController('closing', eventDetails)
78
79 // close subMenu
80 subMenuEl.removeClass('opened current')
81 zeynep.find('.submenu.opened').last().addClass('current')
82 !zeynep.find('.submenu.opened').length && zeynep.removeClass('submenu-opened')
83
84 // scroll to top between submenu transitions
85 subMenuEl[0].scrollTo({ top: 0 })
86
87 eventController('closed', eventDetails)
88 })
89
90 eventController('load')
91
92 // zeynepjs successfully initialized
93 this.options.htmlClass && !$('html').hasClass('zeynep-initialized') && $('html').addClass('zeynep-initialized')
94
95 options.initialized = true
96 }
97
98 Plugin.prototype.open = function () {
99 this.eventController(
100 'opening',
101 { subMenu: false }
102 )
103
104 // zeynepjs menu is opened
105 this.element.addClass('opened')
106 this.options.htmlClass && $('html').addClass('zeynep-opened')
107
108 this.eventController(
109 'opened',
110 { subMenu: false }
111 )
112 }
113
114 Plugin.prototype.close = function (disableEvent) {
115 !disableEvent && this.eventController('closing', { subMenu: false })
116
117 // zeynepjs menu is opened
118 this.element.removeClass('opened')
119 this.options.htmlClass && $('html').removeClass('zeynep-opened')
120
121 !disableEvent && this.eventController('closed', { subMenu: false })
122 }
123
124 Plugin.prototype.destroy = function () {
125 this.eventController('destroying')
126
127 // close the menu without firing any event
128 this.close(true)
129
130 // close submenus
131 this.element.find('.submenu.opened').removeClass('opened')
132
133 // clear/remove the instance on the element
134 this.element.removeData(pluginName)
135
136 this.eventController('destroyed')
137
138 // reset options
139 this.options = defaults
140
141 this.options.htmlClass && $('html').removeClass('zeynep-initialized')
142
143 delete this.element
144 delete this.options
145 delete this.eventController
146 }
147
148 Plugin.prototype.on = function (name, handler) {
149 eventBinder.call(this, name, handler)
150 }
151
152 var eventController = function (type, details) {
153 if (!this.options[type]) return
154 if (typeof this.options[type] !== 'function') throw Error('event handler must be a function: ' + type)
155
156 // call the event
157 this.options[type].call(this, this.element, this.options, details)
158 }
159
160 var getInstance = function (element, options) {
161 var instance = null
162
163 if (!element.data(pluginName)) {
164 // zeynepjs is not initialized for the element
165 // crceate a new instance
166 instance = new Plugin(element, options || {})
167
168 // put the instance on element
169 element.data(pluginName, instance)
170 } else {
171 // return the already initialized instance
172 instance = element.data(pluginName)
173 }
174
175 return instance
176 }
177
178 var eventBinder = function (name, handler) {
179 if (typeof name !== 'string') throw Error('event name is expected to be a string but got: ' + typeof name)
180 if (typeof handler !== 'function') throw Error('event handler is not a function for: ' + name)
181
182 // update options
183 this.options[name] = handler
184 }
185
186 // a really lightweight plugin wrapper around the constructor
187 // preventing against multiple instantiations
188 $.fn[pluginName] = function (options) {
189 // get a zeynepjs instance
190 var instance = getInstance($(this[0]), options)
191
192 return instance
193 }
194})(window.jQuery || window.cash, 'zeynep')