decidim-gallery 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +30 -0
- data/Rakefile +9 -0
- data/app/cells/decidim/gallery/main/image.erb +51 -0
- data/app/cells/decidim/gallery/main/image_collection.erb +13 -0
- data/app/cells/decidim/gallery/main/image_list.erb +9 -0
- data/app/cells/decidim/gallery/main/video.erb +20 -0
- data/app/cells/decidim/gallery/main/video_collection.erb +3 -0
- data/app/cells/decidim/gallery/main_cell.rb +88 -0
- data/app/cells/decidim/gallery/video/show.erb +6 -0
- data/app/cells/decidim/gallery/video_cell.rb +96 -0
- data/app/commands/decidim/gallery/admin/create_gallery_item.rb +50 -0
- data/app/commands/decidim/gallery/admin/publish_gallery_item.rb +38 -0
- data/app/commands/decidim/gallery/admin/unpublish_gallery_item.rb +38 -0
- data/app/commands/decidim/gallery/admin/update_gallery_item.rb +44 -0
- data/app/controllers/decidim/gallery/admin/application_controller.rb +24 -0
- data/app/controllers/decidim/gallery/admin/gallery_item_controller.rb +104 -0
- data/app/controllers/decidim/gallery/application_controller.rb +8 -0
- data/app/controllers/decidim/gallery/gallery_controller.rb +9 -0
- data/app/forms/decidim/gallery/admin/gallery_item_form.rb +17 -0
- data/app/forms/decidim/gallery/admin/gallery_item_image_form.rb +14 -0
- data/app/forms/decidim/gallery/admin/gallery_item_video_form.rb +12 -0
- data/app/helpers/decidim/gallery/admin/application_helper.rb +18 -0
- data/app/model/decidim/gallery/application_record.rb +10 -0
- data/app/model/decidim/gallery/gallery_item.rb +38 -0
- data/app/overrides/decidim/admin/static_pages/edit/add_gallery.html.erb.deface +11 -0
- data/app/overrides/decidim/pages/_standalone/add_content_blocks.html.erb.deface +7 -0
- data/app/overrides/decidim/pages/_tabbed/add_content_blocks.html.erb.deface +5 -0
- data/app/packs/entrypoints/decidim_gallery.js +3 -0
- data/app/packs/images/decidim/gallery/icon.svg +1 -0
- data/app/packs/src/decidim/gallery/gallery.js +42 -0
- data/app/packs/src/decidim/gallery/masonry/EvEmitter.js +85 -0
- data/app/packs/src/decidim/gallery/masonry/getSize.js +181 -0
- data/app/packs/src/decidim/gallery/masonry/jQueryBridget.js +109 -0
- data/app/packs/src/decidim/gallery/masonry/masonry.js +202 -0
- data/app/packs/src/decidim/gallery/masonry/matchesSelector.js +25 -0
- data/app/packs/src/decidim/gallery/masonry/outlayer.js +885 -0
- data/app/packs/src/decidim/gallery/masonry/outlayerItem.js +522 -0
- data/app/packs/src/decidim/gallery/masonry/utils.js +203 -0
- data/app/packs/stylesheets/decidim/gallery/_gallery.scss +3 -0
- data/app/permissions/decidim/gallery/admin/permissions.rb +18 -0
- data/app/permissions/decidim/gallery/permissions.rb +17 -0
- data/app/views/decidim/gallery/admin/gallery_item/_form_image.html.erb +16 -0
- data/app/views/decidim/gallery/admin/gallery_item/_form_video.html.erb +16 -0
- data/app/views/decidim/gallery/admin/gallery_item/edit.html.erb +9 -0
- data/app/views/decidim/gallery/admin/gallery_item/index.html.erb +52 -0
- data/app/views/decidim/gallery/admin/gallery_item/new.html.erb +9 -0
- data/app/views/decidim/gallery/gallery/index.html.erb +11 -0
- data/config/assets.rb +9 -0
- data/config/i18n-tasks.yml +22 -0
- data/config/locales/en.yml +79 -0
- data/config/locales/fr.yml +79 -0
- data/config/locales/ro.yml +79 -0
- data/lib/decidim/gallery/admin/static_pages/command.rb +15 -0
- data/lib/decidim/gallery/admin/static_pages/form.rb +21 -0
- data/lib/decidim/gallery/admin.rb +14 -0
- data/lib/decidim/gallery/admin_engine.rb +27 -0
- data/lib/decidim/gallery/component.rb +47 -0
- data/lib/decidim/gallery/engine.rb +60 -0
- data/lib/decidim/gallery/test/factories.rb +58 -0
- data/lib/decidim/gallery/version.rb +14 -0
- data/lib/decidim/gallery.rb +14 -0
- data/lib/tasks/decidim_gallery.rake +16 -0
- metadata +163 -0
@@ -0,0 +1,522 @@
|
|
1
|
+
import EvEmitter from "./EvEmitter"
|
2
|
+
import getSize from "./getSize";
|
3
|
+
|
4
|
+
// ----- helpers ----- //
|
5
|
+
|
6
|
+
function isEmptyObj( obj ) {
|
7
|
+
for ( var prop in obj ) {
|
8
|
+
return false;
|
9
|
+
}
|
10
|
+
prop = null;
|
11
|
+
return true;
|
12
|
+
}
|
13
|
+
|
14
|
+
// -------------------------- CSS3 support -------------------------- //
|
15
|
+
|
16
|
+
|
17
|
+
var docElemStyle = document.documentElement.style;
|
18
|
+
|
19
|
+
var transitionProperty = typeof docElemStyle.transition == 'string' ?
|
20
|
+
'transition' : 'WebkitTransition';
|
21
|
+
var transformProperty = typeof docElemStyle.transform == 'string' ?
|
22
|
+
'transform' : 'WebkitTransform';
|
23
|
+
|
24
|
+
var transitionEndEvent = {
|
25
|
+
WebkitTransition: 'webkitTransitionEnd',
|
26
|
+
transition: 'transitionend'
|
27
|
+
}[ transitionProperty ];
|
28
|
+
|
29
|
+
// cache all vendor properties that could have vendor prefix
|
30
|
+
var vendorProperties = {
|
31
|
+
transform: transformProperty,
|
32
|
+
transition: transitionProperty,
|
33
|
+
transitionDuration: transitionProperty + 'Duration',
|
34
|
+
transitionProperty: transitionProperty + 'Property',
|
35
|
+
transitionDelay: transitionProperty + 'Delay'
|
36
|
+
};
|
37
|
+
|
38
|
+
// -------------------------- Item -------------------------- //
|
39
|
+
|
40
|
+
function Item( element, layout ) {
|
41
|
+
if ( !element ) {
|
42
|
+
return;
|
43
|
+
}
|
44
|
+
|
45
|
+
this.element = element;
|
46
|
+
// parent layout class, i.e. Masonry, Isotope, or Packery
|
47
|
+
this.layout = layout;
|
48
|
+
this.position = {
|
49
|
+
x: 0,
|
50
|
+
y: 0
|
51
|
+
};
|
52
|
+
|
53
|
+
this._create();
|
54
|
+
}
|
55
|
+
|
56
|
+
// inherit EvEmitter
|
57
|
+
var proto = Item.prototype = Object.create( EvEmitter.prototype );
|
58
|
+
proto.constructor = Item;
|
59
|
+
|
60
|
+
proto._create = function() {
|
61
|
+
// transition objects
|
62
|
+
this._transn = {
|
63
|
+
ingProperties: {},
|
64
|
+
clean: {},
|
65
|
+
onEnd: {}
|
66
|
+
};
|
67
|
+
|
68
|
+
this.css({
|
69
|
+
position: 'absolute'
|
70
|
+
});
|
71
|
+
};
|
72
|
+
|
73
|
+
// trigger specified handler for event type
|
74
|
+
proto.handleEvent = function( event ) {
|
75
|
+
var method = 'on' + event.type;
|
76
|
+
if ( this[ method ] ) {
|
77
|
+
this[ method ]( event );
|
78
|
+
}
|
79
|
+
};
|
80
|
+
|
81
|
+
proto.getSize = function() {
|
82
|
+
this.size = getSize( this.element );
|
83
|
+
};
|
84
|
+
|
85
|
+
/**
|
86
|
+
* apply CSS styles to element
|
87
|
+
* @param {Object} style
|
88
|
+
*/
|
89
|
+
proto.css = function( style ) {
|
90
|
+
var elemStyle = this.element.style;
|
91
|
+
|
92
|
+
for ( var prop in style ) {
|
93
|
+
// use vendor property if available
|
94
|
+
var supportedProp = vendorProperties[ prop ] || prop;
|
95
|
+
elemStyle[ supportedProp ] = style[ prop ];
|
96
|
+
}
|
97
|
+
};
|
98
|
+
|
99
|
+
// measure position, and sets it
|
100
|
+
proto.getPosition = function() {
|
101
|
+
var style = getComputedStyle( this.element );
|
102
|
+
var isOriginLeft = this.layout._getOption('originLeft');
|
103
|
+
var isOriginTop = this.layout._getOption('originTop');
|
104
|
+
var xValue = style[ isOriginLeft ? 'left' : 'right' ];
|
105
|
+
var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
|
106
|
+
var x = parseFloat( xValue );
|
107
|
+
var y = parseFloat( yValue );
|
108
|
+
// convert percent to pixels
|
109
|
+
var layoutSize = this.layout.size;
|
110
|
+
if ( xValue.indexOf('%') != -1 ) {
|
111
|
+
x = ( x / 100 ) * layoutSize.width;
|
112
|
+
}
|
113
|
+
if ( yValue.indexOf('%') != -1 ) {
|
114
|
+
y = ( y / 100 ) * layoutSize.height;
|
115
|
+
}
|
116
|
+
// clean up 'auto' or other non-integer values
|
117
|
+
x = isNaN( x ) ? 0 : x;
|
118
|
+
y = isNaN( y ) ? 0 : y;
|
119
|
+
// remove padding from measurement
|
120
|
+
x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
|
121
|
+
y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
|
122
|
+
|
123
|
+
this.position.x = x;
|
124
|
+
this.position.y = y;
|
125
|
+
};
|
126
|
+
|
127
|
+
// set settled position, apply padding
|
128
|
+
proto.layoutPosition = function() {
|
129
|
+
var layoutSize = this.layout.size;
|
130
|
+
var style = {};
|
131
|
+
var isOriginLeft = this.layout._getOption('originLeft');
|
132
|
+
var isOriginTop = this.layout._getOption('originTop');
|
133
|
+
|
134
|
+
// x
|
135
|
+
var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
|
136
|
+
var xProperty = isOriginLeft ? 'left' : 'right';
|
137
|
+
var xResetProperty = isOriginLeft ? 'right' : 'left';
|
138
|
+
|
139
|
+
var x = this.position.x + layoutSize[ xPadding ];
|
140
|
+
// set in percentage or pixels
|
141
|
+
style[ xProperty ] = this.getXValue( x );
|
142
|
+
// reset other property
|
143
|
+
style[ xResetProperty ] = '';
|
144
|
+
|
145
|
+
// y
|
146
|
+
var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
|
147
|
+
var yProperty = isOriginTop ? 'top' : 'bottom';
|
148
|
+
var yResetProperty = isOriginTop ? 'bottom' : 'top';
|
149
|
+
|
150
|
+
var y = this.position.y + layoutSize[ yPadding ];
|
151
|
+
// set in percentage or pixels
|
152
|
+
style[ yProperty ] = this.getYValue( y );
|
153
|
+
// reset other property
|
154
|
+
style[ yResetProperty ] = '';
|
155
|
+
|
156
|
+
this.css( style );
|
157
|
+
this.emitEvent( 'layout', [ this ] );
|
158
|
+
};
|
159
|
+
|
160
|
+
proto.getXValue = function( x ) {
|
161
|
+
var isHorizontal = this.layout._getOption('horizontal');
|
162
|
+
return this.layout.options.percentPosition && !isHorizontal ?
|
163
|
+
( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
|
164
|
+
};
|
165
|
+
|
166
|
+
proto.getYValue = function( y ) {
|
167
|
+
var isHorizontal = this.layout._getOption('horizontal');
|
168
|
+
return this.layout.options.percentPosition && isHorizontal ?
|
169
|
+
( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
|
170
|
+
};
|
171
|
+
|
172
|
+
proto._transitionTo = function( x, y ) {
|
173
|
+
this.getPosition();
|
174
|
+
// get current x & y from top/left
|
175
|
+
var curX = this.position.x;
|
176
|
+
var curY = this.position.y;
|
177
|
+
|
178
|
+
var didNotMove = x == this.position.x && y == this.position.y;
|
179
|
+
|
180
|
+
// save end position
|
181
|
+
this.setPosition( x, y );
|
182
|
+
|
183
|
+
// if did not move and not transitioning, just go to layout
|
184
|
+
if ( didNotMove && !this.isTransitioning ) {
|
185
|
+
this.layoutPosition();
|
186
|
+
return;
|
187
|
+
}
|
188
|
+
|
189
|
+
var transX = x - curX;
|
190
|
+
var transY = y - curY;
|
191
|
+
var transitionStyle = {};
|
192
|
+
transitionStyle.transform = this.getTranslate( transX, transY );
|
193
|
+
|
194
|
+
this.transition({
|
195
|
+
to: transitionStyle,
|
196
|
+
onTransitionEnd: {
|
197
|
+
transform: this.layoutPosition
|
198
|
+
},
|
199
|
+
isCleaning: true
|
200
|
+
});
|
201
|
+
};
|
202
|
+
|
203
|
+
proto.getTranslate = function( x, y ) {
|
204
|
+
// flip cooridinates if origin on right or bottom
|
205
|
+
var isOriginLeft = this.layout._getOption('originLeft');
|
206
|
+
var isOriginTop = this.layout._getOption('originTop');
|
207
|
+
x = isOriginLeft ? x : -x;
|
208
|
+
y = isOriginTop ? y : -y;
|
209
|
+
return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
|
210
|
+
};
|
211
|
+
|
212
|
+
// non transition + transform support
|
213
|
+
proto.goTo = function( x, y ) {
|
214
|
+
this.setPosition( x, y );
|
215
|
+
this.layoutPosition();
|
216
|
+
};
|
217
|
+
|
218
|
+
proto.moveTo = proto._transitionTo;
|
219
|
+
|
220
|
+
proto.setPosition = function( x, y ) {
|
221
|
+
this.position.x = parseFloat( x );
|
222
|
+
this.position.y = parseFloat( y );
|
223
|
+
};
|
224
|
+
|
225
|
+
// ----- transition ----- //
|
226
|
+
|
227
|
+
/**
|
228
|
+
* @param {Object} style - CSS
|
229
|
+
* @param {Function} onTransitionEnd
|
230
|
+
*/
|
231
|
+
|
232
|
+
// non transition, just trigger callback
|
233
|
+
proto._nonTransition = function( args ) {
|
234
|
+
this.css( args.to );
|
235
|
+
if ( args.isCleaning ) {
|
236
|
+
this._removeStyles( args.to );
|
237
|
+
}
|
238
|
+
for ( var prop in args.onTransitionEnd ) {
|
239
|
+
args.onTransitionEnd[ prop ].call( this );
|
240
|
+
}
|
241
|
+
};
|
242
|
+
|
243
|
+
/**
|
244
|
+
* proper transition
|
245
|
+
* @param {Object} args - arguments
|
246
|
+
* @param {Object} to - style to transition to
|
247
|
+
* @param {Object} from - style to start transition from
|
248
|
+
* @param {Boolean} isCleaning - removes transition styles after transition
|
249
|
+
* @param {Function} onTransitionEnd - callback
|
250
|
+
*/
|
251
|
+
proto.transition = function( args ) {
|
252
|
+
// redirect to nonTransition if no transition duration
|
253
|
+
if ( !parseFloat( this.layout.options.transitionDuration ) ) {
|
254
|
+
this._nonTransition( args );
|
255
|
+
return;
|
256
|
+
}
|
257
|
+
|
258
|
+
var _transition = this._transn;
|
259
|
+
// keep track of onTransitionEnd callback by css property
|
260
|
+
for ( var prop in args.onTransitionEnd ) {
|
261
|
+
_transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
|
262
|
+
}
|
263
|
+
// keep track of properties that are transitioning
|
264
|
+
for ( prop in args.to ) {
|
265
|
+
_transition.ingProperties[ prop ] = true;
|
266
|
+
// keep track of properties to clean up when transition is done
|
267
|
+
if ( args.isCleaning ) {
|
268
|
+
_transition.clean[ prop ] = true;
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
// set from styles
|
273
|
+
if ( args.from ) {
|
274
|
+
this.css( args.from );
|
275
|
+
// force redraw. http://blog.alexmaccaw.com/css-transitions
|
276
|
+
var h = this.element.offsetHeight;
|
277
|
+
// hack for JSHint to hush about unused var
|
278
|
+
h = null;
|
279
|
+
}
|
280
|
+
// enable transition
|
281
|
+
this.enableTransition( args.to );
|
282
|
+
// set styles that are transitioning
|
283
|
+
this.css( args.to );
|
284
|
+
|
285
|
+
this.isTransitioning = true;
|
286
|
+
|
287
|
+
};
|
288
|
+
|
289
|
+
// dash before all cap letters, including first for
|
290
|
+
// WebkitTransform => -webkit-transform
|
291
|
+
function toDashedAll( str ) {
|
292
|
+
return str.replace( /([A-Z])/g, function( $1 ) {
|
293
|
+
return '-' + $1.toLowerCase();
|
294
|
+
});
|
295
|
+
}
|
296
|
+
|
297
|
+
var transitionProps = 'opacity,' + toDashedAll( transformProperty );
|
298
|
+
|
299
|
+
proto.enableTransition = function(/* style */) {
|
300
|
+
// HACK changing transitionProperty during a transition
|
301
|
+
// will cause transition to jump
|
302
|
+
if ( this.isTransitioning ) {
|
303
|
+
return;
|
304
|
+
}
|
305
|
+
|
306
|
+
// make `transition: foo, bar, baz` from style object
|
307
|
+
// HACK un-comment this when enableTransition can work
|
308
|
+
// while a transition is happening
|
309
|
+
// var transitionValues = [];
|
310
|
+
// for ( var prop in style ) {
|
311
|
+
// // dash-ify camelCased properties like WebkitTransition
|
312
|
+
// prop = vendorProperties[ prop ] || prop;
|
313
|
+
// transitionValues.push( toDashedAll( prop ) );
|
314
|
+
// }
|
315
|
+
// munge number to millisecond, to match stagger
|
316
|
+
var duration = this.layout.options.transitionDuration;
|
317
|
+
duration = typeof duration == 'number' ? duration + 'ms' : duration;
|
318
|
+
// enable transition styles
|
319
|
+
this.css({
|
320
|
+
transitionProperty: transitionProps,
|
321
|
+
transitionDuration: duration,
|
322
|
+
transitionDelay: this.staggerDelay || 0
|
323
|
+
});
|
324
|
+
// listen for transition end event
|
325
|
+
this.element.addEventListener( transitionEndEvent, this, false );
|
326
|
+
};
|
327
|
+
|
328
|
+
// ----- events ----- //
|
329
|
+
|
330
|
+
proto.onwebkitTransitionEnd = function( event ) {
|
331
|
+
this.ontransitionend( event );
|
332
|
+
};
|
333
|
+
|
334
|
+
proto.onotransitionend = function( event ) {
|
335
|
+
this.ontransitionend( event );
|
336
|
+
};
|
337
|
+
|
338
|
+
// properties that I munge to make my life easier
|
339
|
+
var dashedVendorProperties = {
|
340
|
+
'-webkit-transform': 'transform'
|
341
|
+
};
|
342
|
+
|
343
|
+
proto.ontransitionend = function( event ) {
|
344
|
+
// disregard bubbled events from children
|
345
|
+
if ( event.target !== this.element ) {
|
346
|
+
return;
|
347
|
+
}
|
348
|
+
var _transition = this._transn;
|
349
|
+
// get property name of transitioned property, convert to prefix-free
|
350
|
+
var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
|
351
|
+
|
352
|
+
// remove property that has completed transitioning
|
353
|
+
delete _transition.ingProperties[ propertyName ];
|
354
|
+
// check if any properties are still transitioning
|
355
|
+
if ( isEmptyObj( _transition.ingProperties ) ) {
|
356
|
+
// all properties have completed transitioning
|
357
|
+
this.disableTransition();
|
358
|
+
}
|
359
|
+
// clean style
|
360
|
+
if ( propertyName in _transition.clean ) {
|
361
|
+
// clean up style
|
362
|
+
this.element.style[ event.propertyName ] = '';
|
363
|
+
delete _transition.clean[ propertyName ];
|
364
|
+
}
|
365
|
+
// trigger onTransitionEnd callback
|
366
|
+
if ( propertyName in _transition.onEnd ) {
|
367
|
+
var onTransitionEnd = _transition.onEnd[ propertyName ];
|
368
|
+
onTransitionEnd.call( this );
|
369
|
+
delete _transition.onEnd[ propertyName ];
|
370
|
+
}
|
371
|
+
|
372
|
+
this.emitEvent( 'transitionEnd', [ this ] );
|
373
|
+
};
|
374
|
+
|
375
|
+
proto.disableTransition = function() {
|
376
|
+
this.removeTransitionStyles();
|
377
|
+
this.element.removeEventListener( transitionEndEvent, this, false );
|
378
|
+
this.isTransitioning = false;
|
379
|
+
};
|
380
|
+
|
381
|
+
/**
|
382
|
+
* removes style property from element
|
383
|
+
* @param {Object} style
|
384
|
+
**/
|
385
|
+
proto._removeStyles = function( style ) {
|
386
|
+
// clean up transition styles
|
387
|
+
var cleanStyle = {};
|
388
|
+
for ( var prop in style ) {
|
389
|
+
cleanStyle[ prop ] = '';
|
390
|
+
}
|
391
|
+
this.css( cleanStyle );
|
392
|
+
};
|
393
|
+
|
394
|
+
var cleanTransitionStyle = {
|
395
|
+
transitionProperty: '',
|
396
|
+
transitionDuration: '',
|
397
|
+
transitionDelay: ''
|
398
|
+
};
|
399
|
+
|
400
|
+
proto.removeTransitionStyles = function() {
|
401
|
+
// remove transition
|
402
|
+
this.css( cleanTransitionStyle );
|
403
|
+
};
|
404
|
+
|
405
|
+
// ----- stagger ----- //
|
406
|
+
|
407
|
+
proto.stagger = function( delay ) {
|
408
|
+
delay = isNaN( delay ) ? 0 : delay;
|
409
|
+
this.staggerDelay = delay + 'ms';
|
410
|
+
};
|
411
|
+
|
412
|
+
// ----- show/hide/remove ----- //
|
413
|
+
|
414
|
+
// remove element from DOM
|
415
|
+
proto.removeElem = function() {
|
416
|
+
this.element.parentNode.removeChild( this.element );
|
417
|
+
// remove display: none
|
418
|
+
this.css({ display: '' });
|
419
|
+
this.emitEvent( 'remove', [ this ] );
|
420
|
+
};
|
421
|
+
|
422
|
+
proto.remove = function() {
|
423
|
+
// just remove element if no transition support or no transition
|
424
|
+
if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
|
425
|
+
this.removeElem();
|
426
|
+
return;
|
427
|
+
}
|
428
|
+
|
429
|
+
// start transition
|
430
|
+
this.once( 'transitionEnd', function() {
|
431
|
+
this.removeElem();
|
432
|
+
});
|
433
|
+
this.hide();
|
434
|
+
};
|
435
|
+
|
436
|
+
proto.reveal = function() {
|
437
|
+
delete this.isHidden;
|
438
|
+
// remove display: none
|
439
|
+
this.css({ display: '' });
|
440
|
+
|
441
|
+
var options = this.layout.options;
|
442
|
+
|
443
|
+
var onTransitionEnd = {};
|
444
|
+
var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
|
445
|
+
onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
|
446
|
+
|
447
|
+
this.transition({
|
448
|
+
from: options.hiddenStyle,
|
449
|
+
to: options.visibleStyle,
|
450
|
+
isCleaning: true,
|
451
|
+
onTransitionEnd: onTransitionEnd
|
452
|
+
});
|
453
|
+
};
|
454
|
+
|
455
|
+
proto.onRevealTransitionEnd = function() {
|
456
|
+
// check if still visible
|
457
|
+
// during transition, item may have been hidden
|
458
|
+
if ( !this.isHidden ) {
|
459
|
+
this.emitEvent('reveal');
|
460
|
+
}
|
461
|
+
};
|
462
|
+
|
463
|
+
/**
|
464
|
+
* get style property use for hide/reveal transition end
|
465
|
+
* @param {String} styleProperty - hiddenStyle/visibleStyle
|
466
|
+
* @returns {String}
|
467
|
+
*/
|
468
|
+
proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
|
469
|
+
var optionStyle = this.layout.options[ styleProperty ];
|
470
|
+
// use opacity
|
471
|
+
if ( optionStyle.opacity ) {
|
472
|
+
return 'opacity';
|
473
|
+
}
|
474
|
+
// get first property
|
475
|
+
for ( var prop in optionStyle ) {
|
476
|
+
return prop;
|
477
|
+
}
|
478
|
+
};
|
479
|
+
|
480
|
+
proto.hide = function() {
|
481
|
+
// set flag
|
482
|
+
this.isHidden = true;
|
483
|
+
// remove display: none
|
484
|
+
this.css({ display: '' });
|
485
|
+
|
486
|
+
var options = this.layout.options;
|
487
|
+
|
488
|
+
var onTransitionEnd = {};
|
489
|
+
var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
|
490
|
+
onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
|
491
|
+
|
492
|
+
this.transition({
|
493
|
+
from: options.visibleStyle,
|
494
|
+
to: options.hiddenStyle,
|
495
|
+
// keep hidden stuff hidden
|
496
|
+
isCleaning: true,
|
497
|
+
onTransitionEnd: onTransitionEnd
|
498
|
+
});
|
499
|
+
};
|
500
|
+
|
501
|
+
proto.onHideTransitionEnd = function() {
|
502
|
+
// check if still hidden
|
503
|
+
// during transition, item may have been un-hidden
|
504
|
+
if ( this.isHidden ) {
|
505
|
+
this.css({ display: 'none' });
|
506
|
+
this.emitEvent('hide');
|
507
|
+
}
|
508
|
+
};
|
509
|
+
|
510
|
+
proto.destroy = function() {
|
511
|
+
this.css({
|
512
|
+
position: '',
|
513
|
+
left: '',
|
514
|
+
right: '',
|
515
|
+
top: '',
|
516
|
+
bottom: '',
|
517
|
+
transition: '',
|
518
|
+
transform: ''
|
519
|
+
});
|
520
|
+
};
|
521
|
+
|
522
|
+
export default Item;
|
@@ -0,0 +1,203 @@
|
|
1
|
+
import matchesSelector from "./matchesSelector";
|
2
|
+
|
3
|
+
var utils = {};
|
4
|
+
|
5
|
+
// ----- extend ----- //
|
6
|
+
|
7
|
+
// extends objects
|
8
|
+
utils.extend = function( a, b ) {
|
9
|
+
for ( var prop in b ) {
|
10
|
+
a[ prop ] = b[ prop ];
|
11
|
+
}
|
12
|
+
return a;
|
13
|
+
};
|
14
|
+
|
15
|
+
// ----- modulo ----- //
|
16
|
+
|
17
|
+
utils.modulo = function( num, div ) {
|
18
|
+
return ( ( num % div ) + div ) % div;
|
19
|
+
};
|
20
|
+
|
21
|
+
// ----- makeArray ----- //
|
22
|
+
|
23
|
+
var arraySlice = Array.prototype.slice;
|
24
|
+
|
25
|
+
// turn element or nodeList into an array
|
26
|
+
utils.makeArray = function( obj ) {
|
27
|
+
if ( Array.isArray( obj ) ) {
|
28
|
+
// use object if already an array
|
29
|
+
return obj;
|
30
|
+
}
|
31
|
+
// return empty array if undefined or null. #6
|
32
|
+
if ( obj === null || obj === undefined ) {
|
33
|
+
return [];
|
34
|
+
}
|
35
|
+
|
36
|
+
var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
|
37
|
+
if ( isArrayLike ) {
|
38
|
+
// convert nodeList to array
|
39
|
+
return arraySlice.call( obj );
|
40
|
+
}
|
41
|
+
|
42
|
+
// array of single index
|
43
|
+
return [ obj ];
|
44
|
+
};
|
45
|
+
|
46
|
+
// ----- removeFrom ----- //
|
47
|
+
|
48
|
+
utils.removeFrom = function( ary, obj ) {
|
49
|
+
var index = ary.indexOf( obj );
|
50
|
+
if ( index != -1 ) {
|
51
|
+
ary.splice( index, 1 );
|
52
|
+
}
|
53
|
+
};
|
54
|
+
|
55
|
+
// ----- getParent ----- //
|
56
|
+
|
57
|
+
utils.getParent = function( elem, selector ) {
|
58
|
+
while ( elem.parentNode && elem != document.body ) {
|
59
|
+
elem = elem.parentNode;
|
60
|
+
if ( matchesSelector( elem, selector ) ) {
|
61
|
+
return elem;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
};
|
65
|
+
|
66
|
+
// ----- getQueryElement ----- //
|
67
|
+
|
68
|
+
// use element as selector string
|
69
|
+
utils.getQueryElement = function( elem ) {
|
70
|
+
if ( typeof elem == 'string' ) {
|
71
|
+
return document.querySelector( elem );
|
72
|
+
}
|
73
|
+
return elem;
|
74
|
+
};
|
75
|
+
|
76
|
+
// ----- handleEvent ----- //
|
77
|
+
|
78
|
+
// enable .ontype to trigger from .addEventListener( elem, 'type' )
|
79
|
+
utils.handleEvent = function( event ) {
|
80
|
+
var method = 'on' + event.type;
|
81
|
+
if ( this[ method ] ) {
|
82
|
+
this[ method ]( event );
|
83
|
+
}
|
84
|
+
};
|
85
|
+
|
86
|
+
// ----- filterFindElements ----- //
|
87
|
+
|
88
|
+
utils.filterFindElements = function( elems, selector ) {
|
89
|
+
// make array of elems
|
90
|
+
elems = utils.makeArray( elems );
|
91
|
+
var ffElems = [];
|
92
|
+
|
93
|
+
elems.forEach( function( elem ) {
|
94
|
+
// check that elem is an actual element
|
95
|
+
if ( !( elem instanceof HTMLElement ) ) {
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
// add elem if no selector
|
99
|
+
if ( !selector ) {
|
100
|
+
ffElems.push( elem );
|
101
|
+
return;
|
102
|
+
}
|
103
|
+
// filter & find items if we have a selector
|
104
|
+
// filter
|
105
|
+
if ( matchesSelector( elem, selector ) ) {
|
106
|
+
ffElems.push( elem );
|
107
|
+
}
|
108
|
+
// find children
|
109
|
+
var childElems = elem.querySelectorAll( selector );
|
110
|
+
// concat childElems to filterFound array
|
111
|
+
for ( var i=0; i < childElems.length; i++ ) {
|
112
|
+
ffElems.push( childElems[i] );
|
113
|
+
}
|
114
|
+
});
|
115
|
+
|
116
|
+
return ffElems;
|
117
|
+
};
|
118
|
+
|
119
|
+
// ----- debounceMethod ----- //
|
120
|
+
|
121
|
+
utils.debounceMethod = function( _class, methodName, threshold ) {
|
122
|
+
threshold = threshold || 100;
|
123
|
+
// original method
|
124
|
+
var method = _class.prototype[ methodName ];
|
125
|
+
var timeoutName = methodName + 'Timeout';
|
126
|
+
|
127
|
+
_class.prototype[ methodName ] = function() {
|
128
|
+
var timeout = this[ timeoutName ];
|
129
|
+
clearTimeout( timeout );
|
130
|
+
|
131
|
+
var args = arguments;
|
132
|
+
var _this = this;
|
133
|
+
this[ timeoutName ] = setTimeout( function() {
|
134
|
+
method.apply( _this, args );
|
135
|
+
delete _this[ timeoutName ];
|
136
|
+
}, threshold );
|
137
|
+
};
|
138
|
+
};
|
139
|
+
|
140
|
+
// ----- docReady ----- //
|
141
|
+
|
142
|
+
utils.docReady = function( callback ) {
|
143
|
+
var readyState = document.readyState;
|
144
|
+
if ( readyState == 'complete' || readyState == 'interactive' ) {
|
145
|
+
// do async to allow for other scripts to run. metafizzy/flickity#441
|
146
|
+
setTimeout( callback );
|
147
|
+
} else {
|
148
|
+
document.addEventListener( 'DOMContentLoaded', callback );
|
149
|
+
}
|
150
|
+
};
|
151
|
+
|
152
|
+
// ----- htmlInit ----- //
|
153
|
+
|
154
|
+
// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
|
155
|
+
utils.toDashed = function( str ) {
|
156
|
+
return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
|
157
|
+
return $1 + '-' + $2;
|
158
|
+
}).toLowerCase();
|
159
|
+
};
|
160
|
+
|
161
|
+
var console = window.console;
|
162
|
+
/**
|
163
|
+
* allow user to initialize classes via [data-namespace] or .js-namespace class
|
164
|
+
* htmlInit( Widget, 'widgetName' )
|
165
|
+
* options are parsed from data-namespace-options
|
166
|
+
*/
|
167
|
+
utils.htmlInit = function( WidgetClass, namespace ) {
|
168
|
+
utils.docReady( function() {
|
169
|
+
var dashedNamespace = utils.toDashed( namespace );
|
170
|
+
var dataAttr = 'data-' + dashedNamespace;
|
171
|
+
var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
|
172
|
+
var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
|
173
|
+
var elems = utils.makeArray( dataAttrElems )
|
174
|
+
.concat( utils.makeArray( jsDashElems ) );
|
175
|
+
var dataOptionsAttr = dataAttr + '-options';
|
176
|
+
var jQuery = window.jQuery;
|
177
|
+
|
178
|
+
elems.forEach( function( elem ) {
|
179
|
+
var attr = elem.getAttribute( dataAttr ) ||
|
180
|
+
elem.getAttribute( dataOptionsAttr );
|
181
|
+
var options;
|
182
|
+
try {
|
183
|
+
options = attr && JSON.parse( attr );
|
184
|
+
} catch ( error ) {
|
185
|
+
// log error, do not initialize
|
186
|
+
if ( console ) {
|
187
|
+
console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
|
188
|
+
': ' + error );
|
189
|
+
}
|
190
|
+
return;
|
191
|
+
}
|
192
|
+
// initialize
|
193
|
+
var instance = new WidgetClass( elem, options );
|
194
|
+
// make available via $().data('namespace')
|
195
|
+
if ( jQuery ) {
|
196
|
+
jQuery.data( elem, namespace, instance );
|
197
|
+
}
|
198
|
+
});
|
199
|
+
|
200
|
+
});
|
201
|
+
};
|
202
|
+
|
203
|
+
export default utils;
|