jumbo-jekyll-theme 3.0.42 → 3.0.43

Sign up to get free protection for your applications and to get access to all the features.
Files changed (246) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +26 -0
  4. data/_config.yml +190 -0
  5. data/_data/authors.yml +7 -0
  6. data/_data/footer.yml +57 -0
  7. data/_data/nav.yml +75 -0
  8. data/_data/news.yaml +230 -0
  9. data/_data/settings.yml +93 -0
  10. data/_data/sidebar-nav.yml +23 -0
  11. data/_data/sticky-tab-bar.yml +29 -0
  12. data/_includes/author-pagination.html +36 -0
  13. data/_includes/authors-posts.html +49 -0
  14. data/_includes/breadcrumb.html +95 -0
  15. data/_includes/carousel-header.html +15 -0
  16. data/_includes/css.html +11 -0
  17. data/_includes/custom.html +1 -0
  18. data/_includes/display-blog-posts.html +67 -0
  19. data/_includes/disqus-comments.html +8 -0
  20. data/_includes/footer.html +68 -0
  21. data/_includes/github-edit.html +60 -0
  22. data/_includes/google-analytics-script.html +9 -0
  23. data/_includes/gtm-noscript.html +5 -0
  24. data/_includes/gtm-script.html +7 -0
  25. data/_includes/head.html +44 -0
  26. data/_includes/hero-banner.html +21 -0
  27. data/_includes/image.html +6 -0
  28. data/_includes/javascript.html +9 -0
  29. data/_includes/jumbotron.html +71 -0
  30. data/_includes/linaro-404.html +10 -0
  31. data/_includes/linaro-svg.html +1 -0
  32. data/_includes/media.html +11 -0
  33. data/_includes/members.html +63 -0
  34. data/_includes/nav.html +132 -0
  35. data/_includes/newsletter-script.html +30 -0
  36. data/_includes/owl-carousel-homepage.html +103 -0
  37. data/_includes/pagination-authors.html +36 -0
  38. data/_includes/pagination-news.html +36 -0
  39. data/_includes/pagination.html +36 -0
  40. data/_includes/post-sidebar.html +90 -0
  41. data/_includes/post-tags.html +9 -0
  42. data/_includes/read_time.html +2 -0
  43. data/_includes/responsive-image.html +6 -0
  44. data/_includes/schema.html +50 -0
  45. data/_includes/sidebar.html +55 -0
  46. data/_includes/sticky-tab-bar.html +61 -0
  47. data/_includes/thumb.html +2 -0
  48. data/_includes/thumbnail_image.html +10 -0
  49. data/_includes/universal-nav.html +28 -0
  50. data/_includes/youtube.html +7 -0
  51. data/_layouts/author-layout.html +13 -0
  52. data/_layouts/author.html +7 -0
  53. data/_layouts/container-breadcrumb-tabs.html +10 -0
  54. data/_layouts/container-breadcrumb.html +19 -0
  55. data/_layouts/container.html +8 -0
  56. data/_layouts/default.html +27 -0
  57. data/_layouts/error.html +23 -0
  58. data/_layouts/jumbotron-container.html +19 -0
  59. data/_layouts/jumbotron.html +12 -0
  60. data/_layouts/post-index.html +18 -0
  61. data/_layouts/post-old.html +70 -0
  62. data/_layouts/post.html +145 -0
  63. data/_layouts/redirect.html +11 -0
  64. data/_sass/_bootstrap-compass.scss +9 -0
  65. data/_sass/_bootstrap-mincer.scss +19 -0
  66. data/_sass/_bootstrap-sprockets.scss +9 -0
  67. data/_sass/_bootstrap.scss +56 -0
  68. data/_sass/app/blog.scss +59 -0
  69. data/_sass/app/contact.scss +3 -0
  70. data/_sass/app/custom.scss +1 -0
  71. data/_sass/app/overrides.scss +37 -0
  72. data/_sass/app/search.scss +1 -0
  73. data/_sass/blog.scss +9 -0
  74. data/_sass/bootstrap/_alerts.scss +73 -0
  75. data/_sass/bootstrap/_badges.scss +68 -0
  76. data/_sass/bootstrap/_breadcrumbs.scss +28 -0
  77. data/_sass/bootstrap/_button-groups.scss +244 -0
  78. data/_sass/bootstrap/_buttons.scss +168 -0
  79. data/_sass/bootstrap/_carousel.scss +270 -0
  80. data/_sass/bootstrap/_close.scss +36 -0
  81. data/_sass/bootstrap/_code.scss +69 -0
  82. data/_sass/bootstrap/_component-animations.scss +37 -0
  83. data/_sass/bootstrap/_dropdowns.scss +216 -0
  84. data/_sass/bootstrap/_forms.scss +617 -0
  85. data/_sass/bootstrap/_glyphicons.scss +307 -0
  86. data/_sass/bootstrap/_grid.scss +84 -0
  87. data/_sass/bootstrap/_input-groups.scss +171 -0
  88. data/_sass/bootstrap/_jumbotron.scss +54 -0
  89. data/_sass/bootstrap/_labels.scss +66 -0
  90. data/_sass/bootstrap/_list-group.scss +130 -0
  91. data/_sass/bootstrap/_media.scss +66 -0
  92. data/_sass/bootstrap/_mixins.scss +40 -0
  93. data/_sass/bootstrap/_modals.scss +150 -0
  94. data/_sass/bootstrap/_navbar.scss +662 -0
  95. data/_sass/bootstrap/_navs.scss +242 -0
  96. data/_sass/bootstrap/_normalize.scss +424 -0
  97. data/_sass/bootstrap/_pager.scss +54 -0
  98. data/_sass/bootstrap/_pagination.scss +89 -0
  99. data/_sass/bootstrap/_panels.scss +271 -0
  100. data/_sass/bootstrap/_popovers.scss +131 -0
  101. data/_sass/bootstrap/_print.scss +101 -0
  102. data/_sass/bootstrap/_progress-bars.scss +87 -0
  103. data/_sass/bootstrap/_responsive-embed.scss +35 -0
  104. data/_sass/bootstrap/_responsive-utilities.scss +179 -0
  105. data/_sass/bootstrap/_scaffolding.scss +161 -0
  106. data/_sass/bootstrap/_tables.scss +234 -0
  107. data/_sass/bootstrap/_theme.scss +291 -0
  108. data/_sass/bootstrap/_thumbnails.scss +38 -0
  109. data/_sass/bootstrap/_tooltip.scss +101 -0
  110. data/_sass/bootstrap/_type.scss +298 -0
  111. data/_sass/bootstrap/_utilities.scss +55 -0
  112. data/_sass/bootstrap/_variables.scss +932 -0
  113. data/_sass/bootstrap/_wells.scss +29 -0
  114. data/_sass/bootstrap/mixins/_alerts.scss +14 -0
  115. data/_sass/bootstrap/mixins/_background-variant.scss +12 -0
  116. data/_sass/bootstrap/mixins/_border-radius.scss +18 -0
  117. data/_sass/bootstrap/mixins/_buttons.scss +65 -0
  118. data/_sass/bootstrap/mixins/_center-block.scss +7 -0
  119. data/_sass/bootstrap/mixins/_clearfix.scss +22 -0
  120. data/_sass/bootstrap/mixins/_forms.scss +88 -0
  121. data/_sass/bootstrap/mixins/_gradients.scss +58 -0
  122. data/_sass/bootstrap/mixins/_grid-framework.scss +81 -0
  123. data/_sass/bootstrap/mixins/_grid.scss +122 -0
  124. data/_sass/bootstrap/mixins/_hide-text.scss +21 -0
  125. data/_sass/bootstrap/mixins/_image.scss +33 -0
  126. data/_sass/bootstrap/mixins/_labels.scss +12 -0
  127. data/_sass/bootstrap/mixins/_list-group.scss +32 -0
  128. data/_sass/bootstrap/mixins/_nav-divider.scss +10 -0
  129. data/_sass/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  130. data/_sass/bootstrap/mixins/_opacity.scss +8 -0
  131. data/_sass/bootstrap/mixins/_pagination.scss +24 -0
  132. data/_sass/bootstrap/mixins/_panels.scss +24 -0
  133. data/_sass/bootstrap/mixins/_progress-bar.scss +10 -0
  134. data/_sass/bootstrap/mixins/_reset-filter.scss +8 -0
  135. data/_sass/bootstrap/mixins/_reset-text.scss +18 -0
  136. data/_sass/bootstrap/mixins/_resize.scss +6 -0
  137. data/_sass/bootstrap/mixins/_responsive-visibility.scss +21 -0
  138. data/_sass/bootstrap/mixins/_size.scss +10 -0
  139. data/_sass/bootstrap/mixins/_tab-focus.scss +9 -0
  140. data/_sass/bootstrap/mixins/_table-row.scss +28 -0
  141. data/_sass/bootstrap/mixins/_text-emphasis.scss +12 -0
  142. data/_sass/bootstrap/mixins/_text-overflow.scss +8 -0
  143. data/_sass/bootstrap/mixins/_vendor-prefixes.scss +222 -0
  144. data/_sass/core.scss +18 -0
  145. data/_sass/core/animations.scss +125 -0
  146. data/_sass/core/blog.scss +438 -0
  147. data/_sass/core/breadcrumb.scss +98 -0
  148. data/_sass/core/carousel-header.scss +91 -0
  149. data/_sass/core/carousel-styles.scss +4 -0
  150. data/_sass/core/carousel.scss +312 -0
  151. data/_sass/core/cookieconsent.scss +39 -0
  152. data/_sass/core/critical.scss +0 -0
  153. data/_sass/core/custom.scss +3 -0
  154. data/_sass/core/error.scss +186 -0
  155. data/_sass/core/fa.scss +2336 -0
  156. data/_sass/core/featherlight.scss +158 -0
  157. data/_sass/core/flipclock.scss +434 -0
  158. data/_sass/core/fly.scss +10 -0
  159. data/_sass/core/font-awesome.min.scss +4 -0
  160. data/_sass/core/fonts.scss +3 -0
  161. data/_sass/core/footer.scss +146 -0
  162. data/_sass/core/forms.scss +3 -0
  163. data/_sass/core/homepage.scss +19 -0
  164. data/_sass/core/jumbotron.scss +116 -0
  165. data/_sass/core/lightbox.scss +212 -0
  166. data/_sass/core/nav.scss +958 -0
  167. data/_sass/core/owl.carousel.min.scss +6 -0
  168. data/_sass/core/owl.theme.default.min.scss +6 -0
  169. data/_sass/core/social-media-icons.scss +67 -0
  170. data/_sass/core/syntax.scss +65 -0
  171. data/_sass/core/tables.scss +145 -0
  172. data/_sass/core/theme.scss +714 -0
  173. data/_sass/core/universal-nav.scss +161 -0
  174. data/_sass/core/youtube-lazy.scss +51 -0
  175. data/_sass/core/youtube.scss +65 -0
  176. data/_sass/home.scss +2 -0
  177. data/assets/css/main-blog.scss +19 -0
  178. data/assets/css/main-error.scss +14 -0
  179. data/assets/css/main-search.scss +13 -0
  180. data/assets/css/main.scss +12 -0
  181. data/assets/fonts/fontawesome-webfont.eot +0 -0
  182. data/assets/fonts/fontawesome-webfont.svg +2671 -0
  183. data/assets/fonts/fontawesome-webfont.ttf +0 -0
  184. data/assets/fonts/fontawesome-webfont.woff +0 -0
  185. data/assets/fonts/fontawesome-webfont.woff2 +0 -0
  186. data/assets/fonts/fontello.eot +0 -0
  187. data/assets/fonts/fontello.svg +44 -0
  188. data/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  189. data/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  190. data/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
  191. data/assets/fonts/lato-regular/LICENSE.txt +93 -0
  192. data/assets/fonts/lato-regular/Lato-regular.eot +0 -0
  193. data/assets/fonts/lato-regular/Lato-regular.svg +435 -0
  194. data/assets/fonts/lato-regular/Lato-regular.ttf +0 -0
  195. data/assets/fonts/lato-regular/Lato-regular.woff +0 -0
  196. data/assets/fonts/lato-regular/Lato-regular.woff2 +0 -0
  197. data/assets/images/Linaro-Logo.svg +1 -0
  198. data/assets/images/Linaro-Logo_light.png +0 -0
  199. data/assets/images/Linaro-Logo_standard.svg +1 -0
  200. data/assets/images/Linaro-Sprinkle.png +0 -0
  201. data/assets/images/avatar-placeholder.png +0 -0
  202. data/assets/images/breadcrumb-image.jpg +0 -0
  203. data/assets/images/close.png +0 -0
  204. data/assets/images/content/background-image1.jpg +0 -0
  205. data/assets/images/content/background-image2.png +0 -0
  206. data/assets/images/content/background-image3.jpg +0 -0
  207. data/assets/images/favicon.ico +0 -0
  208. data/assets/images/favicon.png +0 -0
  209. data/assets/images/loading.gif +0 -0
  210. data/assets/images/next.png +0 -0
  211. data/assets/images/owl.video.play.png +0 -0
  212. data/assets/images/placeholder.png +0 -0
  213. data/assets/images/prev.png +0 -0
  214. data/assets/images/social-media-image.png +0 -0
  215. data/assets/js/app/blog-comments.js +50 -0
  216. data/assets/js/app/custom.js +0 -0
  217. data/assets/js/app/facebook.js +8 -0
  218. data/assets/js/app/fly.js +45 -0
  219. data/assets/js/app/home.js +46 -0
  220. data/assets/js/app/main.js +163 -0
  221. data/assets/js/app/scroll-to-anchors.js +10 -0
  222. data/assets/js/app/search.js +29 -0
  223. data/assets/js/app/sticky-tab-bar.js +71 -0
  224. data/assets/js/app/tables.js +35 -0
  225. data/assets/js/app/youtube-lazy.js +25 -0
  226. data/assets/js/package-blog.js +13 -0
  227. data/assets/js/package-extended.js +14 -0
  228. data/assets/js/package-home.js +12 -0
  229. data/assets/js/package-main.js +13 -0
  230. data/assets/js/package-search.js +8 -0
  231. data/assets/js/vendor/bootstrap.js +2377 -0
  232. data/assets/js/vendor/cognito.js +11 -0
  233. data/assets/js/vendor/cookieconsent.js +1495 -0
  234. data/assets/js/vendor/disqus-loader.js +87 -0
  235. data/assets/js/vendor/featherlight.js +641 -0
  236. data/assets/js/vendor/jquery.js +10364 -0
  237. data/assets/js/vendor/jquery.rss.js +333 -0
  238. data/assets/js/vendor/jquery.validate.js +1601 -0
  239. data/assets/js/vendor/lazysizes.js +698 -0
  240. data/assets/js/vendor/loadCSS.js +35 -0
  241. data/assets/js/vendor/ls.unveilhooks.js +145 -0
  242. data/assets/js/vendor/owl.carousel.js +3475 -0
  243. data/assets/js/vendor/picturefill.js +1471 -0
  244. data/assets/js/vendor/shuffle.js +2004 -0
  245. data/robots.txt +9 -0
  246. metadata +246 -2
@@ -0,0 +1,87 @@
1
+ /*
2
+ disqusLoader.js v1.0
3
+ A JavaScript plugin for lazy-loading Disqus comments widget.
4
+ -
5
+ By Osvaldas Valutis, www.osvaldas.info
6
+ Available for use under the MIT License
7
+ */
8
+
9
+ ;( function( $, window, document, undefined )
10
+ {
11
+ 'use strict';
12
+
13
+ var $win = $( window ),
14
+ throttle = function(a,b){var c,d;return function(){var e=this,f=arguments,g=+new Date;c&&g<c+a?(clearTimeout(d),d=setTimeout(function(){c=g,b.apply(e,f)},a)):(c=g,b.apply(e,f))}},
15
+
16
+ throttleTO = false,
17
+ laziness = false,
18
+ disqusConfig = false,
19
+ scriptUrl = false,
20
+
21
+ scriptStatus = 'unloaded',
22
+ $instance = $(),
23
+
24
+ init = function()
25
+ {
26
+ if( !$instance.length || $instance.data( 'disqusLoaderStatus' ) == 'loaded' )
27
+ return true;
28
+
29
+ var winST = $win.scrollTop();
30
+
31
+ // if the element is too far below || too far above
32
+ if( $instance.offset().top - winST > $win.height() * laziness || winST - $instance.offset().top - $instance.outerHeight() - ( $win.height() * laziness ) > 0 )
33
+ return true;
34
+
35
+ $( '#disqus_thread' ).removeAttr( 'id' );
36
+ $instance.attr( 'id', 'disqus_thread' ).data( 'disqusLoaderStatus', 'loaded' );
37
+
38
+ if( scriptStatus == 'loaded' )
39
+ {
40
+ DISQUS.reset({ reload: true, config: disqusConfig });
41
+ }
42
+ else // unloaded | loading
43
+ {
44
+ window.disqus_config = disqusConfig;
45
+ if( scriptStatus == 'unloaded' )
46
+ {
47
+ scriptStatus = 'loading';
48
+ $.ajax(
49
+ {
50
+ url: scriptUrl,
51
+ async: true,
52
+ cache: true,
53
+ dataType: 'script',
54
+ success: function()
55
+ {
56
+ scriptStatus = 'loaded';
57
+ }
58
+ });
59
+ }
60
+ }
61
+ };
62
+
63
+ $win.on( 'scroll resize', throttle( throttleTO, init ));
64
+
65
+ $.disqusLoader = function( element, options )
66
+ {
67
+ options = $.extend({},
68
+ {
69
+ laziness: 1,
70
+ throttle: 250,
71
+ scriptUrl: false,
72
+ disqusConfig: false,
73
+
74
+ }, options );
75
+
76
+ laziness = options.laziness + 1;
77
+ throttleTO = options.throttle;
78
+ disqusConfig = options.disqusConfig;
79
+ scriptUrl = scriptUrl === false ? options.scriptUrl : scriptUrl; // set it only once
80
+ $instance = ( typeof element == 'string' ? $( element ) : element ).eq( 0 );
81
+
82
+ $instance.data( 'disqusLoaderStatus', 'unloaded' );
83
+
84
+ init();
85
+ };
86
+
87
+ })( jQuery, window, document );
@@ -0,0 +1,641 @@
1
+ /**
2
+ * Featherlight - ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
+ **/
8
+ (function($) {
9
+ "use strict";
10
+
11
+ if('undefined' === typeof $) {
12
+ if('console' in window){ window.console.info('Too much lightness, Featherlight needs jQuery.'); }
13
+ return;
14
+ }
15
+ if($.fn.jquery.match(/-ajax/)) {
16
+ if('console' in window){ window.console.info('Featherlight needs regular jQuery, not the slim version.'); }
17
+ return;
18
+ }
19
+ /* Featherlight is exported as $.featherlight.
20
+ It is a function used to open a featherlight lightbox.
21
+
22
+ [tech]
23
+ Featherlight uses prototype inheritance.
24
+ Each opened lightbox will have a corresponding object.
25
+ That object may have some attributes that override the
26
+ prototype's.
27
+ Extensions created with Featherlight.extend will have their
28
+ own prototype that inherits from Featherlight's prototype,
29
+ thus attributes can be overriden either at the object level,
30
+ or at the extension level.
31
+ To create callbacks that chain themselves instead of overriding,
32
+ use chainCallbacks.
33
+ For those familiar with CoffeeScript, this correspond to
34
+ Featherlight being a class and the Gallery being a class
35
+ extending Featherlight.
36
+ The chainCallbacks is used since we don't have access to
37
+ CoffeeScript's `super`.
38
+ */
39
+
40
+ function Featherlight($content, config) {
41
+ if(this instanceof Featherlight) { /* called with new */
42
+ this.id = Featherlight.id++;
43
+ this.setup($content, config);
44
+ this.chainCallbacks(Featherlight._callbackChain);
45
+ } else {
46
+ var fl = new Featherlight($content, config);
47
+ fl.open();
48
+ return fl;
49
+ }
50
+ }
51
+
52
+ var opened = [],
53
+ pruneOpened = function(remove) {
54
+ opened = $.grep(opened, function(fl) {
55
+ return fl !== remove && fl.$instance.closest('body').length > 0;
56
+ } );
57
+ return opened;
58
+ };
59
+
60
+ // Removes keys of `set` from `obj` and returns the removed key/values.
61
+ function slice(obj, set) {
62
+ var r = {};
63
+ for (var key in obj) {
64
+ if (key in set) {
65
+ r[key] = obj[key];
66
+ delete obj[key];
67
+ }
68
+ }
69
+ return r;
70
+ }
71
+
72
+ // NOTE: List of available [iframe attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe).
73
+ var iFrameAttributeSet = {
74
+ allow: 1, allowfullscreen: 1, frameborder: 1, height: 1, longdesc: 1, marginheight: 1, marginwidth: 1,
75
+ mozallowfullscreen: 1, name: 1, referrerpolicy: 1, sandbox: 1, scrolling: 1, src: 1, srcdoc: 1, style: 1,
76
+ webkitallowfullscreen: 1, width: 1
77
+ };
78
+
79
+ // Converts camelCased attributes to dasherized versions for given prefix:
80
+ // parseAttrs({hello: 1, hellFrozeOver: 2}, 'hell') => {froze-over: 2}
81
+ function parseAttrs(obj, prefix) {
82
+ var attrs = {},
83
+ regex = new RegExp('^' + prefix + '([A-Z])(.*)');
84
+ for (var key in obj) {
85
+ var match = key.match(regex);
86
+ if (match) {
87
+ var dasherized = (match[1] + match[2].replace(/([A-Z])/g, '-$1')).toLowerCase();
88
+ attrs[dasherized] = obj[key];
89
+ }
90
+ }
91
+ return attrs;
92
+ }
93
+
94
+ /* document wide key handler */
95
+ var eventMap = { keyup: 'onKeyUp', resize: 'onResize' };
96
+
97
+ var globalEventHandler = function(event) {
98
+ $.each(Featherlight.opened().reverse(), function() {
99
+ if (!event.isDefaultPrevented()) {
100
+ if (false === this[eventMap[event.type]](event)) {
101
+ event.preventDefault(); event.stopPropagation(); return false;
102
+ }
103
+ }
104
+ });
105
+ };
106
+
107
+ var toggleGlobalEvents = function(set) {
108
+ if(set !== Featherlight._globalHandlerInstalled) {
109
+ Featherlight._globalHandlerInstalled = set;
110
+ var events = $.map(eventMap, function(_, name) { return name+'.'+Featherlight.prototype.namespace; } ).join(' ');
111
+ $(window)[set ? 'on' : 'off'](events, globalEventHandler);
112
+ }
113
+ };
114
+
115
+ Featherlight.prototype = {
116
+ constructor: Featherlight,
117
+ /*** defaults ***/
118
+ /* extend featherlight with defaults and methods */
119
+ namespace: 'featherlight', /* Name of the events and css class prefix */
120
+ targetAttr: 'data-featherlight', /* Attribute of the triggered element that contains the selector to the lightbox content */
121
+ variant: null, /* Class that will be added to change look of the lightbox */
122
+ resetCss: false, /* Reset all css */
123
+ background: null, /* Custom DOM for the background, wrapper and the closebutton */
124
+ openTrigger: 'click', /* Event that triggers the lightbox */
125
+ closeTrigger: 'click', /* Event that triggers the closing of the lightbox */
126
+ filter: null, /* Selector to filter events. Think $(...).on('click', filter, eventHandler) */
127
+ root: 'body', /* Where to append featherlights */
128
+ openSpeed: 250, /* Duration of opening animation */
129
+ closeSpeed: 250, /* Duration of closing animation */
130
+ closeOnClick: 'background', /* Close lightbox on click ('background', 'anywhere' or false) */
131
+ closeOnEsc: true, /* Close lightbox when pressing esc */
132
+ closeIcon: '&#10005;', /* Close icon */
133
+ loading: '', /* Content to show while initial content is loading */
134
+ persist: false, /* If set, the content will persist and will be shown again when opened again. 'shared' is a special value when binding multiple elements for them to share the same content */
135
+ otherClose: null, /* Selector for alternate close buttons (e.g. "a.close") */
136
+ beforeOpen: $.noop, /* Called before open. can return false to prevent opening of lightbox. Gets event as parameter, this contains all data */
137
+ beforeContent: $.noop, /* Called when content is loaded. Gets event as parameter, this contains all data */
138
+ beforeClose: $.noop, /* Called before close. can return false to prevent opening of lightbox. Gets event as parameter, this contains all data */
139
+ afterOpen: $.noop, /* Called after open. Gets event as parameter, this contains all data */
140
+ afterContent: $.noop, /* Called after content is ready and has been set. Gets event as parameter, this contains all data */
141
+ afterClose: $.noop, /* Called after close. Gets event as parameter, this contains all data */
142
+ onKeyUp: $.noop, /* Called on key up for the frontmost featherlight */
143
+ onResize: $.noop, /* Called after new content and when a window is resized */
144
+ type: null, /* Specify type of lightbox. If unset, it will check for the targetAttrs value. */
145
+ contentFilters: ['jquery', 'image', 'html', 'ajax', 'iframe', 'text'], /* List of content filters to use to determine the content */
146
+
147
+ /*** methods ***/
148
+ /* setup iterates over a single instance of featherlight and prepares the background and binds the events */
149
+ setup: function(target, config){
150
+ /* all arguments are optional */
151
+ if (typeof target === 'object' && target instanceof $ === false && !config) {
152
+ config = target;
153
+ target = undefined;
154
+ }
155
+
156
+ var self = $.extend(this, config, {target: target}),
157
+ css = !self.resetCss ? self.namespace : self.namespace+'-reset', /* by adding -reset to the classname, we reset all the default css */
158
+ $background = $(self.background || [
159
+ '<div class="'+css+'-loading '+css+'">',
160
+ '<div class="'+css+'-content">',
161
+ '<button class="'+css+'-close-icon '+ self.namespace + '-close" aria-label="Close">',
162
+ self.closeIcon,
163
+ '</button>',
164
+ '<div class="'+self.namespace+'-inner">' + self.loading + '</div>',
165
+ '</div>',
166
+ '</div>'].join('')),
167
+ closeButtonSelector = '.'+self.namespace+'-close' + (self.otherClose ? ',' + self.otherClose : '');
168
+
169
+ self.$instance = $background.clone().addClass(self.variant); /* clone DOM for the background, wrapper and the close button */
170
+
171
+ /* close when click on background/anywhere/null or closebox */
172
+ self.$instance.on(self.closeTrigger+'.'+self.namespace, function(event) {
173
+ if(event.isDefaultPrevented()) {
174
+ return;
175
+ }
176
+ var $target = $(event.target);
177
+ if( ('background' === self.closeOnClick && $target.is('.'+self.namespace))
178
+ || 'anywhere' === self.closeOnClick
179
+ || $target.closest(closeButtonSelector).length ){
180
+ self.close(event);
181
+ event.preventDefault();
182
+ }
183
+ });
184
+
185
+ return this;
186
+ },
187
+
188
+ /* this method prepares the content and converts it into a jQuery object or a promise */
189
+ getContent: function(){
190
+ if(this.persist !== false && this.$content) {
191
+ return this.$content;
192
+ }
193
+ var self = this,
194
+ filters = this.constructor.contentFilters,
195
+ readTargetAttr = function(name){ return self.$currentTarget && self.$currentTarget.attr(name); },
196
+ targetValue = readTargetAttr(self.targetAttr),
197
+ data = self.target || targetValue || '';
198
+
199
+ /* Find which filter applies */
200
+ var filter = filters[self.type]; /* check explicit type like {type: 'image'} */
201
+
202
+ /* check explicit type like data-featherlight="image" */
203
+ if(!filter && data in filters) {
204
+ filter = filters[data];
205
+ data = self.target && targetValue;
206
+ }
207
+ data = data || readTargetAttr('href') || '';
208
+
209
+ /* check explicity type & content like {image: 'photo.jpg'} */
210
+ if(!filter) {
211
+ for(var filterName in filters) {
212
+ if(self[filterName]) {
213
+ filter = filters[filterName];
214
+ data = self[filterName];
215
+ }
216
+ }
217
+ }
218
+
219
+ /* otherwise it's implicit, run checks */
220
+ if(!filter) {
221
+ var target = data;
222
+ data = null;
223
+ $.each(self.contentFilters, function() {
224
+ filter = filters[this];
225
+ if(filter.test) {
226
+ data = filter.test(target);
227
+ }
228
+ if(!data && filter.regex && target.match && target.match(filter.regex)) {
229
+ data = target;
230
+ }
231
+ return !data;
232
+ });
233
+ if(!data) {
234
+ if('console' in window){ window.console.error('Featherlight: no content filter found ' + (target ? ' for "' + target + '"' : ' (no target specified)')); }
235
+ return false;
236
+ }
237
+ }
238
+ /* Process it */
239
+ return filter.process.call(self, data);
240
+ },
241
+
242
+ /* sets the content of $instance to $content */
243
+ setContent: function($content){
244
+ this.$instance.removeClass(this.namespace+'-loading');
245
+
246
+ /* we need a special class for the iframe */
247
+ this.$instance.toggleClass(this.namespace+'-iframe', $content.is('iframe'));
248
+
249
+ /* replace content by appending to existing one before it is removed
250
+ this insures that featherlight-inner remain at the same relative
251
+ position to any other items added to featherlight-content */
252
+ this.$instance.find('.'+this.namespace+'-inner')
253
+ .not($content) /* excluded new content, important if persisted */
254
+ .slice(1).remove().end() /* In the unexpected event where there are many inner elements, remove all but the first one */
255
+ .replaceWith($.contains(this.$instance[0], $content[0]) ? '' : $content);
256
+
257
+ this.$content = $content.addClass(this.namespace+'-inner');
258
+
259
+ return this;
260
+ },
261
+
262
+ /* opens the lightbox. "this" contains $instance with the lightbox, and with the config.
263
+ Returns a promise that is resolved after is successfully opened. */
264
+ open: function(event){
265
+ var self = this;
266
+ self.$instance.hide().appendTo(self.root);
267
+ if((!event || !event.isDefaultPrevented())
268
+ && self.beforeOpen(event) !== false) {
269
+
270
+ if(event){
271
+ event.preventDefault();
272
+ }
273
+ var $content = self.getContent();
274
+
275
+ if($content) {
276
+ opened.push(self);
277
+
278
+ toggleGlobalEvents(true);
279
+
280
+ self.$instance.fadeIn(self.openSpeed);
281
+ self.beforeContent(event);
282
+
283
+ /* Set content and show */
284
+ return $.when($content)
285
+ .always(function($content){
286
+ self.setContent($content);
287
+ self.afterContent(event);
288
+ })
289
+ .then(self.$instance.promise())
290
+ /* Call afterOpen after fadeIn is done */
291
+ .done(function(){ self.afterOpen(event); });
292
+ }
293
+ }
294
+ self.$instance.detach();
295
+ return $.Deferred().reject().promise();
296
+ },
297
+
298
+ /* closes the lightbox. "this" contains $instance with the lightbox, and with the config
299
+ returns a promise, resolved after the lightbox is successfully closed. */
300
+ close: function(event){
301
+ var self = this,
302
+ deferred = $.Deferred();
303
+
304
+ if(self.beforeClose(event) === false) {
305
+ deferred.reject();
306
+ } else {
307
+
308
+ if (0 === pruneOpened(self).length) {
309
+ toggleGlobalEvents(false);
310
+ }
311
+
312
+ self.$instance.fadeOut(self.closeSpeed,function(){
313
+ self.$instance.detach();
314
+ self.afterClose(event);
315
+ deferred.resolve();
316
+ });
317
+ }
318
+ return deferred.promise();
319
+ },
320
+
321
+ /* resizes the content so it fits in visible area and keeps the same aspect ratio.
322
+ Does nothing if either the width or the height is not specified.
323
+ Called automatically on window resize.
324
+ Override if you want different behavior. */
325
+ resize: function(w, h) {
326
+ if (w && h) {
327
+ /* Reset apparent image size first so container grows */
328
+ this.$content.css('width', '').css('height', '');
329
+ /* Calculate the worst ratio so that dimensions fit */
330
+ /* Note: -1 to avoid rounding errors */
331
+ var ratio = Math.max(
332
+ w / (this.$content.parent().width()-1),
333
+ h / (this.$content.parent().height()-1));
334
+ /* Resize content */
335
+ if (ratio > 1) {
336
+ ratio = h / Math.floor(h / ratio); /* Round ratio down so height calc works */
337
+ this.$content.css('width', '' + w / ratio + 'px').css('height', '' + h / ratio + 'px');
338
+ }
339
+ }
340
+ },
341
+
342
+ /* Utility function to chain callbacks
343
+ [Warning: guru-level]
344
+ Used be extensions that want to let users specify callbacks but
345
+ also need themselves to use the callbacks.
346
+ The argument 'chain' has callback names as keys and function(super, event)
347
+ as values. That function is meant to call `super` at some point.
348
+ */
349
+ chainCallbacks: function(chain) {
350
+ for (var name in chain) {
351
+ this[name] = $.proxy(chain[name], this, $.proxy(this[name], this));
352
+ }
353
+ }
354
+ };
355
+
356
+ $.extend(Featherlight, {
357
+ id: 0, /* Used to id single featherlight instances */
358
+ autoBind: '[data-featherlight]', /* Will automatically bind elements matching this selector. Clear or set before onReady */
359
+ defaults: Featherlight.prototype, /* You can access and override all defaults using $.featherlight.defaults, which is just a synonym for $.featherlight.prototype */
360
+ /* Contains the logic to determine content */
361
+ contentFilters: {
362
+ jquery: {
363
+ regex: /^[#.]\w/, /* Anything that starts with a class name or identifiers */
364
+ test: function(elem) { return elem instanceof $ && elem; },
365
+ process: function(elem) { return this.persist !== false ? $(elem) : $(elem).clone(true); }
366
+ },
367
+ image: {
368
+ regex: /\.(png|jpg|jpeg|gif|tiff?|bmp|svg)(\?\S*)?$/i,
369
+ process: function(url) {
370
+ var self = this,
371
+ deferred = $.Deferred(),
372
+ img = new Image(),
373
+ $img = $('<img src="'+url+'" alt="" class="'+self.namespace+'-image" />');
374
+ img.onload = function() {
375
+ /* Store naturalWidth & height for IE8 */
376
+ $img.naturalWidth = img.width; $img.naturalHeight = img.height;
377
+ deferred.resolve( $img );
378
+ };
379
+ img.onerror = function() { deferred.reject($img); };
380
+ img.src = url;
381
+ return deferred.promise();
382
+ }
383
+ },
384
+ html: {
385
+ regex: /^\s*<[\w!][^<]*>/, /* Anything that starts with some kind of valid tag */
386
+ process: function(html) { return $(html); }
387
+ },
388
+ ajax: {
389
+ regex: /./, /* At this point, any content is assumed to be an URL */
390
+ process: function(url) {
391
+ var self = this,
392
+ deferred = $.Deferred();
393
+ /* we are using load so one can specify a target with: url.html #targetelement */
394
+ var $container = $('<div></div>').load(url, function(response, status){
395
+ if ( status !== "error" ) {
396
+ deferred.resolve($container.contents());
397
+ }
398
+ deferred.fail();
399
+ });
400
+ return deferred.promise();
401
+ }
402
+ },
403
+ iframe: {
404
+ process: function(url) {
405
+ var deferred = new $.Deferred();
406
+ var $content = $('<iframe/>');
407
+ var css = parseAttrs(this, 'iframe');
408
+ var attrs = slice(css, iFrameAttributeSet);
409
+ $content.hide()
410
+ .attr('src', url)
411
+ .attr(attrs)
412
+ .css(css)
413
+ .on('load', function() { deferred.resolve($content.show()); })
414
+ // We can't move an <iframe> and avoid reloading it,
415
+ // so let's put it in place ourselves right now:
416
+ .appendTo(this.$instance.find('.' + this.namespace + '-content'));
417
+ return deferred.promise();
418
+ }
419
+ },
420
+ text: {
421
+ process: function(text) { return $('<div>', {text: text}); }
422
+ }
423
+ },
424
+
425
+ functionAttributes: ['beforeOpen', 'afterOpen', 'beforeContent', 'afterContent', 'beforeClose', 'afterClose'],
426
+
427
+ /*** class methods ***/
428
+ /* read element's attributes starting with data-featherlight- */
429
+ readElementConfig: function(element, namespace) {
430
+ var Klass = this,
431
+ regexp = new RegExp('^data-' + namespace + '-(.*)'),
432
+ config = {};
433
+ if (element && element.attributes) {
434
+ $.each(element.attributes, function(){
435
+ var match = this.name.match(regexp);
436
+ if (match) {
437
+ var val = this.value,
438
+ name = $.camelCase(match[1]);
439
+ if ($.inArray(name, Klass.functionAttributes) >= 0) { /* jshint -W054 */
440
+ val = new Function(val); /* jshint +W054 */
441
+ } else {
442
+ try { val = JSON.parse(val); }
443
+ catch(e) {}
444
+ }
445
+ config[name] = val;
446
+ }
447
+ });
448
+ }
449
+ return config;
450
+ },
451
+
452
+ /* Used to create a Featherlight extension
453
+ [Warning: guru-level]
454
+ Creates the extension's prototype that in turn
455
+ inherits Featherlight's prototype.
456
+ Could be used to extend an extension too...
457
+ This is pretty high level wizardy, it comes pretty much straight
458
+ from CoffeeScript and won't teach you anything about Featherlight
459
+ as it's not really specific to this library.
460
+ My suggestion: move along and keep your sanity.
461
+ */
462
+ extend: function(child, defaults) {
463
+ /* Setup class hierarchy, adapted from CoffeeScript */
464
+ var Ctor = function(){ this.constructor = child; };
465
+ Ctor.prototype = this.prototype;
466
+ child.prototype = new Ctor();
467
+ child.__super__ = this.prototype;
468
+ /* Copy class methods & attributes */
469
+ $.extend(child, this, defaults);
470
+ child.defaults = child.prototype;
471
+ return child;
472
+ },
473
+
474
+ attach: function($source, $content, config) {
475
+ var Klass = this;
476
+ if (typeof $content === 'object' && $content instanceof $ === false && !config) {
477
+ config = $content;
478
+ $content = undefined;
479
+ }
480
+ /* make a copy */
481
+ config = $.extend({}, config);
482
+
483
+ /* Only for openTrigger, filter & namespace... */
484
+ var namespace = config.namespace || Klass.defaults.namespace,
485
+ tempConfig = $.extend({}, Klass.defaults, Klass.readElementConfig($source[0], namespace), config),
486
+ sharedPersist;
487
+ var handler = function(event) {
488
+ var $target = $(event.currentTarget);
489
+ /* ... since we might as well compute the config on the actual target */
490
+ var elemConfig = $.extend(
491
+ {$source: $source, $currentTarget: $target},
492
+ Klass.readElementConfig($source[0], tempConfig.namespace),
493
+ Klass.readElementConfig(event.currentTarget, tempConfig.namespace),
494
+ config);
495
+ var fl = sharedPersist || $target.data('featherlight-persisted') || new Klass($content, elemConfig);
496
+ if(fl.persist === 'shared') {
497
+ sharedPersist = fl;
498
+ } else if(fl.persist !== false) {
499
+ $target.data('featherlight-persisted', fl);
500
+ }
501
+ if (elemConfig.$currentTarget.blur) {
502
+ elemConfig.$currentTarget.blur(); // Otherwise 'enter' key might trigger the dialog again
503
+ }
504
+ fl.open(event);
505
+ };
506
+
507
+ $source.on(tempConfig.openTrigger+'.'+tempConfig.namespace, tempConfig.filter, handler);
508
+
509
+ return {filter: tempConfig.filter, handler: handler};
510
+ },
511
+
512
+ current: function() {
513
+ var all = this.opened();
514
+ return all[all.length - 1] || null;
515
+ },
516
+
517
+ opened: function() {
518
+ var klass = this;
519
+ pruneOpened();
520
+ return $.grep(opened, function(fl) { return fl instanceof klass; } );
521
+ },
522
+
523
+ close: function(event) {
524
+ var cur = this.current();
525
+ if(cur) { return cur.close(event); }
526
+ },
527
+
528
+ /* Does the auto binding on startup.
529
+ Meant only to be used by Featherlight and its extensions
530
+ */
531
+ _onReady: function() {
532
+ var Klass = this;
533
+ if(Klass.autoBind){
534
+ var $autobound = $(Klass.autoBind);
535
+ /* Bind existing elements */
536
+ $autobound.each(function(){
537
+ Klass.attach($(this));
538
+ });
539
+ /* If a click propagates to the document level, then we have an item that was added later on */
540
+ $(document).on('click', Klass.autoBind, function(evt) {
541
+ if (evt.isDefaultPrevented()) {
542
+ return;
543
+ }
544
+ var $cur = $(evt.currentTarget);
545
+ var len = $autobound.length;
546
+ $autobound = $autobound.add($cur);
547
+ if(len === $autobound.length) {
548
+ return; /* already bound */
549
+ }
550
+ /* Bind featherlight */
551
+ var data = Klass.attach($cur);
552
+ /* Dispatch event directly */
553
+ if (!data.filter || $(evt.target).parentsUntil($cur, data.filter).length > 0) {
554
+ data.handler(evt);
555
+ }
556
+ });
557
+ }
558
+ },
559
+
560
+ /* Featherlight uses the onKeyUp callback to intercept the escape key.
561
+ Private to Featherlight.
562
+ */
563
+ _callbackChain: {
564
+ onKeyUp: function(_super, event){
565
+ if(27 === event.keyCode) {
566
+ if (this.closeOnEsc) {
567
+ $.featherlight.close(event);
568
+ }
569
+ return false;
570
+ } else {
571
+ return _super(event);
572
+ }
573
+ },
574
+
575
+ beforeOpen: function(_super, event) {
576
+ // Used to disable scrolling
577
+ $(document.documentElement).addClass('with-featherlight');
578
+
579
+ // Remember focus:
580
+ this._previouslyActive = document.activeElement;
581
+
582
+ // Disable tabbing:
583
+ // See http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus
584
+ this._$previouslyTabbable = $("a, input, select, textarea, iframe, button, iframe, [contentEditable=true]")
585
+ .not('[tabindex]')
586
+ .not(this.$instance.find('button'));
587
+
588
+ this._$previouslyWithTabIndex = $('[tabindex]').not('[tabindex="-1"]');
589
+ this._previousWithTabIndices = this._$previouslyWithTabIndex.map(function(_i, elem) {
590
+ return $(elem).attr('tabindex');
591
+ });
592
+
593
+ this._$previouslyWithTabIndex.add(this._$previouslyTabbable).attr('tabindex', -1);
594
+
595
+ if (document.activeElement.blur) {
596
+ document.activeElement.blur();
597
+ }
598
+ return _super(event);
599
+ },
600
+
601
+ afterClose: function(_super, event) {
602
+ var r = _super(event);
603
+ // Restore focus
604
+ var self = this;
605
+ this._$previouslyTabbable.removeAttr('tabindex');
606
+ this._$previouslyWithTabIndex.each(function(i, elem) {
607
+ $(elem).attr('tabindex', self._previousWithTabIndices[i]);
608
+ });
609
+ this._previouslyActive.focus();
610
+ // Restore scroll
611
+ if(Featherlight.opened().length === 0) {
612
+ $(document.documentElement).removeClass('with-featherlight');
613
+ }
614
+ return r;
615
+ },
616
+
617
+ onResize: function(_super, event){
618
+ this.resize(this.$content.naturalWidth, this.$content.naturalHeight);
619
+ return _super(event);
620
+ },
621
+
622
+ afterContent: function(_super, event){
623
+ var r = _super(event);
624
+ this.$instance.find('[autofocus]:not([disabled])').focus();
625
+ this.onResize(event);
626
+ return r;
627
+ }
628
+ }
629
+ });
630
+
631
+ $.featherlight = Featherlight;
632
+
633
+ /* bind jQuery elements to trigger featherlight */
634
+ $.fn.featherlight = function($content, config) {
635
+ Featherlight.attach(this, $content, config);
636
+ return this;
637
+ };
638
+
639
+ /* bind featherlight on ready if config autoBind is set */
640
+ $(document).ready(function(){ Featherlight._onReady(); });
641
+ }(jQuery));