romo 0.19.10 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,411 +1,271 @@
1
- $.fn.romoDropdown = function() {
2
- return $.map(this, function(element) {
3
- return new RomoDropdown(element);
4
- });
5
- }
6
-
7
- var RomoDropdown = function(element) {
8
- this.elem = $(element);
9
- this.doInitPopup();
10
- this.romoAjax = this.elem.romoAjax()[0];
11
- this.romoAjax.doUnbindElem(); // disable auto invoke on click
12
-
13
- if (this.elem.data('romo-dropdown-disable-click-invoke') !== true) {
14
- this.elem.unbind('click');
15
- this.elem.on('click', $.proxy(this.onToggleClick, this));
16
- }
17
- this.elem.on('dropdown:triggerToggle', $.proxy(this.onToggleClick, this));
18
- this.elem.on('dropdown:triggerPopupOpen', $.proxy(this.onPopupOpen, this));
19
- this.elem.on('dropdown:triggerPopupClose', $.proxy(this.onPopupClose, this));
20
- this.elem.on('romoAjax:callStart', $.proxy(function(e, romoAjax) {
21
- this.doLoadBodyStart();
22
- return false;
23
- }, this));
24
- this.elem.on('romoAjax:callSuccess', $.proxy(function(e, data, romoAjax) {
25
- this.doLoadBodySuccess(data);
26
- return false;
27
- }, this));
28
- this.elem.on('romoAjax:callError', $.proxy(function(e, xhr, romoAjax) {
29
- this.doLoadBodyError(xhr);
30
- return false;
31
- }, this));
32
-
33
- this.doBindElemKeyUp();
1
+ var RomoDropdown = RomoComponent(function(elem) {
2
+ this.elem = elem;
34
3
 
35
4
  this.doInit();
36
- this.doInitBody();
5
+ this._bindElem();
37
6
 
38
- this.elem.trigger('dropdown:ready', [this]);
39
- }
7
+ Romo.trigger(this.elem, 'romoDropdown:ready', [this]);
8
+ });
40
9
 
41
10
  RomoDropdown.prototype.popupOpen = function() {
42
- return this.popupElem.hasClass('romo-dropdown-open') === true;
11
+ return Romo.hasClass(this.popupElem, 'romo-dropdown-open') === true;
43
12
  }
44
13
 
45
14
  RomoDropdown.prototype.popupClosed = function() {
46
- return this.popupElem.hasClass('romo-dropdown-open') === false;
15
+ return Romo.hasClass(this.popupElem, 'romo-dropdown-open') === false;
47
16
  }
48
17
 
49
- RomoDropdown.prototype.doInit = function() {
50
- // override as needed
18
+ RomoDropdown.prototype.doToggle = function() {
19
+ if (this.popupOpen()) {
20
+ Romo.pushFn(Romo.proxy(this.doPopupClose, this));
21
+ } else {
22
+ Romo.pushFn(Romo.proxy(this.doPopupOpen, this));
23
+ }
24
+ Romo.trigger(this.elem, 'romoDropdown:toggle', [this]);
51
25
  }
52
26
 
53
- RomoDropdown.prototype.doInitPopup = function() {
54
- this.popupElem = $('<div class="romo-dropdown-popup"><div class="romo-dropdown-body"></div></div>');
55
- this.popupElem.appendTo(this.elem.closest(this.elem.data('romo-dropdown-append-to-closest') || 'body'));
56
-
57
- this.popupElem.on('modal:popupOpen', $.proxy(function(e) {
58
- this.doUnBindWindowBodyClick();
59
- this.doUnBindWindowBodyKeyUp();
60
- this.doUnBindElemKeyUp();
61
- }, this));
62
- this.popupElem.on('modal:popupClose', $.proxy(function(e) {
63
- this.doBindWindowBodyClick();
64
- this.doBindWindowBodyKeyUp();
65
- this.doBindElemKeyUp();
66
- }, this));
67
-
68
- this.bodyElem = this.popupElem.find('> .romo-dropdown-body');
69
- if (this.elem.data('romo-dropdown-style-class') !== undefined) {
70
- this.bodyElem.addClass(this.elem.data('romo-dropdown-style-class'));
71
- }
27
+ RomoDropdown.prototype.doPopupOpen = function() {
28
+ Romo.popupStack.addElem(
29
+ this.popupElem,
30
+ Romo.proxy(this._openPopup, this),
31
+ Romo.proxy(this._closePopup, this),
32
+ Romo.proxy(this.doPlacePopupElem, this)
33
+ );
34
+ }
72
35
 
73
- this.contentElem = $();
36
+ RomoDropdown.prototype.doPopupClose = function() {
37
+ Romo.popupStack.closeThru(this.popupElem);
38
+ }
74
39
 
75
- var positionData = this._parsePositionData(this.elem.data('romo-dropdown-position'));
76
- this.popupPosition = positionData.position || 'bottom';
77
- this.popupAlignment = positionData.alignment || 'left';
78
- this.popupElem.attr('data-romo-dropdown-position', this.popupPosition);
79
- this.popupElem.attr('data-romo-dropdown-alignment', this.popupAlignment);
80
- this.popupElem.attr('data-romo-dropdown-fixed', this.elem.data('romo-dropdown-fixed'));
40
+ RomoDropdown.prototype.doPlacePopupElem = function() {
41
+ var configHeight = Romo.data(this.elem, 'romo-dropdown-height') ||
42
+ Romo.data(this.elem, 'romo-dropdown-max-height');
43
+ var configPosition = this.popupPosition;
81
44
 
82
- this.doSetPopupZIndex(this.elem);
45
+ if (configHeight === 'detect') {
46
+ var popupHeight = this.popupElem.offsetHeight;
47
+ var topAvailHeight = this._getPopupMaxAvailableHeight('top');
48
+ var bottomAvailHeight = this._getPopupMaxAvailableHeight('bottom');
83
49
 
84
- // don't propagate click events on the popup elem. this prevents the popup
85
- // from closing when clicked (see body click event bind on popup open)
86
- this.popupElem.on('click', function(e) {
87
- if (e !== undefined) {
88
- e.stopPropagation();
50
+ if (popupHeight < topAvailHeight && popupHeight < bottomAvailHeight) {
51
+ // if it fits both ways, use the config position way
52
+ configHeight = this._getPopupMaxAvailableHeight(configPosition);
53
+ } else if (topAvailHeight > bottomAvailHeight) {
54
+ configPosition = 'top';
55
+ configHeight = topAvailHeight;
56
+ } else {
57
+ configPosition = 'bottom';
58
+ configHeight = bottomAvailHeight;
89
59
  }
90
- })
91
-
92
- // the popup should be treated like a child elem. add it to Romo's
93
- // parent-child elems so it will be removed when the elem is removed.
94
- // delay adding it b/c other components may `append` generated dropdowns
95
- // meaning the dropdown is removed and then re-added. if added immediately
96
- // the "remove" part will incorrectly remove the popup.
97
- setTimeout($.proxy(function() {
98
- Romo.parentChildElems.add(this.elem, [this.popupElem]);
99
- }, this), 1);
100
- }
101
-
102
- RomoDropdown.prototype.doInitBody = function() {
103
- this.doResetBody();
104
60
 
105
- this.contentElem = this.bodyElem.find('.romo-dropdown-content').last();
106
- if (this.contentElem.size() === 0) {
107
- this.contentElem = this.bodyElem;
61
+ // remove any height difference between the popup and content elems
62
+ // assumes popup height always greater than or equal to content height
63
+ var contentMaxHeight = configHeight - (popupHeight - this.contentElem.offsetHeight);
64
+ Romo.setStyle(this.contentElem, 'max-height', contentMaxHeight.toString() + 'px');
108
65
  }
109
66
 
110
- this.closeElem = this.popupElem.find('[data-romo-dropdown-close="true"]');
111
- this.closeElem.unbind('click');
112
- this.closeElem.on('click', $.proxy(this.onPopupClose, this));
67
+ var elemRect = this.elem.getBoundingClientRect();
68
+ var elemOffset = Romo.offset(this.elem);
113
69
 
114
- this.contentElem.css({
115
- 'min-height': this.elem.data('romo-dropdown-min-height'),
116
- 'height': this.elem.data('romo-dropdown-height'),
117
- 'overflow-x': this.elem.data('romo-dropdown-overflow-x') || 'auto',
118
- 'overflow-y': this.elem.data('romo-dropdown-overflow-y') || 'auto'
119
- });
70
+ var elemHeight = elemRect.height;
71
+ var elemWidth = elemRect.width;
72
+ var elemTop = elemOffset.top;
73
+ var elemLeft = elemOffset.left
120
74
 
121
- if (this.elem.data('romo-dropdown-max-height') === undefined) {
122
- this.elem.attr('data-romo-dropdown-max-height', 'detect');
123
- }
124
- if (this.elem.data('romo-dropdown-max-height') !== 'detect') {
125
- this.contentElem.css({
126
- 'max-height': this.elem.data('romo-dropdown-max-height')
127
- });
128
- }
75
+ var popupOffsetHeight = this.popupElem.offsetHeight;
76
+ var popupOffsetWidth = this.popupElem.offsetWidth;
129
77
 
130
- if (this.elem.data('romo-dropdown-width') === 'elem') {
131
- this.popupElem.css({
132
- 'width': this.elem.css('width')
133
- });
134
- } else {
135
- this.contentElem.css({
136
- 'min-width': this.elem.data('romo-dropdown-min-width'),
137
- 'max-width': this.elem.data('romo-dropdown-max-width'),
138
- 'width': this.elem.data('romo-dropdown-width')
139
- });
78
+ var posTop = undefined;
79
+ switch (configPosition) {
80
+ case 'top':
81
+ var pad = 2;
82
+ posTop = elemTop - popupOffsetHeight - pad;
83
+ break;
84
+ case 'bottom':
85
+ var pad = 2;
86
+ posTop = elemTop + elemHeight + pad;
87
+ break;
140
88
  }
141
- }
142
-
143
- RomoDropdown.prototype.doResetBody = function() {
144
- this.contentElem.css({
145
- 'min-width': '',
146
- 'max-width': '',
147
- 'width': '',
148
- 'min-height': '',
149
- 'max-height': '',
150
- 'height': '',
151
- 'overflow-x': '',
152
- 'overflow-y': ''
153
- });
154
- }
155
-
156
- RomoDropdown.prototype.doLoadBodyStart = function() {
157
- this.bodyElem.html('');
158
- this.doInitBody();
159
- this.doPlacePopupElem();
160
- this.elem.trigger('dropdown:loadBodyStart', [this]);
161
- }
162
-
163
- RomoDropdown.prototype.doLoadBodySuccess = function(data) {
164
- Romo.initHtml(this.bodyElem, data);
165
- this.doInitBody();
166
- this.doPlacePopupElem();
167
- this.elem.trigger('dropdown:loadBodySuccess', [data, this]);
168
- }
169
-
170
- RomoDropdown.prototype.doLoadBodyError = function(xhr) {
171
- this.elem.trigger('dropdown:loadBodyError', [xhr, this]);
172
- }
173
89
 
174
- RomoDropdown.prototype.onToggleClick = function(e) {
175
- if (e !== undefined) {
176
- e.preventDefault();
90
+ var posLeft = undefined;
91
+ switch (this.popupAlignment) {
92
+ case 'left':
93
+ posLeft = elemLeft;
94
+ break;
95
+ case 'right':
96
+ posLeft = elemLeft + elemWidth - popupOffsetWidth;
97
+ break;
177
98
  }
178
99
 
179
- if (this.elem.hasClass('disabled') === false &&
180
- this.elem.data('romo-dropdown-disable-toggle') !== true) {
181
- this.doToggle();
182
- return true;
183
- }
184
- return false;
100
+ Romo.setStyle(this.popupElem, 'top', this._roundPosOffsetVal(posTop)+'px');
101
+ Romo.setStyle(this.popupElem, 'left', this._roundPosOffsetVal(posLeft)+'px');
185
102
  }
186
103
 
187
- RomoDropdown.prototype.doToggle = function() {
188
- if (this.popupOpen()) {
189
- setTimeout($.proxy(function() {
190
- this.doPopupClose();
191
- }, this), 100);
192
- } else {
193
- setTimeout($.proxy(function() {
194
- this.doPopupOpen();
195
- }, this), 100);
196
- }
197
- this.elem.trigger('dropdown:toggle', [this]);
104
+ RomoDropdown.prototype.doSetPopupZIndex = function(relativeElem) {
105
+ var relativeZIndex = Romo.parseZIndex(relativeElem);
106
+ Romo.setStyle(this.popupElem, 'z-index', relativeZIndex + 1200); // see z-index.css
198
107
  }
199
108
 
200
- RomoDropdown.prototype.onPopupOpen = function(e) {
201
- if (e !== undefined) {
202
- e.preventDefault();
203
- }
109
+ // private
204
110
 
205
- if (this.elem.hasClass('disabled') === false && this.popupClosed()) {
206
- setTimeout($.proxy(function() {
207
- this.doPopupOpen();
208
- }, this), 100);
209
- }
210
- }
111
+ RomoDropdown.prototype._openPopup = function() {
112
+ Romo.on(Romo.scrollableParents(this.elem), 'scroll', this._onScrollableParentsScroll);
211
113
 
212
- RomoDropdown.prototype.doPopupOpen = function() {
213
- if (this.elem.data('romo-dropdown-content-elem') !== undefined) {
214
- this.doLoadBodySuccess($(this.elem.data('romo-dropdown-content-elem')).html())
114
+ if (Romo.data(this.elem, 'romo-dropdown-content-elem') !== undefined) {
115
+ var contentElem = Romo.elems(Romo.data(this.elem, 'romo-dropdown-content-elem'))[0];
116
+ this._loadBodySuccess(contentElem.outerHTML);
215
117
  } else {
216
118
  this.romoAjax.doInvoke();
217
119
  }
218
120
 
219
- this.popupElem.addClass('romo-dropdown-open');
121
+ Romo.addClass(this.popupElem, 'romo-dropdown-open');
220
122
  this.doPlacePopupElem();
221
123
 
222
- // bind an event to close the popup when clicking away from the
223
- // popup. Bind on a timeout to allow time for any toggle
224
- // click event to propagate. If no timeout, we'll bind this
225
- // event, then the toggle click will propagate which will call
226
- // this event and immediately close the popup.
227
- setTimeout($.proxy(function() {
228
- this.doBindWindowBodyClick();
229
- }, this), 100);
230
-
231
- // bind "esc" keystroke to toggle close
232
- this.doBindWindowBodyKeyUp();
233
-
234
- // bind window resizes reposition dropdown
235
- $(window).on('resize', $.proxy(this.onResizeWindow, this));
236
-
237
- this.elem.trigger('dropdown:popupOpen', [this]);
124
+ Romo.trigger(this.elem, 'romoDropdown:popupOpen', [this]);
238
125
  }
239
126
 
240
- RomoDropdown.prototype.onPopupClose = function(e) {
241
- if (e !== undefined) {
242
- e.preventDefault();
243
- }
127
+ RomoDropdown.prototype._closePopup = function() {
128
+ Romo.removeClass(this.popupElem, 'romo-dropdown-open');
129
+ Romo.off(Romo.scrollableParents(this.elem), 'scroll', this._onScrollableParentsScroll);
244
130
 
245
- if (this.elem.hasClass('disabled') === false && this.popupOpen()) {
246
- setTimeout($.proxy(function() {
247
- this.doPopupClose();
248
- }, this), 100);
131
+ if (Romo.data(this.elem, 'romo-dropdown-clear-content') === true) {
132
+ Romo.updateHtml(this.contentElem, '');
249
133
  }
134
+
135
+ Romo.trigger(this.elem, 'romoDropdown:popupClose', [this]);
250
136
  }
251
137
 
252
- RomoDropdown.prototype.doPopupClose = function() {
253
- this.popupElem.removeClass('romo-dropdown-open');
138
+ RomoDropdown.prototype._bindElem = function() {
139
+ this._bindPopup();
140
+ this._bindAjax();
141
+ this._bindBody();
254
142
 
255
- // unbind any event to close the popup when clicking away from it
256
- this.doUnBindWindowBodyClick();
143
+ if (Romo.data(this.elem, 'romo-dropdown-disable-click-invoke') !== true) {
144
+ Romo.on(this.elem, 'click', Romo.proxy(this._onToggle, this));
145
+ }
146
+ Romo.on(this.elem, 'romoDropdown:triggerToggle', Romo.proxy(this._onToggle, this));
147
+ Romo.on(this.elem, 'romoDropdown:triggerPopupOpen', Romo.proxy(this._onPopupOpen, this));
148
+ Romo.on(this.elem, 'romoDropdown:triggerPopupClose', Romo.proxy(this._onPopupClose, this));
149
+ }
150
+
151
+ RomoDropdown.prototype._bindPopup = function() {
152
+ this.popupElem = Romo.elems(
153
+ '<div class="romo-dropdown-popup"><div class="romo-dropdown-body"></div></div>'
154
+ )[0];
155
+ var popupParentElem = Romo.closest(
156
+ this.elem,
157
+ Romo.data(this.elem, 'romo-dropdown-append-to-closest') || 'body'
158
+ );
159
+ Romo.append(popupParentElem, this.popupElem);
160
+
161
+ this.bodyElem = Romo.children(this.popupElem).find(Romo.proxy(function(childElem) {
162
+ return Romo.is(childElem, '.romo-dropdown-body');
163
+ }, this));
164
+ if (Romo.data(this.elem, 'romo-dropdown-style-class') !== undefined) {
165
+ Romo.addClass(this.bodyElem, Romo.data(this.elem, 'romo-dropdown-style-class'));
166
+ }
257
167
 
258
- // unbind "esc" keystroke to toggle close
259
- this.doUnBindWindowBodyKeyUp();
168
+ this.contentElem = undefined;
260
169
 
261
- // unbind window resizes reposition dropdown
262
- $(window).off('resize', $.proxy(this.onResizeWindow, this));
170
+ var positionData = this._parsePositionData(Romo.data(this.elem, 'romo-dropdown-position'));
171
+ this.popupPosition = positionData.position || 'bottom';
172
+ this.popupAlignment = positionData.alignment || 'left';
173
+ Romo.setData(this.popupElem, 'romo-dropdown-position', this.popupPosition);
174
+ Romo.setData(this.popupElem, 'romo-dropdown-alignment', this.popupAlignment);
263
175
 
264
- // clear the content elem markup if configured to
265
- if (this.elem.data('romo-dropdown-clear-content') === true) {
266
- this.contentElem.html('');
267
- }
176
+ this.doSetPopupZIndex(this.elem);
268
177
 
269
- this.elem.trigger('dropdown:popupClose', [this]);
178
+ Romo.parentChildElems.add(this.elem, [this.popupElem]);
179
+ Romo.on(this.popupElem, 'romoParentChildElems:childRemoved', Romo.proxy(function(e, childElem) {
180
+ Romo.popupStack.closeThru(this.popupElem);
181
+ }, this));
182
+ Romo.on(this.popupElem, 'romoPopupStack:popupClosedByEsc', Romo.proxy(function(e, romoPopupStack) {
183
+ Romo.trigger(this.elem, 'romoDropdown:popupClosedByEsc', [this]);
184
+ }, this));
270
185
  }
271
186
 
272
- RomoDropdown.prototype.doBindElemKeyUp = function() {
273
- this.elem.on('keyup', $.proxy(this.onElemKeyUp, this));
274
- this.popupElem.on('keyup', $.proxy(this.onElemKeyUp, this));
275
- }
187
+ RomoDropdown.prototype._bindAjax = function() {
188
+ this.romoAjax = new RomoAjax(this.elem);
189
+ this.romoAjax.doUnbindElem(); // disable auto invoke on click
276
190
 
277
- RomoDropdown.prototype.doUnBindElemKeyUp = function() {
278
- this.elem.off('keyup', $.proxy(this.onElemKeyUp, this));
279
- this.popupElem.off('keyup', $.proxy(this.onElemKeyUp, this));
191
+ Romo.on(this.elem, 'romoAjax:callStart', Romo.proxy(function(e, romoAjax) {
192
+ this._loadBodyStart();
193
+ return false;
194
+ }, this));
195
+ Romo.on(this.elem, 'romoAjax:callSuccess', Romo.proxy(function(e, data, romoAjax) {
196
+ this._loadBodySuccess(data);
197
+ return false;
198
+ }, this));
199
+ Romo.on(this.elem, 'romoAjax:callError', Romo.proxy(function(e, xhr, romoAjax) {
200
+ this._loadBodyError(xhr);
201
+ return false;
202
+ }, this));
280
203
  }
281
204
 
282
- RomoDropdown.prototype.onElemKeyUp = function(e) {
283
- if (this.elem.hasClass('disabled') === false) {
284
- if (this.popupOpen()) {
285
- if(e.keyCode === 27 /* Esc */ ) {
286
- this.doPopupClose();
287
- this.elem.trigger('dropdown:popupClosedByEsc', [this]);
288
- return false;
289
- } else {
290
- return true;
291
- }
292
- } else {
293
- return true;
294
- }
205
+ RomoDropdown.prototype._bindBody = function() {
206
+ this._resetBody();
207
+
208
+ var contentElems = Romo.find(this.bodyElem, '.romo-dropdown-content');
209
+ this.contentElem = contentElems[contentElems.length - 1];
210
+ if (this.contentElem === undefined) {
211
+ this.contentElem = this.bodyElem;
295
212
  }
296
- return true;
297
- }
298
213
 
299
- RomoDropdown.prototype.doBindWindowBodyClick = function() {
300
- $('body').on('click', $.proxy(this.onWindowBodyClick, this));
301
- $('body').on('modal:mousemove', $.proxy(this.onWindowBodyClick, this));
302
- }
214
+ this.closeElems = Romo.find(this.popupElem, '[data-romo-dropdown-close="true"]');
215
+ Romo.on(this.closeElems, 'click', Romo.proxy(this._onPopupClose, this));
303
216
 
304
- RomoDropdown.prototype.doUnBindWindowBodyClick = function() {
305
- $('body').off('click', $.proxy(this.onWindowBodyClick, this));
306
- $('body').off('modal:mousemove', $.proxy(this.onWindowBodyClick, this));
307
- }
217
+ Romo.setStyle(this.contentElem, 'min-height', Romo.data(this.elem, 'romo-dropdown-min-height'));
218
+ Romo.setStyle(this.contentElem, 'height', Romo.data(this.elem, 'romo-dropdown-height'));
219
+ Romo.setStyle(this.contentElem, 'overflow-x', Romo.data(this.elem, 'romo-dropdown-overflow-x') || 'auto');
220
+ Romo.setStyle(this.contentElem, 'overflow-y', Romo.data(this.elem, 'romo-dropdown-overflow-y') || 'auto');
308
221
 
309
- RomoDropdown.prototype.onWindowBodyClick = function(e) {
310
- // if not clicked on the popup elem or the elem
311
- var target = $(e.target);
312
- if (e !== undefined &&
313
- target.parents('.romo-dropdown-popup').size() === 0 &&
314
- target.closest(this.elem).size() === 0) {
315
- this.doPopupClose();
222
+ if (Romo.data(this.elem, 'romo-dropdown-max-height') === undefined) {
223
+ Romo.setData(this.elem, 'romo-dropdown-max-height', 'detect');
224
+ }
225
+ if (Romo.data(this.elem, 'romo-dropdown-max-height') !== 'detect') {
226
+ Romo.setStyle(this.contentElem, 'max-height', Romo.data(this.elem, 'romo-dropdown-max-height'));
316
227
  }
317
- return true;
318
- }
319
-
320
- RomoDropdown.prototype.doBindWindowBodyKeyUp = function() {
321
- $('body').on('keyup', $.proxy(this.onWindowBodyKeyUp, this));
322
- }
323
228
 
324
- RomoDropdown.prototype.doUnBindWindowBodyKeyUp = function() {
325
- $('body').off('keyup', $.proxy(this.onWindowBodyKeyUp, this));
229
+ if (Romo.data(this.elem, 'romo-dropdown-width') === 'elem') {
230
+ Romo.setStyle(this.popupElem, 'width', Romo.css(this.elem, 'width'));
231
+ } else {
232
+ Romo.setStyle(this.contentElem, 'min-width', Romo.data(this.elem, 'romo-dropdown-min-width'));
233
+ Romo.setStyle(this.contentElem, 'max-width', Romo.data(this.elem, 'romo-dropdown-max-width'));
234
+ Romo.setStyle(this.contentElem, 'width', Romo.data(this.elem, 'romo-dropdown-width'));
235
+ }
326
236
  }
327
237
 
328
- RomoDropdown.prototype.onWindowBodyKeyUp = function(e) {
329
- if (e.keyCode === 27 /* Esc */) {
330
- this.doPopupClose();
331
- this.elem.trigger('dropdown:popupClosedByEsc', [this]);
238
+ RomoDropdown.prototype._resetBody = function() {
239
+ if (this.contentElem !== undefined) {
240
+ Romo.rmStyle(this.contentElem, 'min-width');
241
+ Romo.rmStyle(this.contentElem, 'max-width');
242
+ Romo.rmStyle(this.contentElem, 'width');
243
+ Romo.rmStyle(this.contentElem, 'min-height');
244
+ Romo.rmStyle(this.contentElem, 'max-height');
245
+ Romo.rmStyle(this.contentElem, 'height');
246
+ Romo.rmStyle(this.contentElem, 'overflow-x');
247
+ Romo.rmStyle(this.contentElem, 'overflow-y');
332
248
  }
333
- return true;
334
249
  }
335
250
 
336
- RomoDropdown.prototype.onResizeWindow = function(e) {
251
+ RomoDropdown.prototype._loadBodyStart = function() {
252
+ Romo.updateHtml(this.bodyElem, '');
253
+ this._bindBody();
337
254
  this.doPlacePopupElem();
338
- return true;
255
+ Romo.pushFn(Romo.proxy(this.doPlacePopupElem, this));
256
+ Romo.trigger(this.elem, 'romoDropdown:loadBodyStart', [this]);
339
257
  }
340
258
 
341
- RomoDropdown.prototype.doPlacePopupElem = function() {
342
- if (this.elem.parents('.romo-modal-popup').size() !== 0) {
343
- this.popupElem.css({'position': 'fixed'});
344
- }
345
-
346
- var pos = $.extend({}, this.elem[0].getBoundingClientRect(), this.elem.offset());
347
- var w = this.popupElem[0].offsetWidth;
348
- var h = this.popupElem[0].offsetHeight;
349
- var offset = {};
350
-
351
- var configHeight = this.elem.data('romo-dropdown-height') || this.elem.data('romo-dropdown-max-height');
352
- var configPosition = this.popupPosition;
353
-
354
- if (configHeight === 'detect') {
355
- var popupHeight = this.popupElem.height();
356
- var topAvailHeight = this._getPopupMaxAvailableHeight('top');
357
- var bottomAvailHeight = this._getPopupMaxAvailableHeight('bottom');
358
-
359
- if (popupHeight < topAvailHeight && popupHeight < bottomAvailHeight) {
360
- // if it fits both ways, use the config position way
361
- configHeight = this._getPopupMaxAvailableHeight(configPosition);
362
- } else if (topAvailHeight > bottomAvailHeight) {
363
- configPosition = 'top';
364
- configHeight = topAvailHeight;
365
- } else {
366
- configPosition = 'bottom';
367
- configHeight = bottomAvailHeight;
368
- }
369
-
370
- // remove any height difference between the popup and content elems
371
- // assumes popup height always greater than or equal to content height
372
- configHeight = configHeight - (h - this.contentElem[0].offsetHeight);
373
- this.contentElem.css({'max-height': configHeight.toString() + 'px'});
374
- }
375
-
376
- if(h > configHeight) {
377
- h = configHeight;
378
- }
379
-
380
- switch (configPosition) {
381
- case 'top':
382
- var pad = 2;
383
- $.extend(offset, { top: pos.top - h - pad });
384
- break;
385
- case 'bottom':
386
- var pad = 2;
387
- $.extend(offset, { top: pos.top + pos.height + pad });
388
- break;
389
- }
390
- switch (this.popupAlignment) {
391
- case 'left':
392
- $.extend(offset, { left: pos.left });
393
- break;
394
- case 'right':
395
- $.extend(offset, { left: pos.left + pos.width - w });
396
- break;
397
- }
398
-
399
- $.extend(offset, {
400
- top: this._roundPosOffsetVal(offset['top']),
401
- left: this._roundPosOffsetVal(offset['left'])
402
- });
403
- this.popupElem.offset(offset);
259
+ RomoDropdown.prototype._loadBodySuccess = function(data) {
260
+ Romo.initUpdateHtml(this.bodyElem, data);
261
+ this._bindBody();
262
+ this.doPlacePopupElem();
263
+ Romo.pushFn(Romo.proxy(this.doPlacePopupElem, this));
264
+ Romo.trigger(this.elem, 'romoDropdown:loadBodySuccess', [data, this]);
404
265
  }
405
266
 
406
- RomoDropdown.prototype.doSetPopupZIndex = function(relativeElem) {
407
- var relativeZIndex = Romo.parseZIndex(relativeElem);
408
- this.popupElem.css({'z-index': relativeZIndex + 1200}); // see z-index.css
267
+ RomoDropdown.prototype._loadBodyError = function(xhr) {
268
+ Romo.trigger(this.elem, 'romoDropdown:loadBodyError', [xhr, this]);
409
269
  }
410
270
 
411
271
  RomoDropdown.prototype._parsePositionData = function(posString) {
@@ -418,12 +278,13 @@ RomoDropdown.prototype._getPopupMaxAvailableHeight = function(position) {
418
278
 
419
279
  switch (position) {
420
280
  case 'top':
421
- var elemTop = this.elem[0].getBoundingClientRect().top;
281
+ var elemTop = this.elem.getBoundingClientRect().top;
422
282
  maxHeight = elemTop - this._getPopupMaxHeightDetectPad(position);
423
283
  break;
424
284
  case 'bottom':
425
- var elemBottom = this.elem[0].getBoundingClientRect().bottom;
426
- maxHeight = $(window).height() - elemBottom - this._getPopupMaxHeightDetectPad(position);
285
+ var viewportHeight = document.documentElement.clientHeight;
286
+ var elemBottom = this.elem.getBoundingClientRect().bottom;
287
+ maxHeight = viewportHeight - elemBottom - this._getPopupMaxHeightDetectPad(position);
427
288
  break;
428
289
  }
429
290
 
@@ -431,13 +292,43 @@ RomoDropdown.prototype._getPopupMaxAvailableHeight = function(position) {
431
292
  }
432
293
 
433
294
  RomoDropdown.prototype._getPopupMaxHeightDetectPad = function(position) {
434
- return this.elem.data('romo-dropdown-max-height-detect-pad-'+position) || this.elem.data('romo-dropdown-max-height-detect-pad') || 10;
295
+ return Romo.data(this.elem, 'romo-dropdown-max-height-detect-pad-'+position) || Romo.data(this.elem, 'romo-dropdown-max-height-detect-pad') || 10;
435
296
  }
436
297
 
437
298
  RomoDropdown.prototype._roundPosOffsetVal = function(value) {
438
299
  return Math.round(value*100) / 100;
439
300
  }
440
301
 
441
- Romo.onInitUI(function(e) {
442
- Romo.initUIElems(e, '[data-romo-dropdown-auto="true"]').romoDropdown();
443
- });
302
+ // event functions
303
+
304
+ RomoDropdown.prototype.romoEvFn._onToggle = function(e) {
305
+ e.preventDefault();
306
+
307
+ if (
308
+ Romo.hasClass(this.elem, 'disabled') === false &&
309
+ Romo.data(this.elem, 'romo-dropdown-disable-toggle') !== true
310
+ ) {
311
+ this.doToggle();
312
+ }
313
+ }
314
+
315
+ RomoDropdown.prototype.romoEvFn._onPopupOpen = function(e) {
316
+ if (Romo.hasClass(this.elem, 'disabled') === false && this.popupClosed()) {
317
+ Romo.pushFn(Romo.proxy(this.doPopupOpen, this));
318
+ }
319
+ }
320
+
321
+ RomoDropdown.prototype.romoEvFn._onPopupClose = function(e) {
322
+ if (Romo.hasClass(this.elem, 'disabled') === false && this.popupOpen()) {
323
+ Romo.pushFn(Romo.proxy(this.doPopupClose, this));
324
+ }
325
+ }
326
+
327
+ RomoDropdown.prototype.romoEvFn._onScrollableParentsScroll = function(e) {
328
+ Romo.popupStack.placeAllPopups();
329
+ }
330
+
331
+ // init
332
+
333
+ Romo.popupStack.addStyleClass('romo-dropdown-popup');
334
+ Romo.addElemsInitSelector('[data-romo-dropdown-auto="true"]', RomoDropdown);