udongo 6.3.2 → 6.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/backend/application.js +1 -0
  3. data/app/assets/javascripts/backend/general.js +6 -0
  4. data/app/assets/stylesheets/backend/application.scss +1 -0
  5. data/app/assets/stylesheets/backend/base/_general.scss +7 -0
  6. data/app/assets/stylesheets/backend/pages/_flexible_content.scss +0 -8
  7. data/app/assets/stylesheets/backend/udongo.scss +2 -0
  8. data/app/controllers/backend/content/rows/columns_controller.rb +1 -9
  9. data/app/controllers/backend/content/rows/slideshows_controller.rb +11 -0
  10. data/app/controllers/backend/content/rows_controller.rb +16 -0
  11. data/app/controllers/backend/forms/fields_controller.rb +3 -1
  12. data/app/controllers/backend/image_collections/base_controller.rb +11 -0
  13. data/app/controllers/backend/image_collections/images_controller.rb +15 -0
  14. data/app/controllers/backend/image_collections_controller.rb +50 -0
  15. data/app/controllers/concerns/backend/content_type_controller.rb +1 -10
  16. data/app/decorators/content_slideshow_decorator.rb +3 -0
  17. data/app/models/content_slideshow.rb +9 -0
  18. data/app/models/image_collection.rb +9 -0
  19. data/app/views/backend/content/_form.html.erb +1 -1
  20. data/app/views/backend/content/_rows.html.erb +11 -7
  21. data/app/views/backend/content/_slideshow.html.erb +6 -0
  22. data/app/views/backend/content/rows/columns/edit.html.erb +6 -14
  23. data/app/views/backend/content/rows/columns/new.html.erb +6 -14
  24. data/app/views/backend/content/rows/edit.html.erb +31 -0
  25. data/app/views/backend/content/rows/forms/edit.html.erb +4 -12
  26. data/app/views/backend/content/rows/images/edit.html.erb +12 -20
  27. data/app/views/backend/content/rows/pictures/edit.html.erb +7 -15
  28. data/app/views/backend/content/rows/pictures/link_or_upload.html.erb +12 -20
  29. data/app/views/backend/content/rows/slideshows/edit.html.erb +17 -0
  30. data/app/views/backend/content/rows/texts/edit.html.erb +2 -10
  31. data/app/views/backend/content/rows/videos/edit.html.erb +5 -6
  32. data/app/views/backend/forms/fields/_form.html.erb +1 -0
  33. data/app/views/backend/image_collections/_form.html.erb +19 -0
  34. data/app/views/backend/image_collections/_tabs.html.erb +18 -0
  35. data/app/views/backend/image_collections/edit.html.erb +6 -0
  36. data/app/views/backend/image_collections/images/index.html.erb +43 -0
  37. data/app/views/backend/image_collections/index.html.erb +30 -0
  38. data/app/views/backend/image_collections/new.html.erb +5 -0
  39. data/app/views/backend/lightbox_saved.html.erb +3 -0
  40. data/app/views/layouts/backend/_top_navigation.html.erb +1 -0
  41. data/app/views/layouts/backend/lightbox.html.erb +5 -3
  42. data/changelog.md +13 -0
  43. data/config/locales/en_backend.yml +5 -6
  44. data/config/locales/en_forms.yml +14 -0
  45. data/config/locales/nl_backend.yml +7 -6
  46. data/config/locales/nl_forms.yml +13 -0
  47. data/config/routes.rb +7 -1
  48. data/db/migrate/20170615113617_create_asset_collections.rb +12 -0
  49. data/db/migrate/20170615120716_rename_asset_collection_to_image_collection.rb +5 -0
  50. data/db/migrate/20170615131909_create_content_slideshows.rb +11 -0
  51. data/db/migrate/20170615184855_add_content_row_margin_padding_and_bg_color.rb +9 -0
  52. data/db/migrate/20170616114757_add_external_ref_to_form_field.rb +6 -0
  53. data/lib/udongo/bogus_model.rb +34 -0
  54. data/lib/udongo/configs/flexible_content.rb +1 -1
  55. data/lib/udongo/search/result_objects/base.rb +1 -1
  56. data/lib/udongo/version.rb +1 -1
  57. data/spec/factories/content_slideshows.rb +5 -0
  58. data/spec/factories/image_collections.rb +6 -0
  59. data/vendor/assets/javascripts/backend/lity.js +637 -0
  60. data/vendor/assets/stylesheets/backend/lity.scss +200 -0
  61. metadata +30 -2
@@ -47,6 +47,8 @@ nl:
47
47
  general: Algemeen
48
48
  house_number: Huisnummer
49
49
  html_content: HTML inhoud
50
+ image_collection: Afbeeldingsgroep
51
+ image_collections: Afbeeldingsgroepen
50
52
  image: Afbeelding
51
53
  images: Afbeeldingen
52
54
  last_changed_at: Laatst gewijzigd op
@@ -81,6 +83,7 @@ nl:
81
83
  sent_at: Verzonden op
82
84
  settings: Instellingen
83
85
  size: Grootte
86
+ slideshow: Slideshow
84
87
  snippet: Snippet
85
88
  snippets: Snippets
86
89
  source: Bron
@@ -118,6 +121,7 @@ nl:
118
121
  form: Formulier
119
122
  image: Afbeelding (niet meer gebruiken!)
120
123
  picture: Foto
124
+ slideshow: Slideshow
121
125
  text: Tekst
122
126
  video: Video
123
127
  deleted: '%{actor} werd verwijderd.'
@@ -133,17 +137,14 @@ nl:
133
137
  align_vertical_bottom: Vertikaal onderaan uitlijnen
134
138
  align_vertical_center: Vertikaal centreren
135
139
  align_vertical_top: Vertikaal bovenaan uitlijnen
136
- edit_column: Kolom bewerken
137
- edit_form: Formulier bewerken
138
- edit_image: Afbeelding bewerken
139
- edit_picture: Foto bewerken
140
- edit_text: Tekst bewerken
141
- edit_video: Video bewerken
142
140
  explanation: Met deze module kan je flexibele, responsive inhoud toevoegen. Klik op onderstaande knop om een eerste rij toe te voegen.
143
141
  full_width: Volledige breedte
142
+ margin_explanation: Marge is de witruimte boven en onder je rij.
144
143
  no_form_present: Er werd nog geen formulier gelinkt.
145
144
  no_picture_present: Er werd nog geen foto geüpload of gelinkt.
145
+ no_slideshow_present: Er werd nog geen slideshow geconfigureerd.
146
146
  no_video_present: Er werd nog geen geldige URL voor een video opgegeven.
147
+ padding_explanation: Padding is de witruimte boven en onder binnenin je rij.
147
148
  width_explanation: Voor de flexibele inhoud wordt er gebruikt gemaakt van een grid layout. Deze werkt met rijen en kolommen. Iedere rij kan maximaal 12 kolommen bevatten. Daarom dat de breedte uitgedrukt is in een breuk op 12.
148
149
  forgot_password: Wachtwoord vergeten?
149
150
  form_fields:
@@ -24,6 +24,7 @@ nl:
24
24
  description: Beschrijving
25
25
  disabled: Uitgeschakeld
26
26
  email: E-mail
27
+ external_reference: Externe referentie
27
28
  extra: Extra
28
29
  field_type: Veldtype
29
30
  first_name: Voornaam
@@ -67,6 +68,18 @@ nl:
67
68
  width_lg: Breedte (large)
68
69
  width_xl: Breedte (extra large)
69
70
 
71
+ content_row:
72
+ background_color: Achtergrondkleur
73
+ margin_bottom: Marge onderaan
74
+ margin_top: Marge bovenaan
75
+ padding_bottom: Padding onderaan
76
+ padding_top: Padding bovenaan
77
+
78
+ content_slideshow:
79
+ autoplay: Automatisch afspelen
80
+ image_collection_id: Afbeeldingsgroep
81
+ slide_interval: Interval tussen slides
82
+
70
83
  email_template:
71
84
  from_email: E-mail adres afzender
72
85
  from_name: Naam afzender
@@ -41,6 +41,12 @@ Rails.application.routes.draw do
41
41
  end
42
42
  end
43
43
 
44
+ resources :image_collections do
45
+ resources :images, only: [:index], controller: 'image_collections/images' do
46
+ concerns :positionable
47
+ end
48
+ end
49
+
44
50
  resources :articles, except: [:show] do
45
51
  concerns :translatable
46
52
 
@@ -80,7 +86,7 @@ Rails.application.routes.draw do
80
86
  end
81
87
 
82
88
  namespace :content do
83
- resources :rows, only: [:index, :new, :destroy] do
89
+ resources :rows, only: [:index, :new, :edit, :update, :destroy] do
84
90
  member do
85
91
  get :horizontal_alignment, :vertical_alignment, :toggle_full_width
86
92
  end
@@ -0,0 +1,12 @@
1
+ class CreateAssetCollections < ActiveRecord::Migration[5.0]
2
+ def change
3
+ create_table :asset_collections do |t|
4
+ t.string :identifier
5
+ t.text :description
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :asset_collections, :identifier
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ class RenameAssetCollectionToImageCollection < ActiveRecord::Migration[5.0]
2
+ def change
3
+ rename_table :asset_collections, :image_collections
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ class CreateContentSlideshows < ActiveRecord::Migration[5.0]
2
+ def change
3
+ create_table :content_slideshows do |t|
4
+ t.references :image_collection
5
+ t.boolean :autoplay
6
+ t.integer :slide_interval
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ class AddContentRowMarginPaddingAndBgColor < ActiveRecord::Migration[5.0]
2
+ def change
3
+ add_column :content_rows, :background_color, :string, after: 'vertical_alignment'
4
+ add_column :content_rows, :padding_top, :integer, after: 'background_color'
5
+ add_column :content_rows, :padding_bottom, :integer, after: 'padding_top'
6
+ add_column :content_rows, :margin_top, :integer, after: 'padding_bottom'
7
+ add_column :content_rows, :margin_bottom, :integer, after: 'margin_top'
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ class AddExternalRefToFormField < ActiveRecord::Migration[5.0]
2
+ def change
3
+ add_column :form_fields, :external_reference, :string, after: 'email'
4
+ add_index :form_fields, :external_reference
5
+ end
6
+ end
@@ -0,0 +1,34 @@
1
+ # This class was made to help test class agnostic engine functionality that
2
+ # requires model interfaces to work.
3
+ #
4
+ # An example would be tests for polymorphic associations:
5
+ # foo = Udongo::BogusModel.new(id: 37, description: 'foobar', hidden?: false)
6
+ # create(:search_index, searchable: foo, locale: 'nl')
7
+ class Udongo::BogusModel < OpenStruct
8
+ attr_reader :id
9
+
10
+ def self.base_class
11
+ self.class
12
+ end
13
+
14
+ def self.primary_key
15
+ :id
16
+ end
17
+
18
+ def _read_attribute(attribute)
19
+ nil
20
+ end
21
+
22
+ def id
23
+ @id = rand(1..1000) unless @id
24
+ @id
25
+ end
26
+
27
+ def destroyed?
28
+ false
29
+ end
30
+
31
+ def new_record?
32
+ false
33
+ end
34
+ end
@@ -6,7 +6,7 @@ module Udongo
6
6
  BREAKPOINTS = %w(xs sm md lg xl)
7
7
  DEFAULT_BREAKPOINT = 'md'
8
8
 
9
- attribute :types, Array, default: %w(text picture video form image)
9
+ attribute :types, Array, default: %w(text picture video slideshow form image)
10
10
  attribute :picture_caption_editor, Axiom::Types::Boolean, default: false
11
11
 
12
12
  def picture_caption_editor?
@@ -36,7 +36,7 @@ module Udongo
36
36
  end
37
37
 
38
38
  def hidden?
39
- searchable.respond_to?(:visible) && searchable.hidden?
39
+ searchable.respond_to?(:visible?) && searchable.hidden?
40
40
  end
41
41
 
42
42
  def label
@@ -1,3 +1,3 @@
1
1
  module Udongo
2
- VERSION = '6.3.2'
2
+ VERSION = '6.4.0'
3
3
  end
@@ -0,0 +1,5 @@
1
+ FactoryGirl.define do
2
+ factory :content_slideshow do
3
+ image_collection
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ factory :image_collection do
3
+ description 'foo'
4
+ sequence(:identifier) { |n| "foo-#{n}" }
5
+ end
6
+ end
@@ -0,0 +1,637 @@
1
+ /*! Lity - v2.2.2 - 2016-12-14
2
+ * http://sorgalla.com/lity/
3
+ * Copyright (c) 2015-2016 Jan Sorgalla; Licensed MIT */
4
+ (function(window, factory) {
5
+ if (typeof define === 'function' && define.amd) {
6
+ define(['jquery'], function($) {
7
+ return factory(window, $);
8
+ });
9
+ } else if (typeof module === 'object' && typeof module.exports === 'object') {
10
+ module.exports = factory(window, require('jquery'));
11
+ } else {
12
+ window.lity = factory(window, window.jQuery || window.Zepto);
13
+ }
14
+ }(typeof window !== "undefined" ? window : this, function(window, $) {
15
+ 'use strict';
16
+
17
+ var document = window.document;
18
+
19
+ var _win = $(window);
20
+ var _deferred = $.Deferred;
21
+ var _html = $('html');
22
+ var _instances = [];
23
+
24
+ var _attrAriaHidden = 'aria-hidden';
25
+ var _dataAriaHidden = 'lity-' + _attrAriaHidden;
26
+
27
+ var _focusableElementsSelector = 'a[href],area[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled]),iframe,object,embed,[contenteditable],[tabindex]:not([tabindex^="-"])';
28
+
29
+ var _defaultOptions = {
30
+ handler: null,
31
+ handlers: {
32
+ image: imageHandler,
33
+ inline: inlineHandler,
34
+ youtube: youtubeHandler,
35
+ vimeo: vimeoHandler,
36
+ googlemaps: googlemapsHandler,
37
+ facebookvideo: facebookvideoHandler,
38
+ iframe: iframeHandler
39
+ },
40
+ template: '<div class="lity" role="dialog" aria-label="Dialog Window (Press escape to close)" tabindex="-1"><div class="lity-wrap" data-lity-close role="document"><div class="lity-loader" aria-hidden="true">Loading...</div><div class="lity-container"><div class="lity-content"></div><button class="lity-close" type="button" aria-label="Close (Press escape to close)" data-lity-close>&times;</button></div></div></div>'
41
+ };
42
+
43
+ var _imageRegexp = /(^data:image\/)|(\.(png|jpe?g|gif|svg|webp|bmp|ico|tiff?)(\?\S*)?$)/i;
44
+ var _youtubeRegex = /(youtube(-nocookie)?\.com|youtu\.be)\/(watch\?v=|v\/|u\/|embed\/?)?([\w-]{11})(.*)?/i;
45
+ var _vimeoRegex = /(vimeo(pro)?.com)\/(?:[^\d]+)?(\d+)\??(.*)?$/;
46
+ var _googlemapsRegex = /((maps|www)\.)?google\.([^\/\?]+)\/?((maps\/?)?\?)(.*)/i;
47
+ var _facebookvideoRegex = /(facebook\.com)\/([a-z0-9_-]*)\/videos\/([0-9]*)(.*)?$/i;
48
+
49
+ var _transitionEndEvent = (function() {
50
+ var el = document.createElement('div');
51
+
52
+ var transEndEventNames = {
53
+ WebkitTransition: 'webkitTransitionEnd',
54
+ MozTransition: 'transitionend',
55
+ OTransition: 'oTransitionEnd otransitionend',
56
+ transition: 'transitionend'
57
+ };
58
+
59
+ for (var name in transEndEventNames) {
60
+ if (el.style[name] !== undefined) {
61
+ return transEndEventNames[name];
62
+ }
63
+ }
64
+
65
+ return false;
66
+ })();
67
+
68
+ function transitionEnd(element) {
69
+ var deferred = _deferred();
70
+
71
+ if (!_transitionEndEvent || !element.length) {
72
+ deferred.resolve();
73
+ } else {
74
+ element.one(_transitionEndEvent, deferred.resolve);
75
+ setTimeout(deferred.resolve, 500);
76
+ }
77
+
78
+ return deferred.promise();
79
+ }
80
+
81
+ function settings(currSettings, key, value) {
82
+ if (arguments.length === 1) {
83
+ return $.extend({}, currSettings);
84
+ }
85
+
86
+ if (typeof key === 'string') {
87
+ if (typeof value === 'undefined') {
88
+ return typeof currSettings[key] === 'undefined'
89
+ ? null
90
+ : currSettings[key];
91
+ }
92
+
93
+ currSettings[key] = value;
94
+ } else {
95
+ $.extend(currSettings, key);
96
+ }
97
+
98
+ return this;
99
+ }
100
+
101
+ function parseQueryParams(params) {
102
+ var pairs = decodeURI(params.split('#')[0]).split('&');
103
+ var obj = {}, p;
104
+
105
+ for (var i = 0, n = pairs.length; i < n; i++) {
106
+ if (!pairs[i]) {
107
+ continue;
108
+ }
109
+
110
+ p = pairs[i].split('=');
111
+ obj[p[0]] = p[1];
112
+ }
113
+
114
+ return obj;
115
+ }
116
+
117
+ function appendQueryParams(url, params) {
118
+ return url + (url.indexOf('?') > -1 ? '&' : '?') + $.param(params);
119
+ }
120
+
121
+ function transferHash(originalUrl, newUrl) {
122
+ var pos = originalUrl.indexOf('#');
123
+
124
+ if (-1 === pos) {
125
+ return newUrl;
126
+ }
127
+
128
+ if (pos > 0) {
129
+ originalUrl = originalUrl.substr(pos);
130
+ }
131
+
132
+ return newUrl + originalUrl;
133
+ }
134
+
135
+ function error(msg) {
136
+ return $('<span class="lity-error"/>').append(msg);
137
+ }
138
+
139
+ function imageHandler(target, instance) {
140
+ var desc = (instance.opener() && instance.opener().data('lity-desc')) || 'Image with no description';
141
+ var img = $('<img src="' + target + '" alt="' + desc + '"/>');
142
+ var deferred = _deferred();
143
+ var failed = function() {
144
+ deferred.reject(error('Failed loading image'));
145
+ };
146
+
147
+ img
148
+ .on('load', function() {
149
+ if (this.naturalWidth === 0) {
150
+ return failed();
151
+ }
152
+
153
+ deferred.resolve(img);
154
+ })
155
+ .on('error', failed)
156
+ ;
157
+
158
+ return deferred.promise();
159
+ }
160
+
161
+ imageHandler.test = function(target) {
162
+ return _imageRegexp.test(target);
163
+ };
164
+
165
+ function inlineHandler(target, instance) {
166
+ var el, placeholder, hasHideClass;
167
+
168
+ try {
169
+ el = $(target);
170
+ } catch (e) {
171
+ return false;
172
+ }
173
+
174
+ if (!el.length) {
175
+ return false;
176
+ }
177
+
178
+ placeholder = $('<i style="display:none !important"/>');
179
+ hasHideClass = el.hasClass('lity-hide');
180
+
181
+ instance
182
+ .element()
183
+ .one('lity:remove', function() {
184
+ placeholder
185
+ .before(el)
186
+ .remove()
187
+ ;
188
+
189
+ if (hasHideClass && !el.closest('.lity-content').length) {
190
+ el.addClass('lity-hide');
191
+ }
192
+ })
193
+ ;
194
+
195
+ return el
196
+ .removeClass('lity-hide')
197
+ .after(placeholder)
198
+ ;
199
+ }
200
+
201
+ function youtubeHandler(target) {
202
+ var matches = _youtubeRegex.exec(target);
203
+
204
+ if (!matches) {
205
+ return false;
206
+ }
207
+
208
+ return iframeHandler(
209
+ transferHash(
210
+ target,
211
+ appendQueryParams(
212
+ 'https://www.youtube' + (matches[2] || '') + '.com/embed/' + matches[4],
213
+ $.extend(
214
+ {
215
+ autoplay: 1
216
+ },
217
+ parseQueryParams(matches[5] || '')
218
+ )
219
+ )
220
+ )
221
+ );
222
+ }
223
+
224
+ function vimeoHandler(target) {
225
+ var matches = _vimeoRegex.exec(target);
226
+
227
+ if (!matches) {
228
+ return false;
229
+ }
230
+
231
+ return iframeHandler(
232
+ transferHash(
233
+ target,
234
+ appendQueryParams(
235
+ 'https://player.vimeo.com/video/' + matches[3],
236
+ $.extend(
237
+ {
238
+ autoplay: 1
239
+ },
240
+ parseQueryParams(matches[4] || '')
241
+ )
242
+ )
243
+ )
244
+ );
245
+ }
246
+
247
+ function facebookvideoHandler(target) {
248
+ var matches = _facebookvideoRegex.exec(target);
249
+
250
+ if (!matches) {
251
+ return false;
252
+ }
253
+
254
+ if (0 !== target.indexOf('http')) {
255
+ target = 'https:' + target;
256
+ }
257
+
258
+ return iframeHandler(
259
+ transferHash(
260
+ target,
261
+ appendQueryParams(
262
+ 'https://www.facebook.com/plugins/video.php?href=' + target,
263
+ $.extend(
264
+ {
265
+ autoplay: 1
266
+ },
267
+ parseQueryParams(matches[4] || '')
268
+ )
269
+ )
270
+ )
271
+ );
272
+ }
273
+
274
+ function googlemapsHandler(target) {
275
+ var matches = _googlemapsRegex.exec(target);
276
+
277
+ if (!matches) {
278
+ return false;
279
+ }
280
+
281
+ return iframeHandler(
282
+ transferHash(
283
+ target,
284
+ appendQueryParams(
285
+ 'https://www.google.' + matches[3] + '/maps?' + matches[6],
286
+ {
287
+ output: matches[6].indexOf('layer=c') > 0 ? 'svembed' : 'embed'
288
+ }
289
+ )
290
+ )
291
+ );
292
+ }
293
+
294
+ function iframeHandler(target) {
295
+ return '<div class="lity-iframe-container"><iframe frameborder="0" allowfullscreen src="' + target + '"/></div>';
296
+ }
297
+
298
+ function winHeight() {
299
+ return document.documentElement.clientHeight
300
+ ? document.documentElement.clientHeight
301
+ : Math.round(_win.height());
302
+ }
303
+
304
+ function keydown(e) {
305
+ var current = currentInstance();
306
+
307
+ if (!current) {
308
+ return;
309
+ }
310
+
311
+ // ESC key
312
+ if (e.keyCode === 27) {
313
+ current.close();
314
+ }
315
+
316
+ // TAB key
317
+ if (e.keyCode === 9) {
318
+ handleTabKey(e, current);
319
+ }
320
+ }
321
+
322
+ function handleTabKey(e, instance) {
323
+ var focusableElements = instance.element().find(_focusableElementsSelector);
324
+ var focusedIndex = focusableElements.index(document.activeElement);
325
+
326
+ if (e.shiftKey && focusedIndex <= 0) {
327
+ focusableElements.get(focusableElements.length - 1).focus();
328
+ e.preventDefault();
329
+ } else if (!e.shiftKey && focusedIndex === focusableElements.length - 1) {
330
+ focusableElements.get(0).focus();
331
+ e.preventDefault();
332
+ }
333
+ }
334
+
335
+ function resize() {
336
+ $.each(_instances, function(i, instance) {
337
+ instance.resize();
338
+ });
339
+ }
340
+
341
+ function registerInstance(instanceToRegister) {
342
+ if (1 === _instances.unshift(instanceToRegister)) {
343
+ _html.addClass('lity-active');
344
+
345
+ _win
346
+ .on({
347
+ resize: resize,
348
+ keydown: keydown
349
+ })
350
+ ;
351
+ }
352
+
353
+ $('body > *').not(instanceToRegister.element())
354
+ .addClass('lity-hidden')
355
+ .each(function() {
356
+ var el = $(this);
357
+
358
+ if (undefined !== el.data(_dataAriaHidden)) {
359
+ return;
360
+ }
361
+
362
+ el.data(_dataAriaHidden, el.attr(_attrAriaHidden) || null);
363
+ })
364
+ .attr(_attrAriaHidden, 'true')
365
+ ;
366
+ }
367
+
368
+ function removeInstance(instanceToRemove) {
369
+ var show;
370
+
371
+ instanceToRemove
372
+ .element()
373
+ .attr(_attrAriaHidden, 'true')
374
+ ;
375
+
376
+ if (1 === _instances.length) {
377
+ _html.removeClass('lity-active');
378
+
379
+ _win
380
+ .off({
381
+ resize: resize,
382
+ keydown: keydown
383
+ })
384
+ ;
385
+ }
386
+
387
+ _instances = $.grep(_instances, function(instance) {
388
+ return instanceToRemove !== instance;
389
+ });
390
+
391
+ if (!!_instances.length) {
392
+ show = _instances[0].element();
393
+ } else {
394
+ show = $('.lity-hidden');
395
+ }
396
+
397
+ show
398
+ .removeClass('lity-hidden')
399
+ .each(function() {
400
+ var el = $(this), oldAttr = el.data(_dataAriaHidden);
401
+
402
+ if (!oldAttr) {
403
+ el.removeAttr(_attrAriaHidden);
404
+ } else {
405
+ el.attr(_attrAriaHidden, oldAttr);
406
+ }
407
+
408
+ el.removeData(_dataAriaHidden);
409
+ })
410
+ ;
411
+ }
412
+
413
+ function currentInstance() {
414
+ if (0 === _instances.length) {
415
+ return null;
416
+ }
417
+
418
+ return _instances[0];
419
+ }
420
+
421
+ function factory(target, instance, handlers, preferredHandler) {
422
+ var handler = 'inline', content;
423
+
424
+ var currentHandlers = $.extend({}, handlers);
425
+
426
+ if (preferredHandler && currentHandlers[preferredHandler]) {
427
+ content = currentHandlers[preferredHandler](target, instance);
428
+ handler = preferredHandler;
429
+ } else {
430
+ // Run inline and iframe handlers after all other handlers
431
+ $.each(['inline', 'iframe'], function(i, name) {
432
+ delete currentHandlers[name];
433
+
434
+ currentHandlers[name] = handlers[name];
435
+ });
436
+
437
+ $.each(currentHandlers, function(name, currentHandler) {
438
+ // Handler might be "removed" by setting callback to null
439
+ if (!currentHandler) {
440
+ return true;
441
+ }
442
+
443
+ if (
444
+ currentHandler.test &&
445
+ !currentHandler.test(target, instance)
446
+ ) {
447
+ return true;
448
+ }
449
+
450
+ content = currentHandler(target, instance);
451
+
452
+ if (false !== content) {
453
+ handler = name;
454
+ return false;
455
+ }
456
+ });
457
+ }
458
+
459
+ return {handler: handler, content: content || ''};
460
+ }
461
+
462
+ function Lity(target, options, opener, activeElement) {
463
+ var self = this;
464
+ var result;
465
+ var isReady = false;
466
+ var isClosed = false;
467
+ var element;
468
+ var content;
469
+
470
+ options = $.extend(
471
+ {},
472
+ _defaultOptions,
473
+ options
474
+ );
475
+
476
+ element = $(options.template);
477
+
478
+ // -- API --
479
+
480
+ self.element = function() {
481
+ return element;
482
+ };
483
+
484
+ self.opener = function() {
485
+ return opener;
486
+ };
487
+
488
+ self.options = $.proxy(settings, self, options);
489
+ self.handlers = $.proxy(settings, self, options.handlers);
490
+
491
+ self.resize = function() {
492
+ if (!isReady || isClosed) {
493
+ return;
494
+ }
495
+
496
+ content
497
+ .css('max-height', winHeight() + 'px')
498
+ .trigger('lity:resize', [self])
499
+ ;
500
+ };
501
+
502
+ self.close = function() {
503
+ if (!isReady || isClosed) {
504
+ return;
505
+ }
506
+
507
+ isClosed = true;
508
+
509
+ removeInstance(self);
510
+
511
+ var deferred = _deferred();
512
+
513
+ // We return focus only if the current focus is inside this instance
514
+ if (
515
+ activeElement &&
516
+ (
517
+ document.activeElement === element[0] ||
518
+ $.contains(element[0], document.activeElement)
519
+ )
520
+ ) {
521
+ try {
522
+ activeElement.focus();
523
+ } catch (e) {
524
+ // Ignore exceptions, eg. for SVG elements which can't be
525
+ // focused in IE11
526
+ }
527
+ }
528
+
529
+ content.trigger('lity:close', [self]);
530
+
531
+ element
532
+ .removeClass('lity-opened')
533
+ .addClass('lity-closed')
534
+ ;
535
+
536
+ transitionEnd(content.add(element))
537
+ .always(function() {
538
+ content.trigger('lity:remove', [self]);
539
+ element.remove();
540
+ element = undefined;
541
+ deferred.resolve();
542
+ })
543
+ ;
544
+
545
+ return deferred.promise();
546
+ };
547
+
548
+ // -- Initialization --
549
+
550
+ result = factory(target, self, options.handlers, options.handler);
551
+
552
+ element
553
+ .attr(_attrAriaHidden, 'false')
554
+ .addClass('lity-loading lity-opened lity-' + result.handler)
555
+ .appendTo('body')
556
+ .focus()
557
+ .on('click', '[data-lity-close]', function(e) {
558
+ if ($(e.target).is('[data-lity-close]')) {
559
+ self.close();
560
+ }
561
+ })
562
+ .trigger('lity:open', [self])
563
+ ;
564
+
565
+ registerInstance(self);
566
+
567
+ $.when(result.content)
568
+ .always(ready)
569
+ ;
570
+
571
+ function ready(result) {
572
+ content = $(result)
573
+ .css('max-height', winHeight() + 'px')
574
+ ;
575
+
576
+ element
577
+ .find('.lity-loader')
578
+ .each(function() {
579
+ var loader = $(this);
580
+
581
+ transitionEnd(loader)
582
+ .always(function() {
583
+ loader.remove();
584
+ })
585
+ ;
586
+ })
587
+ ;
588
+
589
+ element
590
+ .removeClass('lity-loading')
591
+ .find('.lity-content')
592
+ .empty()
593
+ .append(content)
594
+ ;
595
+
596
+ isReady = true;
597
+
598
+ content
599
+ .trigger('lity:ready', [self])
600
+ ;
601
+ }
602
+ }
603
+
604
+ function lity(target, options, opener) {
605
+ if (!target.preventDefault) {
606
+ opener = $(opener);
607
+ } else {
608
+ target.preventDefault();
609
+ opener = $(this);
610
+ target = opener.data('lity-target') || opener.attr('href') || opener.attr('src');
611
+ }
612
+
613
+ var instance = new Lity(
614
+ target,
615
+ $.extend(
616
+ {},
617
+ opener.data('lity-options') || opener.data('lity'),
618
+ options
619
+ ),
620
+ opener,
621
+ document.activeElement
622
+ );
623
+
624
+ if (!target.preventDefault) {
625
+ return instance;
626
+ }
627
+ }
628
+
629
+ lity.version = '2.2.2';
630
+ lity.options = $.proxy(settings, lity, _defaultOptions);
631
+ lity.handlers = $.proxy(settings, lity, _defaultOptions.handlers);
632
+ lity.current = currentInstance;
633
+
634
+ $(document).on('click.lity', '[data-lity]', lity);
635
+
636
+ return lity;
637
+ }));