diff --git a/.gitignore b/.gitignore index b608297..6f5f4fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules/ strip-*.zip -*.log \ No newline at end of file +*.log +.idea +.history \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js index f659ae9..b4ffc32 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,79 +1,80 @@ -module.exports = function(grunt) { - +module.exports = function (grunt) { // Config grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), + pkg: grunt.file.readJSON("package.json"), dirs: { - dest: 'dist' + dest: "dist", }, - vars: { }, + vars: {}, concat: { js: { options: { - process: true + process: true, }, src: [ - 'src/js/umd-head.js', - 'src/js/setup.js', - 'src/js/skins.js', + "src/js/umd-head.js", + "src/js/setup.js", + "src/js/skins.js", - // helpers - 'src/js/helpers/browser.js', - 'src/js/helpers/helpers.js', - 'src/js/helpers/support.js', - 'src/js/helpers/bounds.js', - 'src/js/helpers/imageready.js', - 'src/js/helpers/spinner.js', - 'src/js/helpers/timers.js', - 'src/js/helpers/url.js', - 'src/js/helpers/vimeoready.js', + // helpers + "src/js/helpers/browser.js", + "src/js/helpers/helpers.js", + "src/js/helpers/support.js", + "src/js/helpers/bounds.js", + "src/js/helpers/imageready.js", + "src/js/helpers/spinner.js", + "src/js/helpers/timers.js", + "src/js/helpers/url.js", + "src/js/helpers/vimeoready.js", - // core - 'src/js/options.js', - 'src/js/view.js', - 'src/js/pages.js', - 'src/js/page.js', - 'src/js/window.js', - 'src/js/keyboard.js', + // core + "src/js/options.js", + "src/js/view.js", + "src/js/pages.js", + "src/js/page.js", + "src/js/window.js", + "src/js/keyboard.js", - 'src/js/api.js', + "src/js/api.js", - 'src/js/umd-tail.js' + "src/js/umd-tail.js", ], - dest: '<%= dirs.dest %>/js/strip.pkgd.js' + dest: "<%= dirs.dest %>/js/strip.pkgd.js", }, css: { options: { - process: true + process: true, }, - src: ['src/css/strip.css'], - dest: '<%= dirs.dest %>/css/strip.css' - } + src: ["src/css/strip.css"], + dest: "<%= dirs.dest %>/css/strip.css", + }, }, copy: { - 'css': { + css: { files: [ { expand: true, - cwd: 'src/css/strip-skins/', - src: ['**'], - dest: '<%= dirs.dest %>/css/strip-skins/' - } - ] - } + cwd: "src/css/strip-skins/", + src: ["**"], + dest: "<%= dirs.dest %>/css/strip-skins/", + }, + ], + }, }, uglify: { js: { options: { - preserveComments: 'some' + output: { + comments: "some", + }, }, - 'src': ['<%= dirs.dest %>/js/strip.pkgd.js'], - 'dest': '<%= dirs.dest %>/js/strip.pkgd.min.js' - } + src: ["<%= dirs.dest %>/js/strip.pkgd.js"], + dest: "<%= dirs.dest %>/js/strip.pkgd.min.js", + }, }, svgmin: { @@ -81,38 +82,41 @@ module.exports = function(grunt) { plugins: [ { removeViewBox: false }, { removeUselessStrokeAndFill: false }, - { removeEmptyAttrs: false } - ] + { removeEmptyAttrs: false }, + ], }, dist: { - files: [{ - expand: true, - cwd: 'src/css/', - src: ['**/*.svg'], - dest: 'src/css/' - }] - } + files: [ + { + expand: true, + cwd: "src/css/", + src: ["**/*.svg"], + dest: "src/css/", + }, + ], + }, }, clean: { - dest: '<%= dirs.dest %>/*' - } + dest: "<%= dirs.dest %>/*", + }, }); // Load plugins - grunt.loadNpmTasks('grunt-contrib-concat'); - grunt.loadNpmTasks('grunt-contrib-copy'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.loadNpmTasks('grunt-svgmin'); - grunt.loadNpmTasks('grunt-sync'); + grunt.loadNpmTasks("grunt-contrib-concat"); + grunt.loadNpmTasks("grunt-contrib-copy"); + grunt.loadNpmTasks("grunt-contrib-uglify"); + grunt.loadNpmTasks("grunt-contrib-clean"); + grunt.loadNpmTasks("grunt-svgmin"); // Tasks - grunt.registerTask('default', [ - 'clean:dest', - 'concat:js', 'uglify:js', - 'concat:css', 'copy:css' + grunt.registerTask("default", [ + "clean:dest", + "concat:js", + "uglify:js", + "concat:css", + "copy:css", ]); - grunt.registerTask('svg', ['svgmin']); -}; \ No newline at end of file + grunt.registerTask("svg", ["svgmin"]); +}; diff --git a/README.md b/README.md index e931d72..dc131be 100644 --- a/README.md +++ b/README.md @@ -2,54 +2,667 @@ _An Unobtrusive Responsive Lightbox_ -Strip is a Lightbox that only partially covers the page. This is less intrusive and leaves room to interact with the page on larger screens while giving smaller mobile devices the classic Lightbox experience. +Strip is a Lightbox that only partially covers the page. This leaves room to interact with the page on larger screens while giving smaller devices the classic Lightbox experience. -See [stripjs.com](http://www.stripjs.com) for demos and docs. +![screenshot](https://cloud.githubusercontent.com/assets/5575/4969788/ec4fc80e-686c-11e4-8406-614db6980325.jpg) -[![screenshot](https://cloud.githubusercontent.com/assets/5575/4969788/ec4fc80e-686c-11e4-8406-614db6980325.jpg)](http://www.stripjs.com) +- [Strip](#strip) + - [Usage](#usage) + - [Installation](#installation) + - [Basic Usage](#basic-usage) + - [Groups](#groups) + - [Media types](#media-types) + - [Image](#image) + - [Youtube](#youtube) + - [Vimeo](#vimeo) + - [Javascript API](#javascript-api) + - [Groups](#groups-1) + - [Links](#links) + - [Options](#options) + - [Callbacks](#callbacks) + - [Skins](#skins) + - [Default options](#default-options) + - [Changing the default skin](#changing-the-default-skin) -## Install +## Usage -Install with [Bower](http://bower.io): `bower install strip` +### Installation -[Install with npm](http://npmjs.com/package/@staaky/strip): `npm install @staaky/strip` +Include Strip below the latest 3.x release of [jQuery](https://www.jquery.com/): -## License +```html + + + +``` + +Alternatively Strip can be installed using [npm](https://npmjs.com/package/@staaky/strip): + +```bash +npm install @staaky/strip +``` + +### Basic Usage + +The most basic way to use Strip is by adding the class `strip` to a link: + +```html +Show image +``` + +A caption can be added using the data-strip-caption attribute: + +```html +Caption +``` + +Or customize Strip by putting [options](#options) on the `data-strip-options` attribute: + +```html +Options +``` + +### Groups + +Create groups by giving links a `data-strip-group` attribute with a unique name: + +```html +Image 1 +Image 2 +``` + +The `data-strip-group-options` attribute can be used to set options for all items in the group: + +```html +This group +has shared options +``` + +## Media types + +Strip attempts to automatically detect the media type using the given url. The type can also be set to one of the following values using the `data-strip-type` attribute: `image`, `youtube` or `vimeo`. + +### Image + +Most of the time setting the type will not be required for images, it will be required in cases where Strip cannot detect it based on the url: + +```html +Image +``` + +### Youtube + +Strip will detect Youtube links and automatically embed them: + +```html +Youtube +``` + +Options can be set using the `youtube` option, see [YouTube Embedded Players and Player Parameters](https://developers.google.com/youtube/player_parameters?playerVersion=HTML5) for all the available options. + +```html +Youtube - Dimensions and options +``` + +### Vimeo + +Strips embeds Vimeo videos using the Vimeo Player API. + +```html +Vimeo +``` + +Options can be set using the `vimeo` option, see [Vimeo Player Embedding](https://developer.vimeo.com/player/embedding) for all the available options. + +## Javascript API + +The API allows Strip to be used with Javascript, as an alternative to using the `strip` class on links. + + + + + + + + + + + + + + + + + +
Method
+ +`Strip.show()` + + + +A single item can be shown by giving `Strip.show()` a url: + +```js +Strip.show("image.jpg"); +``` + +Add a caption by using an object instead: + +```js +Strip.show({ + url: "image.jpg", + caption: "Caption for this image", +}); +``` + +This object also accepts [options](#options) to customize Strip: + +```js +Strip.show({ + url: "http://vimeo.com/32071937", + options: { + side: "top", + }, +}); +``` + +#### Groups + +Groups can be shown by giving `Strip.show()` an array with multiple items: + +```js +// use urls +Strip.show(["image1.jpg", "image2.jpg"]); + +// or objects +Strip.show([ + { url: "image1.jpg", caption: "Caption for this image" }, + { url: "image2.jpg", caption: "Another caption" }, +]); +``` + +[Options](#options) for the entire group can be set using the second argument: + +```js +Strip.show(["image1.jpg", "image2.jpg"], { + loop: false, + maxWidth: 500, +}); +``` + +Open Strip at a specific position by setting a number as the last argument: + +```js +Strip.show(["image1.jpg", "image2.jpg"], 2); +``` + +#### Links + +Links that use the strip class can also be opened by passing `Strip.show()` an element: + +```js +Strip.show($("#elementid")[0]); +``` + +
+ +`Strip.hide()` + + + +Close Strip at any time by calling `Strip.hide()`: + +```js +Strip.hide(); +``` + +
+ +`Strip.disable()` + + + +Disables Strip. When disabled, links using the `strip` class will no longer open Strip but work as regular links. Calls to `Strip.show()` will use a fallback to make them behave like regular links. + +```js +Strip.disable(); +``` + +Use `Strip.fallback(false)` should you need to disable this fallback as well: + +```js +Strip.fallback(false).disable(); +``` + +
+ +`Strip.enable()` + + + +Enable Strip if it was previously disabled. + +```js +Strip.enable(); +``` + +
+ +`Strip.fallback()` + + + +When Strip is disabled it will fallback to making `Strip.show()` calls open as regular links. By disabling this fallback API calls will do nothing at all. + +```js +Strip.fallback(false); +``` + +
+ +`Strip.setDefaultSkin()` + + + +Sets the name of the default skin, this skin will be used when no `skin` option is provided. + +```js +Strip.setDefaultSkin("custom"); +``` + +
+ +## Options + + + + + + + + + + + + + + + + + + + + + + + + + + +
Option
+ +`effects` + + + +Sets the duration of individual effects, or disables them when set to _false_. + +``` +effects: false +``` + +These are all available effects: + +```js +effects: { + spinner: { show: 200, hide: 200 }, + transition: { min: 175, max: 250 }, + ui: { show: 0, hide: 200 }, + window: { show: 300, hide: 300 } +} +``` + +
+ +`hideOnClickOutside` + + + +Hide Strip when clicking outside of it or an element that could open it, enabled by default. + +``` +hideOnClickOutside: false +``` -Strip may be used in commercial projects and applications with the one-time purchase of a commercial license. If you are paid to do your job, and part of your job is implementing Strip, a commercial license is required. +
-[http://www.stripjs.com/license](http://www.stripjs.com/license) +`keyboard` -For non-commercial projects and applications, you may use Strip under the terms of the [Creative Commons BY-NC-ND 3.0 License](http://creativecommons.org/licenses/by-nc-nd/3.0/) for free. + -## Build +Enable or disable individual keyboard buttons or all of them when set to _false_. -The latest release can be found on [stripjs.com/download](http://www.stripjs.com/download). +``` +keyboard: false +``` + +Or use an object to toggle individual buttons: + +```js +keyboard: { + left: true, + right: true, + esc: false +} +``` + +**Note:** `youtube` and `vimeo` will always have left and right disabled, because a video could require these keys. + +
+ +`loop` -To build Strip yourself start by cloning a copy of the main Strip git repo by running: + + +When set to true a group becomes a loop, making it possible to move between the first and last item: ``` -git clone git://github.com/staaky/strip.git +loop: true ``` -Go inside the strip folder that was just fetched and install dependencies: +
+ +`maxHeight` + + + +Sets a maximum height for the content. ``` -cd strip && npm install +maxHeight: 500 ``` -Make sure the [grunt command line interface](https://github.com/gruntjs/grunt-cli) is installed as a global package: +
+ +`maxWidth` + + + +Sets a maximum width for the content. ``` -npm install -g grunt-cli +maxWidth: 500 ``` -Now run the `grunt` command, this updates files in `dist` to include the latest changes made in the `src` folder: +
+ +`overlap` + + + +Allows buttons to overlap the content when set to _true_, which is the default. Disabling overlap will cause buttons to be positioned outside of the content. ``` -grunt +overlap: false +``` + +**Note:** Vimeo and Youtube always have `overlap: false` because overlapping buttons could otherwise prevent interaction with the video. + +
+ +`position` + + + +Show or hide the position indicator. + +``` +position: false +``` + +
+ +`preload` + + + +Sets the items to preload before and after the current item, or disables preloading when set to _false_. + +``` +preload: [1,2] // preload 1 before and 2 after +``` + +``` +preload: false // disables preloading +``` + +
+ +`side` + + + +Set the side to position Strip on to `top`, `bottom`, `left` or `right`. + +``` +side: 'top' +``` + +
+ +`skin` + + + +Sets the skin. If you've provided default options for this skin they'll be applied as a starting point for other options. The default skin is `strip`. + +``` +skin: 'custom' +``` + +
+ +`spinner` + + + +Disables the loading icon when set to _false_. + +``` +spinner: false +``` + +
+ +`toggle` + + + +Clicking elements will toggle Strip, this behavior can be disabed by setting `toggle` to _false_. Doing so will keep Strip open even if an element is clicked twice. + +``` +toggle: false +``` + +**Note:** `Strip.show()` calls don't use toggle behavior, this only works for elements with `class='strip'` + +
+ +`vimeo` + + + +Sets the player parameters of a Vimeo video, available options can be found in the Vimeo documentation: [Vimeo Player Embedding](https://developer.vimeo.com/player/embedding). + +```js +vimeo: { + autoplay: 1, + title: 1, + byline: 1, + portrait: 0, + loop: 0 +} +``` + +
+ +`youtube` + + + +youtubeSets the player parameters of a Youtube video, available options can be found in the Youtube documentation: [YouTube Embedded Players and Player Parameters](https://developers.google.com/youtube/player_parameters?playerVersion=HTML5). + +```js +youtube: { + autohide: 1, + autoplay: 1, + controls: 1, + enablejsapi: 1, + hd: 1, + iv_load_policy: 3, + loop: 0, + modestbranding: 1, + rel: 0 +} +``` + +
+ +## Callbacks + +Callbacks can be used alongside other [Options](#options). + + + + + + + + + + + + + +
Callback
+ +`afterPosition` + + + +A function to call after the position changed. The first argument is the current position within the group. + +```js +afterPosition: function(position) { + console.log("You've reached position " + position); +} +``` + +
+ +`afterHide` + + + +A function to call after Strip is fully hidden. + +```js +afterHide: function() { + console.log('Strip is no longer visible'); +} +``` + +
+ +`onResize` + + + +This callback allows you to respond to Strip as it's resizing and make adjustments to your page. You could for example slide your page along or adjust margins. The parameters of onResize give you everything needed to make these adjustments. + +```js +onResize: function(fxProperty, fxValue, side) { + console.log(fxProperty, fxValue, side); + // logs: 'width', 0, 'right' when starting the animation + // and adjusts fxValue for each step in the animation +} +``` + +`fxProperty` is the property currently animated, which can be _'width'_ or _'height'_. `fxValue` is the value of that property at the current step in the animation. side is the current side Strip is positioned on, which can be _'top'_, _'bottom'_, _'left'_ or _'right'_. + +
+ +`onShow` + + + +A function to call when Strip comes into view. + +```js +onShow: function() { + console.log('Strip is visible'); +} +``` + +
+ +## Skins + +Custom skins can be added by copying the existing default skin called `strip`, rename it and modify it to your needs. It's recommended to do this in a separate css file so that `strip.css` can be upgraded without losing anything. + +Once you have a skin in place it can be used with the `skin` option: + +``` +skin: 'custom' +``` + +### Default options + +Default options can be provided for a skin by extending `Strip.Skins` with options for your custom skin: + +```js +$.extend(Strip.Skins, { + custom: { + loop: false, + }, +}); +``` + +### Changing the default skin + +The default skin can be changed using `Strip.setDefaultSkin()`. + +```js +Strip.setDefaultSkin("custom"); ``` -* * * +--- -By [Nick Stakenburg](http://www.nickstakenburg.com) +By [Nick Stakenburg](https://github.com/staaky) diff --git a/bower.json b/bower.json deleted file mode 100644 index 4c9bdc2..0000000 --- a/bower.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "strip", - "description": "An Unobtrusive Responsive Lightbox", - "version": "1.6.4", - "homepage": "http://stripjs.com", - "keywords": [ - "lightbox", - "modal", - "window", - "responsive", - "jquery", - "jquery-plugin" - ], - "main": [ - "dist/js/strip.pkgd.js", - "dist/css/strip.css" - ], - "ignore": [ - "node_modules", - "bower_components", - "src", - "/.*", - "bower.json", - "Gruntfile.js", - "package.json", - "README.md" - ], - "dependencies": { - "jquery": "^1.11.3" - } -} \ No newline at end of file diff --git a/dist/css/strip.css b/dist/css/strip.css index 2ba03f6..7382013 100644 --- a/dist/css/strip.css +++ b/dist/css/strip.css @@ -1,21 +1,20 @@ /*! - * Strip - An Unobtrusive Responsive Lightbox - v1.6.4 - * (c) 2014-2016 Nick Stakenburg + * Strip - An Unobtrusive Responsive Lightbox - v1.8.0 + * (c) 2014-2021 Nick Stakenburg * - * http://www.stripjs.com + * https://github.com/staaky/strip * - * Licensing: - * - Commercial: http://www.stripjs.com/license - * - Non-commercial: http://creativecommons.org/licenses/by-nc-nd/3.0 + * @license: https://creativecommons.org/licenses/by/4.0 */ .strp-window { - position: fixed; - width: 0; - height: 100%; + position: fixed; + width: 0; + height: 100%; overflow: hidden; background: #292929; - font: 13px/20px "Lucida Sans", "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, sans-serif; + font: 13px/20px "Lucida Sans", "Lucida Sans Unicode", "Lucida Grande", Verdana, + Arial, sans-serif; } .strp-window.strp-vertical { @@ -26,23 +25,31 @@ /* margin is added around the window to keep a visual reference * to the underlying page at all times. */ -.strp-window { margin-left: 40px; } -.strp-window.strp-vertical { margin-left: 0; margin-bottom: 40px; } +.strp-window { + margin-left: 40px; +} +.strp-window.strp-vertical { + margin-left: 0; + margin-bottom: 40px; +} /* fullscreen on smaller screens (iPhone 6+ and smaller) * since min-width is used to make this work it won't show on IE8, but * we're not expecting that browser to have a mobile sized screen anyway */ @media all and (max-width: 414px) and (orientation: portrait), - all and (max-width: 736px) and (max-height: 414px) { - .strp-window.strp-horizontal { min-width: 100%; } + all and (max-width: 736px) and (max-height: 414px) { + .strp-window.strp-horizontal { + min-width: 100%; + } } @media all and (max-height: 414px) and (orientation: landscape), - all and (max-height: 736px) and (max-width: 414px){ - .strp-window.strp-vertical { min-height: 100%; } + all and (max-height: 736px) and (max-width: 414px) { + .strp-window.strp-vertical { + min-height: 100%; + } } - /* z-index */ .strp-window, .strp-spinner-move { @@ -51,14 +58,16 @@ /* reset box-sizing */ .strp-window, -.strp-window [class^='strp-'], +.strp-window [class^="strp-"], .strp-spinner-move, -.strp-spinner-move [class^='strp-'] { +.strp-spinner-move [class^="strp-"] { box-sizing: border-box; } /* Chrome hack, this fixes a visual glitch when quickly toggling a video */ -.strp-window { transform: translateZ(0px); } +.strp-window { + transform: translateZ(0px); +} /* some properties on the window are used to toggle things * like margin and the fullscreen mode, @@ -78,25 +87,73 @@ } /* sides */ -.strp-side-right { top: 0; right: 0; } -.strp-side-right .strp-pages { top: 0; right: 0; } -.strp-side-right .strp-page { top: 0; right: 0; } -.strp-side-right .strp-close { top: 0; right: 0; } - -.strp-side-left { top: 0; left: 0; } -.strp-side-left .strp-pages { top: 0; left: 0; } -.strp-side-left .strp-page { top: 0; left: 0; } -.strp-side-left .strp-close { top: 0; right: 0; } - -.strp-side-top { top: 0; left: 0; } -.strp-side-top .strp-pages { top: 0; left: 0; } -.strp-side-top .strp-page { top: 0; left: 0; } -.strp-side-top .strp-close { top: 0; right: 0; } - -.strp-side-bottom { bottom: 0; left: 0; } -.strp-side-bottom .strp-pages { bottom: 0; left: 0; } -.strp-side-bottom .strp-page { bottom: 0; left: 0; } -.strp-side-bottom .strp-close { top: 0; right: 0; } +.strp-side-right { + top: 0; + right: 0; +} +.strp-side-right .strp-pages { + top: 0; + right: 0; +} +.strp-side-right .strp-page { + top: 0; + right: 0; +} +.strp-side-right .strp-close { + top: 0; + right: 0; +} + +.strp-side-left { + top: 0; + left: 0; +} +.strp-side-left .strp-pages { + top: 0; + left: 0; +} +.strp-side-left .strp-page { + top: 0; + left: 0; +} +.strp-side-left .strp-close { + top: 0; + right: 0; +} + +.strp-side-top { + top: 0; + left: 0; +} +.strp-side-top .strp-pages { + top: 0; + left: 0; +} +.strp-side-top .strp-page { + top: 0; + left: 0; +} +.strp-side-top .strp-close { + top: 0; + right: 0; +} + +.strp-side-bottom { + bottom: 0; + left: 0; +} +.strp-side-bottom .strp-pages { + bottom: 0; + left: 0; +} +.strp-side-bottom .strp-page { + bottom: 0; + left: 0; +} +.strp-side-bottom .strp-close { + top: 0; + right: 0; +} .strp-page { position: absolute; @@ -124,14 +181,23 @@ navbutton = 72 = 54 + (2 * 9 margin) closebutton = 48 */ -.strp-no-overlap .strp-container { padding: 48px 72px; } -.strp-no-overlap.strp-no-sides .strp-container { padding: 48px 0; } - -.strp-vertical .strp-no-overlap .strp-container { padding: 0 72px; } -.strp-vertical .strp-no-overlap.strp-no-sides .strp-container { padding: 0 48px; } +.strp-no-overlap .strp-container { + padding: 48px 72px; +} +.strp-no-overlap.strp-no-sides .strp-container { + padding: 48px 0; +} -.strp-hovering-clickable .strp-container { cursor: pointer; } +.strp-vertical .strp-no-overlap .strp-container { + padding: 0 72px; +} +.strp-vertical .strp-no-overlap.strp-no-sides .strp-container { + padding: 0 48px; +} +.strp-hovering-clickable .strp-container { + cursor: pointer; +} .strp-content-element { position: absolute; @@ -196,9 +262,9 @@ background: none; text-decoration: underline; } -.strp-info a:hover { color: #eee; } - - +.strp-info a:hover { + color: #eee; +} /* < > */ .strp-nav { @@ -213,10 +279,17 @@ -moz-user-select: none; user-select: none; } -.strp-nav-previous { left: 0; } -.strp-nav-next { right: 0; left: auto; } +.strp-nav-previous { + left: 0; +} +.strp-nav-next { + right: 0; + left: auto; +} -.strp-nav-disabled { cursor: default; } +.strp-nav-disabled { + cursor: default; +} .strp-nav-button { float: left; @@ -243,7 +316,6 @@ background-repeat: no-repeat; } - /* X */ .strp-close { position: absolute; @@ -268,13 +340,16 @@ .strp-close-background { filter: alpha(opacity=80); - opacity: .8; + opacity: 0.8; background-color: #101010; } -.strp-close:hover .strp-close-background { background-color: #161616; } - +.strp-close:hover .strp-close-background { + background-color: #161616; +} -.strp-has-error .strp-container { background-color: #ca3434; } +.strp-has-error .strp-container { + background-color: #ca3434; +} .strp-error { position: absolute; top: 50%; @@ -285,9 +360,11 @@ margin-top: -120px; background-position: 50% 50%; background-repeat: no-repeat; - background-image: url('strip-skins/strip/error.svg'); + background-image: url("strip-skins/strip/error.svg"); +} +.strp-no-svg .strp-error { + background-image: url("strip-skins/strip/error.png"); } -.strp-no-svg .strp-error { background-image: url('strip-skins/strip/error.png'); } /* Spinner - loading icon, wrapped by a div that moves it */ .strp-spinner-move { @@ -299,7 +376,10 @@ /* ensure overflow during a jQuery animation */ overflow: visible !important; } -.strp-spinner-move.strp-vertical { width: 48px; height: 0; } +.strp-spinner-move.strp-vertical { + width: 48px; + height: 0; +} .strp-spinner { width: 48px; @@ -309,18 +389,52 @@ } /* different sides */ -.strp-spinner-move.strp-side-top { top: 0; right: 0; bottom: auto; left: auto; } -.strp-spinner-move.strp-side-bottom { top: auto; right: 0; bottom: 0; left: auto; } - -.strp-spinner-move.strp-side-right .strp-spinner { margin-left: -48px; } -.strp-spinner-move.strp-side-left .strp-spinner { margin-right: -48px; float: right; } -.strp-spinner-move.strp-side-bottom .strp-spinner { margin-top: -48px; } -.strp-spinner-move.strp-side-top .strp-spinner { position: absolute; bottom: 0; right: 0; margin-bottom: -48px; } +.strp-spinner-move.strp-side-top { + top: 0; + right: 0; + bottom: auto; + left: auto; +} +.strp-spinner-move.strp-side-bottom { + top: auto; + right: 0; + bottom: 0; + left: auto; +} +.strp-spinner-move.strp-side-right .strp-spinner { + margin-left: -48px; +} +.strp-spinner-move.strp-side-left .strp-spinner { + margin-right: -48px; + float: right; +} +.strp-spinner-move.strp-side-bottom .strp-spinner { + margin-top: -48px; +} +.strp-spinner-move.strp-side-top .strp-spinner { + position: absolute; + bottom: 0; + right: 0; + margin-bottom: -48px; +} -@-moz-keyframes strp-spinner-spin { 100% { -moz-transform: rotate(360deg); } } -@-webkit-keyframes strp-spinner-spin { 100% { -webkit-transform: rotate(360deg); } } -@keyframes strp-spinner-spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } } +@-moz-keyframes strp-spinner-spin { + 100% { + -moz-transform: rotate(360deg); + } +} +@-webkit-keyframes strp-spinner-spin { + 100% { + -webkit-transform: rotate(360deg); + } +} +@keyframes strp-spinner-spin { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} .strp-spinner-rotate, .strp-spinner-frame { @@ -343,34 +457,62 @@ color: inherit; /* color of the dots, inherited from text on the page */ } - - /* * ===== Skin: strip ===== */ - /* < > */ -.strp-window-skin-strip .strp-nav-button-background { background-color: transparent; } -.strp-window-skin-strip .strp-nav-previous .strp-nav-button-icon { background-image: url('strip-skins/strip/previous.svg'); } -.strp-window-skin-strip .strp-nav-next .strp-nav-button-icon { background-image: url('strip-skins/strip/next.svg'); } +/* < > */ +.strp-window-skin-strip .strp-nav-button-background { + background-color: transparent; +} +.strp-window-skin-strip .strp-nav-previous .strp-nav-button-icon { + background-image: url("strip-skins/strip/previous.svg"); +} +.strp-window-skin-strip .strp-nav-next .strp-nav-button-icon { + background-image: url("strip-skins/strip/next.svg"); +} /* IE7-8/no-svg (using a faded png) */ -.strp-window-skin-strip.strp-no-svg .strp-nav-previous .strp-nav-button-icon { background-image: url('strip-skins/strip/previous-faded.png'); opacity: 1; } -.strp-window-skin-strip.strp-no-svg .strp-nav-next .strp-nav-button-icon { background-image: url('strip-skins/strip/next-faded.png'); opacity: 1; } +.strp-window-skin-strip.strp-no-svg .strp-nav-previous .strp-nav-button-icon { + background-image: url("strip-skins/strip/previous-faded.png"); + opacity: 1; +} +.strp-window-skin-strip.strp-no-svg .strp-nav-next .strp-nav-button-icon { + background-image: url("strip-skins/strip/next-faded.png"); + opacity: 1; +} -.strp-window-skin-strip .strp-nav .strp-nav-button-icon { opacity: .6; } /* normal state */ -.strp-window-skin-strip.strp-mobile-touch .strp-nav .strp-nav-button-icon { opacity: 1; } /* mobile-touch always has normal states at full opacity */ +.strp-window-skin-strip .strp-nav .strp-nav-button-icon { + opacity: 0.6; +} /* normal state */ +.strp-window-skin-strip.strp-mobile-touch .strp-nav .strp-nav-button-icon { + opacity: 1; +} /* mobile-touch always has normal states at full opacity */ /* < > : hover */ .strp-window-skin-strip .strp-nav:hover .strp-nav-button-icon, -.strp-window-skin-strip .strp-nav-hover .strp-nav-button-icon { opacity: 1; } +.strp-window-skin-strip .strp-nav-hover .strp-nav-button-icon { + opacity: 1; +} /* IE7-8/no-svg (unfaded png) */ -.strp-window-skin-strip.strp-no-svg .strp-nav.strp-nav-previous:hover .strp-nav-button-icon, -.strp-window-skin-strip.strp-no-svg .strp-nav-hover.strp-nav-previous .strp-nav-button-icon { background-image: url('strip-skins/strip/previous.png'); } -.strp-window-skin-strip.strp-no-svg .strp-nav.strp-nav-next:hover .strp-nav-button-icon, -.strp-window-skin-strip.strp-no-svg .strp-nav-hover.strp-nav-next .strp-nav-button-icon { background-image: url('strip-skins/strip/next.png'); } +.strp-window-skin-strip.strp-no-svg + .strp-nav.strp-nav-previous:hover + .strp-nav-button-icon, +.strp-window-skin-strip.strp-no-svg + .strp-nav-hover.strp-nav-previous + .strp-nav-button-icon { + background-image: url("strip-skins/strip/previous.png"); +} +.strp-window-skin-strip.strp-no-svg + .strp-nav.strp-nav-next:hover + .strp-nav-button-icon, +.strp-window-skin-strip.strp-no-svg + .strp-nav-hover.strp-nav-next + .strp-nav-button-icon { + background-image: url("strip-skins/strip/next.png"); +} /* Reduce < > button size on narrow screens (iPhone 6 and smaller) */ @media all and (max-width: 375px) and (orientation: portrait), - all and (max-height: 375px) and (max-width: 667px) { + all and (max-height: 375px) and (max-width: 667px) { .strp-window-skin-strip .strp-nav { width: 48px; height: 60px; @@ -379,41 +521,78 @@ } /* < > */ - .strp-window-skin-strip .strp-nav-previous .strp-nav-button-icon { background-image: url('strip-skins/strip/previous-small.svg'); } - .strp-window-skin-strip .strp-nav-next .strp-nav-button-icon { background-image: url('strip-skins/strip/next-small.svg'); } + .strp-window-skin-strip .strp-nav-previous .strp-nav-button-icon { + background-image: url("strip-skins/strip/previous-small.svg"); + } + .strp-window-skin-strip .strp-nav-next .strp-nav-button-icon { + background-image: url("strip-skins/strip/next-small.svg"); + } /* IE7-8/no-svg (using a faded png) */ - .strp-window-skin-strip.strp-no-svg .strp-nav-previous .strp-nav-button-icon { background-image: url('strip-skins/strip/previous-small-faded.png'); } - .strp-window-skin-strip.strp-no-svg .strp-nav-next .strp-nav-button-icon { background-image: url('strip-skins/strip/next-small-faded.png'); } + .strp-window-skin-strip.strp-no-svg .strp-nav-previous .strp-nav-button-icon { + background-image: url("strip-skins/strip/previous-small-faded.png"); + } + .strp-window-skin-strip.strp-no-svg .strp-nav-next .strp-nav-button-icon { + background-image: url("strip-skins/strip/next-small-faded.png"); + } /* IE7-8/no-svg (unfaded png) */ - .strp-window-skin-strip.strp-no-svg .strp-nav.strp-nav-previous:hover .strp-nav-button-icon, - .strp-window-skin-strip.strp-no-svg .strp-nav-hover.strp-nav-previous .strp-nav-button-icon { background-image: url('strip-skins/strip/previous-small.png'); } - .strp-window-skin-strip.strp-no-svg .strp-nav.strp-nav-next:hover .strp-nav-button-icon, - .strp-window-skin-strip.strp-no-svg .strp-nav-hover.strp-nav-next .strp-nav-button-icon { background-image: url('strip-skins/strip/next-small.png'); } + .strp-window-skin-strip.strp-no-svg + .strp-nav.strp-nav-previous:hover + .strp-nav-button-icon, + .strp-window-skin-strip.strp-no-svg + .strp-nav-hover.strp-nav-previous + .strp-nav-button-icon { + background-image: url("strip-skins/strip/previous-small.png"); + } + .strp-window-skin-strip.strp-no-svg + .strp-nav.strp-nav-next:hover + .strp-nav-button-icon, + .strp-window-skin-strip.strp-no-svg + .strp-nav-hover.strp-nav-next + .strp-nav-button-icon { + background-image: url("strip-skins/strip/next-small.png"); + } /* also reduce padding navbutton = 58 = 48 + (2 * 5 margin) closebutton = 48 */ - .strp-no-overlap .strp-container { padding: 48px 58px; } - .strp-no-overlap.strp-no-sides .strp-container { padding: 48px 0; } + .strp-no-overlap .strp-container { + padding: 48px 58px; + } + .strp-no-overlap.strp-no-sides .strp-container { + padding: 48px 0; + } - .strp-vertical .strp-no-overlap .strp-container { padding: 0 58px; } - .strp-vertical .strp-no-overlap.strp-no-sides .strp-container { padding: 0 48px; } + .strp-vertical .strp-no-overlap .strp-container { + padding: 0 58px; + } + .strp-vertical .strp-no-overlap.strp-no-sides .strp-container { + padding: 0 48px; + } } /* X */ -.strp-window-skin-strip .strp-close .strp-close-icon { background-image: url('strip-skins/strip/close.svg'); opacity: .8; } -.strp-window-skin-strip .strp-close:hover .strp-close-icon { opacity: 1; } +.strp-window-skin-strip .strp-close .strp-close-icon { + background-image: url("strip-skins/strip/close.svg"); + opacity: 0.8; +} +.strp-window-skin-strip .strp-close:hover .strp-close-icon { + opacity: 1; +} /* iOS 8.4.1 bug: when opacity changes it'll require 2 taps force a single opacity to fix this */ .strp-window-skin-strip.strp-mobile-touch .strp-close .strp-close-icon, -.strp-window-skin-strip.strp-mobile-touch .strp-close:hover .strp-close-icon { opacity: 1; } +.strp-window-skin-strip.strp-mobile-touch .strp-close:hover .strp-close-icon { + opacity: 1; +} /* IE7-8/no-svg */ -.strp-window-skin-strip.strp-no-svg .strp-close .strp-close-icon { background-image: url('strip-skins/strip/close.png'); opacity: 1; } - +.strp-window-skin-strip.strp-no-svg .strp-close .strp-close-icon { + background-image: url("strip-skins/strip/close.png"); + opacity: 1; +} /* here's how to have content slide in with the window when opening and closing */ /* diff --git a/dist/js/strip.pkgd.js b/dist/js/strip.pkgd.js index cd61c64..f600f48 100644 --- a/dist/js/strip.pkgd.js +++ b/dist/js/strip.pkgd.js @@ -1,13 +1,10 @@ /*! - * Strip - An Unobtrusive Responsive Lightbox - v1.6.4 - * (c) 2014-2016 Nick Stakenburg + * Strip - An Unobtrusive Responsive Lightbox - v1.8.0 + * (c) 2014-2021 Nick Stakenburg * - * http://www.stripjs.com - * - * Licensing: - * - Commercial: http://www.stripjs.com/license - * - Non-commercial: http://creativecommons.org/licenses/by-nc-nd/3.0 + * https://github.com/staaky/strip * + * @license: https://creativecommons.org/licenses/by/4.0 */ // UMD wrapper @@ -25,75 +22,87 @@ }(this, function($) { var Strip = { - version: '1.6.4' + version: "1.8.0", }; Strip.Skins = { // the default skin - 'strip': { } + strip: {}, }; -var Browser = (function(uA) { +var Browser = (function (uA) { function getVersion(identifier) { - var version = new RegExp(identifier + '([\\d.]+)').exec(uA); + var version = new RegExp(identifier + "([\\d.]+)").exec(uA); return version ? parseFloat(version[1]) : true; } return { - IE: !!(window.attachEvent && uA.indexOf('Opera') === -1) && getVersion('MSIE '), - Opera: uA.indexOf('Opera') > -1 && ((!!window.opera && opera.version && parseFloat(opera.version())) || 7.55), - WebKit: uA.indexOf('AppleWebKit/') > -1 && getVersion('AppleWebKit/'), - Gecko: uA.indexOf('Gecko') > -1 && uA.indexOf('KHTML') === -1 && getVersion('rv\:'), + IE: + !!(window.attachEvent && uA.indexOf("Opera") === -1) && + getVersion("MSIE "), + Opera: + uA.indexOf("Opera") > -1 && + ((!!window.opera && opera.version && parseFloat(opera.version())) || + 7.55), + WebKit: uA.indexOf("AppleWebKit/") > -1 && getVersion("AppleWebKit/"), + Gecko: + uA.indexOf("Gecko") > -1 && + uA.indexOf("KHTML") === -1 && + getVersion("rv:"), MobileSafari: !!uA.match(/Apple.*Mobile.*Safari/), - Chrome: uA.indexOf('Chrome') > -1 && getVersion('Chrome/'), - ChromeMobile: uA.indexOf('CrMo') > -1 && getVersion('CrMo/'), - Android: uA.indexOf('Android') > -1 && getVersion('Android '), - IEMobile: uA.indexOf('IEMobile') > -1 && getVersion('IEMobile/') + Chrome: uA.indexOf("Chrome") > -1 && getVersion("Chrome/"), + ChromeMobile: uA.indexOf("CrMo") > -1 && getVersion("CrMo/"), + Android: uA.indexOf("Android") > -1 && getVersion("Android "), + IEMobile: uA.indexOf("IEMobile") > -1 && getVersion("IEMobile/"), }; })(navigator.userAgent); - var _slice = Array.prototype.slice; // Fit var Fit = { - within: function(bounds, dimensions) { - var options = $.extend({ - height: true, - width: true - }, arguments[2] || {}); + within: function (bounds, dimensions) { + var options = $.extend( + { + height: true, + width: true, + }, + arguments[2] || {} + ); - var size = $.extend({}, dimensions), - scale = 1, - attempts = 5; + var size = $.extend({}, dimensions), + scale = 1, + attempts = 5; var fit = { width: options.width, height: options.height }; // adjust the bounds depending on what to fit (width/height) // start - while (attempts > 0 && - ((fit.width && size.width > bounds.width) || - (fit.height && size.height > bounds.height))) { - + while ( + attempts > 0 && + ((fit.width && size.width > bounds.width) || + (fit.height && size.height > bounds.height)) + ) { // if both dimensions fall underneath a minimum, then don't event continue //if (size.width < 100 && size.height < 100) { - var scaleX = 1, scaleY = 1; + var scaleX = 1, + scaleY = 1; - if (fit.width && size.width > bounds.width) { - scaleX = (bounds.width / size.width); - } - if (fit.height && size.height > bounds.height) { - scaleY = (bounds.height / size.height); - } + if (fit.width && size.width > bounds.width) { + scaleX = bounds.width / size.width; + } + if (fit.height && size.height > bounds.height) { + scaleY = bounds.height / size.height; + } - // we'll end up using the largest scaled down factor - var scale = Math.min(scaleX, scaleY); + // we'll end up using the largest scaled down factor + var scale = Math.min(scaleX, scaleY); - // adjust current size, based on original dimensions - size = { - width: Math.round(dimensions.width * scale), - height: Math.round(dimensions.height * scale) - }; + // adjust current size, based on original dimensions + size = { + width: Math.round(dimensions.width * scale), + height: Math.round(dimensions.height * scale), + }; //} attempts--; @@ -104,83 +113,93 @@ var Fit = { size.height = Math.max(size.height, 0); return size; - } + }, }; // we only uses some of the jQueryUI easing functions // add those with a prefix to prevent conflicts $.extend($.easing, { stripEaseInCubic: function (x, t, b, c, d) { - return c*(t/=d)*t*t + b; + return c * (t /= d) * t * t + b; }, stripEaseInSine: function (x, t, b, c, d) { - return -c * Math.cos(t/d * (Math.PI/2)) + c + b; + return -c * Math.cos((t / d) * (Math.PI / 2)) + c + b; }, stripEaseOutSine: function (x, t, b, c, d) { - return c * Math.sin(t/d * (Math.PI/2)) + b; - } + return c * Math.sin((t / d) * (Math.PI / 2)) + b; + }, }); +var Support = (function () { + var testElement = document.createElement("div"), + domPrefixes = "Webkit Moz O ms Khtml".split(" "); -var Support = (function() { - var testElement = document.createElement('div'), - domPrefixes = 'Webkit Moz O ms Khtml'.split(' '); - - function prefixed(property){ - return testAllProperties(property, 'prefix'); - }; + function prefixed(property) { + return testAllProperties(property, "prefix"); + } - function testProperties(properties, prefixed ) { - for ( var i in properties ) { - if (testElement.style[ properties[i] ] !== undefined ) { - return prefixed == 'prefix' ? properties[i] : true; - } - } - return false; + function testProperties(properties, prefixed) { + for (var i in properties) { + if (testElement.style[properties[i]] !== undefined) { + return prefixed == "prefix" ? properties[i] : true; + } + } + return false; } - function testAllProperties(property, prefixed ) { - var ucProperty = property.charAt(0).toUpperCase() + property.substr(1), - properties = (property + ' ' + domPrefixes.join(ucProperty + ' ') + ucProperty).split(' '); + function testAllProperties(property, prefixed) { + var ucProperty = property.charAt(0).toUpperCase() + property.substr(1), + properties = ( + property + + " " + + domPrefixes.join(ucProperty + " ") + + ucProperty + ).split(" "); - return testProperties(properties, prefixed); + return testProperties(properties, prefixed); } // feature detect return { css: { - animation: testAllProperties('animation'), - transform: testAllProperties('transform'), - prefixed: prefixed + animation: testAllProperties("animation"), + transform: testAllProperties("transform"), + prefixed: prefixed, }, - svg: (!!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect), + svg: + !!document.createElementNS && + !!document.createElementNS("http://www.w3.org/2000/svg", "svg") + .createSVGRect, - touch: (function() { + touch: (function () { try { - return !!(('ontouchstart' in window) || - window.DocumentTouch && document instanceof DocumentTouch); // firefox on Android + return !!( + "ontouchstart" in window || + (window.DocumentTouch && document instanceof DocumentTouch) + ); // firefox on Android } catch (e) { return false; } - })() - + })(), }; })(); - // add mobile touch to support -Support.mobileTouch = Support.touch && - (Browser.MobileSafari || Browser.Android || Browser.IEMobile || Browser.ChromeMobile - || !/^(Win|Mac|Linux)/.test(navigator.platform) // otherwise, assume anything not on Windows, Mac or Linux is a mobile device - ); +Support.mobileTouch = + Support.touch && + (Browser.MobileSafari || + Browser.Android || + Browser.IEMobile || + Browser.ChromeMobile || + !/^(Win|Mac|Linux)/.test(navigator.platform)); // otherwise, assume anything not on Windows, Mac or Linux is a mobile device var Bounds = { - viewport: function() { + viewport: function () { var dimensions = { - width: $(window).width() + width: $(window).width(), }; // Mobile Safari has a bugged viewport height after scrolling @@ -194,327 +213,361 @@ var Bounds = { } return dimensions; - } + }, }; /* ImageReady (standalone) - part of VoilĂ  * http://voila.nickstakenburg.com * MIT License */ -var ImageReady = (function($) { +var ImageReady = (function ($) { + var Poll = function () { + return this.initialize.apply(this, Array.prototype.slice.call(arguments)); + }; + $.extend(Poll.prototype, { + initialize: function () { + this.options = $.extend( + { + test: function () {}, + success: function () {}, + timeout: function () {}, + callAt: false, + intervals: [ + [0, 0], + [1 * 1000, 10], + [2 * 1000, 50], + [4 * 1000, 100], + [20 * 1000, 500], + ], + }, + arguments[0] || {} + ); -var Poll = function() { - return this.initialize.apply(this, Array.prototype.slice.call(arguments)); -}; -$.extend(Poll.prototype, { - initialize: function() { - this.options = $.extend({ - test: function() {}, - success: function() {}, - timeout: function() {}, - callAt: false, - intervals: [ - [0, 0], - [1 * 1000, 10], - [2 * 1000, 50], - [4 * 1000, 100], - [20 * 1000, 500] - ] - }, arguments[0] || {}); - - this._test = this.options.test; - this._success = this.options.success; - this._timeout = this.options.timeout; - - this._ipos = 0; - this._time = 0; - this._delay = this.options.intervals[this._ipos][1]; - this._callTimeouts = []; - - this.poll(); - this._createCallsAt(); - }, - - poll: function() { - this._polling = setTimeout($.proxy(function() { - if (this._test()) { - this.success(); - return; - } + this._test = this.options.test; + this._success = this.options.success; + this._timeout = this.options.timeout; - // update time - this._time += this._delay; + this._ipos = 0; + this._time = 0; + this._delay = this.options.intervals[this._ipos][1]; + this._callTimeouts = []; - // next i within the interval - if (this._time >= this.options.intervals[this._ipos][0]) { - // timeout when no next interval - if (!this.options.intervals[this._ipos + 1]) { - if ($.type(this._timeout) == 'function') { - this._timeout(); + this.poll(); + this._createCallsAt(); + }, + + poll: function () { + this._polling = setTimeout( + function () { + if (this._test()) { + this.success(); + return; } - return; - } - this._ipos++; + // update time + this._time += this._delay; + + // next i within the interval + if (this._time >= this.options.intervals[this._ipos][0]) { + // timeout when no next interval + if (!this.options.intervals[this._ipos + 1]) { + if (typeof this._timeout === "function") { + this._timeout(); + } + return; + } - // update to the new bracket - this._delay = this.options.intervals[this._ipos][1]; - } + this._ipos++; - this.poll(); - }, this), this._delay); - }, + // update to the new bracket + this._delay = this.options.intervals[this._ipos][1]; + } - success: function() { - this.abort(); - this._success(); - }, + this.poll(); + }.bind(this), + this._delay + ); + }, - _createCallsAt: function() { - if (!this.options.callAt) return; + success: function () { + this.abort(); + this._success(); + }, - // start a timer for each call - $.each(this.options.callAt, $.proxy(function(i, at) { - var time = at[0], fn = at[1]; + _createCallsAt: function () { + if (!this.options.callAt) return; + + // start a timer for each call + $.each( + this.options.callAt, + function (i, at) { + var time = at[0], + fn = at[1]; + + var timeout = setTimeout( + function () { + fn(); + }.bind(this), + time + ); + + this._callTimeouts.push(timeout); + }.bind(this) + ); + }, - var timeout = setTimeout($.proxy(function() { - fn(); - }, this), time); + _stopCallTimeouts: function () { + $.each(this._callTimeouts, function (i, timeout) { + clearTimeout(timeout); + }); + this._callTimeouts = []; + }, - this._callTimeouts.push(timeout); - }, this)); - }, + abort: function () { + this._stopCallTimeouts(); - _stopCallTimeouts: function() { - $.each(this._callTimeouts, function(i, timeout) { - clearTimeout(timeout); - }); - this._callTimeouts = []; - }, + if (this._polling) { + clearTimeout(this._polling); + this._polling = null; + } + }, + }); - abort: function() { - this._stopCallTimeouts(); + var ImageReady = function () { + return this.initialize.apply(this, Array.prototype.slice.call(arguments)); + }; + $.extend(ImageReady.prototype, { + supports: { + naturalWidth: (function () { + return "naturalWidth" in new Image(); + })(), + }, - if (this._polling) { - clearTimeout(this._polling); - this._polling = null; - } - } -}); + // NOTE: setTimeouts allow callbacks to be attached + initialize: function (img, successCallback, errorCallback) { + this.img = $(img)[0]; + this.successCallback = successCallback; + this.errorCallback = errorCallback; + this.isLoaded = false; + + this.options = $.extend( + { + method: "onload", + pollFallbackAfter: 1000, + }, + arguments[3] || {} + ); + // onload and a fallback for no naturalWidth support (IE6-7) + if (this.options.method == "onload" || !this.supports.naturalWidth) { + this.load(); + return; + } -var ImageReady = function() { - return this.initialize.apply(this, Array.prototype.slice.call(arguments)); -}; -$.extend(ImageReady.prototype, { - supports: { - naturalWidth: (function() { - return ('naturalWidth' in new Image()); - })() - }, - - // NOTE: setTimeouts allow callbacks to be attached - initialize: function(img, successCallback, errorCallback) { - this.img = $(img)[0]; - this.successCallback = successCallback; - this.errorCallback = errorCallback; - this.isLoaded = false; - - this.options = $.extend({ - method: 'onload', - pollFallbackAfter: 1000 - }, arguments[3] || {}); - - // onload and a fallback for no naturalWidth support (IE6-7) - if (this.options.method == 'onload' || !this.supports.naturalWidth) { - this.load(); - return; - } + // start polling + this.poll(); + }, - // start polling - this.poll(); - }, - - // NOTE: Polling for naturalWidth is only reliable if the - // .src never changes. naturalWidth isn't always reset - // to 0 after the src changes (depending on how the spec - // was implemented). The spec even seems to be against - // this, making polling unreliable in those cases. - poll: function() { - this._poll = new Poll({ - test: $.proxy(function() { - return this.img.naturalWidth > 0; - }, this), - - success: $.proxy(function() { - this.success(); - }, this), - - timeout: $.proxy(function() { - // error on timeout - this.error(); - }, this), - - callAt: [ - [this.options.pollFallbackAfter, $.proxy(function() { - this.load(); - }, this)] - ] - }); - }, + // NOTE: Polling for naturalWidth is only reliable if the + // .src never changes. naturalWidth isn't always reset + // to 0 after the src changes (depending on how the spec + // was implemented). The spec even seems to be against + // this, making polling unreliable in those cases. + poll: function () { + this._poll = new Poll({ + test: function () { + return this.img.naturalWidth > 0; + }.bind(this), + + success: function () { + this.success(); + }.bind(this), + + timeout: function () { + // error on timeout + this.error(); + }.bind(this), + + callAt: [ + [ + this.options.pollFallbackAfter, + function () { + this.load(); + }.bind(this), + ], + ], + }); + }, - load: function() { - this._loading = setTimeout($.proxy(function() { - var image = new Image(); - this._onloadImage = image; + load: function () { + this._loading = setTimeout( + function () { + var image = new Image(); + this._onloadImage = image; - image.onload = $.proxy(function() { - image.onload = function() {}; + image.onload = function () { + image.onload = function () {}; - if (!this.supports.naturalWidth) { - this.img.naturalWidth = image.width; - this.img.naturalHeight = image.height; - image.naturalWidth = image.width; - image.naturalHeight = image.height; - } + if (!this.supports.naturalWidth) { + this.img.naturalWidth = image.width; + this.img.naturalHeight = image.height; + image.naturalWidth = image.width; + image.naturalHeight = image.height; + } - this.success(); - }, this); + this.success(); + }.bind(this); - image.onerror = $.proxy(this.error, this); + image.onerror = this.error.bind(this); - image.src = this.img.src; - }, this)); - }, + image.src = this.img.src; + }.bind(this) + ); + }, - success: function() { - if (this._calledSuccess) return; + success: function () { + if (this._calledSuccess) return; - this._calledSuccess = true; + this._calledSuccess = true; - // stop loading/polling - this.abort(); + // stop loading/polling + this.abort(); - // some time to allow layout updates, IE requires this! - this.waitForRender($.proxy(function() { - this.isLoaded = true; - this.successCallback(this); - }, this)); - }, + // some time to allow layout updates, IE requires this! + this.waitForRender( + function () { + this.isLoaded = true; + this.successCallback(this); + }.bind(this) + ); + }, - error: function() { - if (this._calledError) return; + error: function () { + if (this._calledError) return; - this._calledError = true; + this._calledError = true; - // stop loading/polling - this.abort(); + // stop loading/polling + this.abort(); - // don't wait for an actual render on error, just timeout - // to give the browser some time to render a broken image icon - this._errorRenderTimeout = setTimeout($.proxy(function() { - if (this.errorCallback) this.errorCallback(this); - }, this)); - }, + // don't wait for an actual render on error, just timeout + // to give the browser some time to render a broken image icon + this._errorRenderTimeout = setTimeout( + function () { + if (this.errorCallback) this.errorCallback(this); + }.bind(this) + ); + }, - abort: function() { - this.stopLoading(); - this.stopPolling(); - this.stopWaitingForRender(); - }, + abort: function () { + this.stopLoading(); + this.stopPolling(); + this.stopWaitingForRender(); + }, - stopPolling: function() { - if (this._poll) { - this._poll.abort(); - this._poll = null; - } - }, + stopPolling: function () { + if (this._poll) { + this._poll.abort(); + this._poll = null; + } + }, - stopLoading: function() { - if (this._loading) { - clearTimeout(this._loading); - this._loading = null; - } + stopLoading: function () { + if (this._loading) { + clearTimeout(this._loading); + this._loading = null; + } - if (this._onloadImage) { - this._onloadImage.onload = function() { }; - this._onloadImage.onerror = function() { }; - } - }, + if (this._onloadImage) { + this._onloadImage.onload = function () {}; + this._onloadImage.onerror = function () {}; + } + }, - // used by success() only - waitForRender: function(callback) { - this._renderTimeout = setTimeout(callback); - }, + // used by success() only + waitForRender: function (callback) { + this._renderTimeout = setTimeout(callback); + }, - stopWaitingForRender: function() { - if (this._renderTimeout) { - clearTimeout(this._renderTimeout); - this._renderTimeout = null; - } + stopWaitingForRender: function () { + if (this._renderTimeout) { + clearTimeout(this._renderTimeout); + this._renderTimeout = null; + } - if (this._errorRenderTimeout) { - clearTimeout(this._errorRenderTimeout); - this._errorRenderTimeout = null; - } - } -}); + if (this._errorRenderTimeout) { + clearTimeout(this._errorRenderTimeout); + this._errorRenderTimeout = null; + } + }, + }); -return ImageReady; + return ImageReady; })(jQuery); // Spinner // Create pure CSS based spinners -function Spinner() { return this.initialize.apply(this, _slice.call(arguments)); }; +function Spinner() { + return this.initialize.apply(this, _slice.call(arguments)); +} // mark as supported Spinner.supported = Support.css.transform && Support.css.animation; $.extend(Spinner.prototype, { - initialize: function(element) { + initialize: function (element) { this.element = $(element); if (!this.element[0]) return; - this.classPrefix = 'strp-'; + this.classPrefix = "strp-"; this.setOptions(arguments[1] || {}); - this.element.addClass(this.classPrefix + 'spinner'); - this.element.append(this._rotate = $('
').addClass(this.classPrefix + 'spinner-rotate')); + this.element.addClass(this.classPrefix + "spinner"); + this.element.append( + (this._rotate = $("
").addClass(this.classPrefix + "spinner-rotate")) + ); this.build(); this.start(); }, - setOptions: function(options) { - this.options = $.extend({ - show: 200, - hide: 200 - }, options || {}); + setOptions: function (options) { + this.options = $.extend( + { + show: 200, + hide: 200, + }, + options || {} + ); }, - build: function() { + build: function () { if (this._build) return; - this._rotate.html(''); + this._rotate.html(""); var d = (this.options.length + this.options.radius) * 2, - dimensions = { height: d, width: d }; + dimensions = { height: d, width: d }; // we parse stuff below so make sure that happens with a visible spinner - var is_vis = this.element.is(':visible'); + var is_vis = this.element.is(":visible"); if (!is_vis) this.element.show(); // find the amount of lines var frame, line; - this._rotate.append(frame = $('
').addClass(this.classPrefix + 'spinner-frame') - .append(line = $('
').addClass(this.classPrefix + 'spinner-line')) + this._rotate.append( + (frame = $("
") + .addClass(this.classPrefix + "spinner-frame") + .append( + (line = $("
").addClass(this.classPrefix + "spinner-line")) + )) ); - var lines = parseInt($(line).css('z-index')); + var lines = parseInt($(line).css("z-index")); this.lines = lines; // now reset that z-index - line.css({ 'z-index': 'inherit' }); + line.css({ "z-index": "inherit" }); frame.remove(); @@ -523,72 +576,83 @@ $.extend(Spinner.prototype, { // insert frames var color; - for (var i = 0;i').addClass(this.classPrefix + 'spinner-frame') - .append(line = $('
').addClass(this.classPrefix + 'spinner-line')) + this._rotate.append( + (frame = $("
") + .addClass(this.classPrefix + "spinner-frame") + .append( + (line = $("
").addClass(this.classPrefix + "spinner-line")) + )) ); - color = color || line.css('color'); + color = color || line.css("color"); line.css({ background: color }); - frame.css({ opacity: ((1 / lines) * (i+1)).toFixed(2) }); + frame.css({ opacity: ((1 / lines) * (i + 1)).toFixed(2) }); var transformCSS = {}; - transformCSS[Support.css.prefixed('transform')] = 'rotate(' + ((360 / lines) * (i + 1)) + 'deg)'; + transformCSS[Support.css.prefixed("transform")] = + "rotate(" + (360 / lines) * (i + 1) + "deg)"; frame.css(transformCSS); } this._build = true; }, - start: function() { + start: function () { var rotateCSS = {}; - rotateCSS[Support.css.prefixed('animation')] = this.classPrefix + 'spinner-spin 1s infinite steps(' + this.lines + ')'; + rotateCSS[Support.css.prefixed("animation")] = + this.classPrefix + "spinner-spin 1s infinite steps(" + this.lines + ")"; this._rotate.css(rotateCSS); }, - stop: function() { + stop: function () { var rotateCSS = {}; - rotateCSS[Support.css.prefixed('animation')] = 'none'; + rotateCSS[Support.css.prefixed("animation")] = "none"; this._rotate.css(rotateCSS); }, - show: function(callback) { + show: function (callback) { this.build(); this.start(); - this.element.stop(true).fadeTo(this.options.show, 1, callback);//deferred.resolve); + this.element.stop(true).fadeTo(this.options.show, 1, callback); //deferred.resolve); }, - hide: function(callback) { - this.element.stop(true).fadeOut(this.options.hide, $.proxy(function() { - this.stop(); - if (callback) callback(); - }, this)); + hide: function (callback) { + this.element.stop(true).fadeOut( + this.options.hide, + function () { + this.stop(); + if (callback) callback(); + }.bind(this) + ); }, - refresh: function() { + refresh: function () { this._build = false; this.build(); - } + }, }); -function Timers() { return this.initialize.apply(this, _slice.call(arguments)); }; +function Timers() { + return this.initialize.apply(this, _slice.call(arguments)); +} $.extend(Timers.prototype, { - initialize: function() { + initialize: function () { this._timers = {}; }, - set: function(name, handler, ms) { + set: function (name, handler, ms) { this._timers[name] = setTimeout(handler, ms); }, - get: function(name) { + get: function (name) { return this._timers[name]; }, - clear: function(name) { + clear: function (name) { if (name) { if (this._timers[name]) { clearTimeout(this._timers[name]); @@ -599,18 +663,18 @@ $.extend(Timers.prototype, { } }, - clearAll: function() { - $.each(this._timers, function(i, timer) { + clearAll: function () { + $.each(this._timers, function (_i, timer) { clearTimeout(timer); }); this._timers = {}; - } + }, }); // uses Types to scan a URI for info function getURIData(url) { - var result = { type: 'image' }; - $.each(Types, function(i, type) { + var result = { type: "image" }; + $.each(Types, function (i, type) { var data = type.data(url); if (data) { result = data; @@ -623,137 +687,151 @@ function getURIData(url) { } function detectExtension(url) { - var ext = (url || '').replace(/\?.*/g, '').match(/\.([^.]{3,4})$/); + var ext = (url || "").replace(/\?.*/g, "").match(/\.([^.]{3,4})$/); return ext ? ext[1].toLowerCase() : null; } - var Types = { - 'image': { - extensions: 'bmp gif jpeg jpg png webp', - detect: function(url) { - return $.inArray(detectExtension(url), this.extensions.split(' ')) > -1; + image: { + extensions: "bmp gif jpeg jpg png webp", + detect: function (url) { + return $.inArray(detectExtension(url), this.extensions.split(" ")) > -1; }, - data: function(url) { + data: function (url) { if (!this.detect()) return false; return { - extension: detectExtension(url) + extension: detectExtension(url), }; - } + }, }, - 'youtube': { - detect: function(url) { - var res = /(youtube\.com|youtu\.be)\/watch\?(?=.*vi?=([a-zA-Z0-9-_]+))(?:\S+)?$/.exec(url); + youtube: { + detect: function (url) { + var res = + /(youtube\.com|youtu\.be)\/watch\?(?=.*vi?=([a-zA-Z0-9-_]+))(?:\S+)?$/.exec( + url + ); if (res && res[2]) return res[2]; - res = /(youtube\.com|youtu\.be)\/(vi?\/|u\/|embed\/)?([a-zA-Z0-9-_]+)(?:\S+)?$/i.exec(url); + res = + /(youtube\.com|youtu\.be)\/(vi?\/|u\/|embed\/)?([a-zA-Z0-9-_]+)(?:\S+)?$/i.exec( + url + ); if (res && res[3]) return res[3]; return false; }, - data: function(url) { + data: function (url) { var id = this.detect(url); if (!id) return false; return { - id: id + id: id, }; - } + }, }, - 'vimeo': { - detect: function(url) { + vimeo: { + detect: function (url) { var res = /(vimeo\.com)\/([a-zA-Z0-9-_]+)(?:\S+)?$/i.exec(url); if (res && res[2]) return res[2]; return false; }, - data: function(url) { + data: function (url) { var id = this.detect(url); if (!id) return false; return { - id: id + id: id, }; - } - } + }, + }, }; +var VimeoReady = (function () { + var VimeoReady = function () { + return this.initialize.apply(this, _slice.call(arguments)); + }; + $.extend(VimeoReady.prototype, { + initialize: function (url, callback) { + this.url = url; + this.callback = callback; -var VimeoReady = (function() { - -var VimeoReady = function() { return this.initialize.apply(this, _slice.call(arguments)); }; -$.extend(VimeoReady.prototype, { - initialize: function(url, callback) { - this.url = url; - this.callback = callback; - - this.load(); - }, + this.load(); + }, - load: function() { - // first try the cache - var cache = Cache.get(this.url); + load: function () { + // first try the cache + var cache = Cache.get(this.url); - if (cache) { - return this.callback(cache.data); - } + if (cache) { + return this.callback(cache.data); + } - var protocol = 'http' + (window.location && window.location.protocol == 'https:' ? 's' : '') + ':', + var protocol = + "http" + + (window.location && window.location.protocol == "https:" ? "s" : "") + + ":", video_id = getURIData(this.url).id; - this._xhr = $.getJSON(protocol + '//vimeo.com/api/oembed.json?url=' + protocol + '//vimeo.com/' + video_id + '&maxwidth=9999999&maxheight=9999999&callback=?', $.proxy(function(_data) { - var data = { - dimensions: { - width: _data.width, - height: _data.height - } - }; - - Cache.set(this.url, data); + this._xhr = $.getJSON( + protocol + + "//vimeo.com/api/oembed.json?url=" + + protocol + + "//vimeo.com/" + + video_id + + "&maxwidth=9999999&maxheight=9999999&callback=?", + function (_data) { + var data = { + dimensions: { + width: _data.width, + height: _data.height, + }, + }; - if (this.callback) this.callback(data); - }, this)); - }, - - abort: function() { - if (this._xhr) { - this._xhr.abort(); - this._xhr = null; - } - } -}); + Cache.set(this.url, data); + if (this.callback) this.callback(data); + }.bind(this) + ); + }, -var Cache = { - cache: [], + abort: function () { + if (this._xhr) { + this._xhr.abort(); + this._xhr = null; + } + }, + }); - get: function(url) { - var entry = null; - for(var i=0;i element - if ($.type(object) == 'string') { - // turn the string into an element - object = { url: object }; - } - - // element -> object - else if (object && object.nodeType == 1) { - var element = $(object); - - object = { - element: element[0], - url: element.attr('href'), - caption: element.data('strip-caption'), - group: element.data('strip-group'), - extension: element.data('strip-extension'), - type: element.data('strip-type'), - options: (element.data('strip-options') && eval('({' + element.data('strip-options') + '})')) || {} - }; - } - - if (object) { - // detect type if none is set - if (!object.extension) { - object.extension = detectExtension(object.url); - } - - if (!object.type) { - var data = getURIData(object.url); - object._data = data; - object.type = data.type; - } - } - - if (!object._data) { - object._data = getURIData(object.url); - } - - if (object && object.options) { - object.options = $.extend(true, $.extend({}, options), $.extend({}, object.options)); - } else { - object.options = $.extend({}, options); - } - // extend the options - object.options = Options.create(object.options, object.type, object._data); - - // extend this with data - $.extend(this, object); - - return this; - } + initialize: function (object) { + var options = arguments[1] || {}, + data = {}; + + // string -> element + if (typeof object === "string") { + // turn the string into an element + object = { url: object }; + } + + // element -> object + else if (object && object.nodeType === 1) { + var element = $(object); + + object = { + element: element[0], + url: element.attr("href"), + caption: element.attr("data-strip-caption"), + group: element.attr("data-strip-group"), + extension: element.attr("data-strip-extension"), + type: element.attr("data-strip-type"), + options: + (element.attr("data-strip-options") && + eval("({" + element.attr("data-strip-options") + "})")) || + {}, + }; + } + + if (object) { + // detect type if none is set + if (!object.extension) { + object.extension = detectExtension(object.url); + } + + if (!object.type) { + var data = getURIData(object.url); + object._data = data; + object.type = data.type; + } + } + + if (!object._data) { + object._data = getURIData(object.url); + } + + if (object && object.options) { + object.options = $.extend( + true, + $.extend({}, options), + $.extend({}, object.options) + ); + } else { + object.options = $.extend({}, options); + } + // extend the options + object.options = Options.create(object.options, object.type, object._data); + + // extend this with data + $.extend(this, object); + + return this; + }, }); var Pages = { - initialize: function(element) { + initialize: function (element) { this.element = element; this.pages = {}; this.uid = 1; }, - add: function(views) { + add: function (views) { this.uid++; this.views = views; @@ -952,12 +1047,15 @@ var Pages = { Window._showUIOnResize = true; // add pages for all these views - $.each(views, $.proxy(function(i, view) { - this.pages[this.uid].push(new Page(view, i + 1, this.views.length)); - }, this)); + $.each( + views, + function (i, view) { + this.pages[this.uid].push(new Page(view, i + 1, this.views.length)); + }.bind(this) + ); }, - show: function(position, callback) { + show: function (position, callback) { var page = this.pages[this.uid][position - 1]; // never try to reload the exact same frame @@ -980,18 +1078,20 @@ var Pages = { this.page = page; this.removeHiddenAndLoadingInactive(); - page.show($.proxy(function() { - // once a page has been fully shown we mark Pages as not being switched anymore - this._switched = false; - if (callback) callback(); - }, this)); + page.show( + function () { + // once a page has been fully shown we mark Pages as not being switched anymore + this._switched = false; + if (callback) callback(); + }.bind(this) + ); }, - getLoadingCount: function() { + getLoadingCount: function () { // we only stop loading if all the frames we have are not loading anymore var count = 0; - $.each(this.pages, function(id, pages) { - $.each(pages, function(j, page) { + $.each(this.pages, function (_id, pages) { + $.each(pages, function (_j, page) { if (page.loading) count++; }); }); @@ -1000,37 +1100,36 @@ var Pages = { // used by the API when opening // checks if the page is in the currently open group - getPositionInActivePageGroup: function(element) { + getPositionInActivePageGroup: function (element) { var position = 0, - activeGroup = this.pages[this.uid]; + activeGroup = this.pages[this.uid]; if (activeGroup) { - $.each(activeGroup, function(i, page) { + $.each(activeGroup, function (i, page) { if (page.view.element && page.view.element == element) { position = i + 1; } }); } - return position + return position; }, // remove pages not matching the current id - removeExpired: function(instantly) { - $.each(this.pages, function(id, pages) { + removeExpired: function (instantly) { + $.each(this.pages, function (id, pages) { if (id != this._id) { - $.each(pages, function(j, page) { + $.each(pages, function (_j, page) { page.remove(instantly); }); } }); }, - // Window.hide will call this when fully closed - removeAll: function() { - $.each(this.pages, function(id, pages) { - $.each(pages, function(j, page) { + removeAll: function () { + $.each(this.pages, function (_id, pages) { + $.each(pages, function (_j, page) { page.remove(); }); }); @@ -1039,783 +1138,892 @@ var Pages = { this.pages = {}; }, - hideVisibleInactive: function(alternateDuration) { - $.each(this.pages, $.proxy(function(id, pages) { - $.each(pages, $.proxy(function(j, page) { - if (page.uid != this.page.uid) { - page.hide(null, alternateDuration); - } - }, this)); - }, this)); + hideVisibleInactive: function (alternateDuration) { + $.each( + this.pages, + function (_id, pages) { + $.each( + pages, + function (_j, page) { + if (page.uid != this.page.uid) { + page.hide(null, alternateDuration); + } + }.bind(this) + ); + }.bind(this) + ); }, - stopInactive: function() { - $.each(this.pages, $.proxy(function(id, pages) { - $.each(pages, $.proxy(function(j, page) { - if (page.uid != this.page.uid && !page.preloading) { - page.stop(); - } - }, this)); - }, this)); + stopInactive: function () { + $.each( + this.pages, + function (_id, pages) { + $.each( + pages, + function (_j, page) { + if (page.uid != this.page.uid && !page.preloading) { + page.stop(); + } + }.bind(this) + ); + }.bind(this) + ); }, // TODO: might be nice to have a hide animation before removal, it's instant now - removeHiddenAndLoadingInactive: function() { + removeHiddenAndLoadingInactive: function () { // track which inactive page groups are empty var empty = []; - $.each(this.pages, $.proxy(function(uid, pages) { - // only remove pages in the groups that are currently not active - if (uid != this.uid) { - var removed = 0; - - $.each(pages, $.proxy(function(j, page) { - // remove hidden or loading, but dont'remove frames in animation - if ((!page.visible || page.loading) && !page.animatingWindow) { - page.remove(); - } - - if (page.removed) removed++; // count all, not those we remove now - }, this)); - - // if we've removed all pages from this group it's safe to remove it - // we don't do this in the loop but below - if (removed == pages.length) { - empty.push(uid); + $.each( + this.pages, + function (uid, pages) { + // only remove pages in the groups that are currently not active + if (uid != this.uid) { + var removed = 0; + + $.each( + pages, + function (_j, page) { + // remove hidden or loading, but dont'remove frames in animation + if ((!page.visible || page.loading) && !page.animatingWindow) { + page.remove(); + } + + if (page.removed) removed++; // count all, not those we remove now + }.bind(this) + ); + + // if we've removed all pages from this group it's safe to remove it + // we don't do this in the loop but below + if (removed == pages.length) { + empty.push(uid); + } } - } - }, this)); + }.bind(this) + ); // now remove all empty page groups - $.each(empty, $.proxy(function(i, uid) { - delete this.pages[uid]; - }, this)); - + $.each( + empty, + function (_i, uid) { + delete this.pages[uid]; + }.bind(this) + ); }, - stop: function() { - $.each(this.pages, function(id, pages) { - $.each(pages, function(j, page) { + stop: function () { + $.each(this.pages, function (id, pages) { + $.each(pages, function (_j, page) { page.stop(); }); }); }, - setActiveClass: function(page) { + setActiveClass: function (page) { // switch the active element class this.removeActiveClasses(); // add the active class if the new page is bound to an element var element = page.view.element; if (element) { - $(element).addClass('strip-active-element strip-active-group'); + $(element).addClass("strip-active-element strip-active-group"); // also give other items in the group the active group class - var group = $(element).data('strip-group'); + var group = $(element).attr("data-strip-group"); if (group) { - $('.strip[data-strip-group="' + group + '"]').addClass('strip-active-group'); + $('.strip[data-strip-group="' + group + '"]').addClass( + "strip-active-group" + ); } } }, - removeActiveClasses: function() { - $('.strip-active-group').removeClass('strip-active-group strip-active-element'); - } + removeActiveClasses: function () { + $(".strip-active-group").removeClass( + "strip-active-group strip-active-element" + ); + }, }; -var Page = (function() { -var uid = 0, +var Page = (function () { + var uid = 0, loadedUrlCache = {}; -function Page() { return this.initialize.apply(this, _slice.call(arguments)); }; -$.extend(Page.prototype, { - initialize: function(view, position, total) { - this.view = view; - this.dimensions = { width: 0, height: 0 }; - this.uid = uid++; + function Page() { + return this.initialize.apply(this, _slice.call(arguments)); + } + $.extend(Page.prototype, { + initialize: function (view, position, total) { + this.view = view; + this.dimensions = { width: 0, height: 0 }; + this.uid = uid++; - // store position/total views for later use - this._position = position; - this._total = total; + // store position/total views for later use + this._position = position; + this._total = total; - this.animated = false; - this.visible = false; + this.animated = false; + this.visible = false; - this.queues = {}; - this.queues.showhide = $({}); - }, + this.queues = {}; + this.queues.showhide = $({}); + }, - // create the page, this doesn't mean it's loaded - // should happen instantly - create: function() { - if (this._created) return; + // create the page, this doesn't mean it's loaded + // should happen instantly + create: function () { + if (this._created) return; + + Pages.element.append( + (this.element = $("
") + .addClass("strp-page") + .append((this.container = $("
").addClass("strp-container"))) + .css({ opacity: 0 }) + .hide()) + ); - Pages.element.append(this.element = $('
').addClass('strp-page') - .append(this.container = $('
').addClass('strp-container')) - .css({ opacity: 0 }) - .hide() - ); + var hasPosition = this.view.options.position && this._total > 1; + if (this.view.caption || hasPosition) { + this.element.append( + (this.info = $("
") + .addClass("strp-info") + .append( + (this.info_padder = $("
").addClass("strp-info-padder")) + )) + ); - var hasPosition = (this.view.options.position && this._total > 1); - if (this.view.caption || hasPosition) { - this.element.append(this.info = $('
').addClass('strp-info') - .append(this.info_padder = $('
').addClass('strp-info-padder')) - ); + // insert caption first because it floats right + if (hasPosition) { + this.element.addClass("strp-has-position"); - // insert caption first because it floats right - if (hasPosition) { - this.element.addClass('strp-has-position'); + this.info_padder.append( + $("
") + .addClass("strp-position") + .html(this._position + " / " + this._total) + ); + } - this.info_padder.append($('
').addClass('strp-position') - .html(this._position + ' / ' + this._total) - ); + if (this.view.caption) { + this.info_padder.append( + (this.caption = $("
") + .addClass("strp-caption") + .html(this.view.caption)) + ); + } } - if (this.view.caption) { - this.info_padder.append(this.caption = $('
').addClass('strp-caption') - .html(this.view.caption) - ); + switch (this.view.type) { + case "image": + this.container.append( + (this.content = $("").attr({ src: this.view.url })) + ); + break; + + case "vimeo": + case "youtube": + this.container.append((this.content = $("
"))); + break; } - } - switch (this.view.type) { - case 'image': - this.container.append(this.content = $('') - .attr({ src: this.view.url }) - ); - break; - - case 'vimeo': - case 'youtube': - this.container.append(this.content = $('
')); - break; - } - - // ui - this.element.addClass('strp' + (this.view.options.overlap ? '' : '-no') + '-overlap'); + // ui + this.element.addClass( + "strp" + (this.view.options.overlap ? "" : "-no") + "-overlap" + ); - // no sides - if (this._total < 2) { - this.element.addClass('strp-no-sides'); - } + // no sides + if (this._total < 2) { + this.element.addClass("strp-no-sides"); + } - this.content.addClass('strp-content-element'); + this.content.addClass("strp-content-element"); - this._created = true; - }, + this._created = true; + }, - // surrounding - _getSurroundingPages: function() { - var preload; - if (!(preload = this.view.options.preload)) return []; + // surrounding + _getSurroundingPages: function () { + var preload; + if (!(preload = this.view.options.preload)) return []; - var pages = [], + var pages = [], begin = Math.max(1, this._position - preload[0]), end = Math.min(this._position + preload[1], this._total), pos = this._position; - // add the pages after this one first for the preloading order - for (var i = pos;i<=end;i++) { - var page = Pages.pages[Pages.uid][i-1]; - if (page._position != pos) pages.push(page); - } - - for (var i = pos;i>=begin;i--) { - var page = Pages.pages[Pages.uid][i-1]; - if (page._position != pos) pages.push(page); - } - - return pages; - }, - - preloadSurroundingImages: function() { - var pages = this._getSurroundingPages(); - - $.each(pages, $.proxy(function(i, page) { - page.preload(); - }, this)); - }, - - // preload is a non-abortable preloader, - // so that it doesn't interfere with our regular load - preload: function() { - if (this.preloading || this.preloaded - || this.view.type != 'image' - || !this.view.options.preload - || this.loaded // page might be loaded before it's preloaded so also stop there - ) { - return; - } - - // make sure the page is created - this.create(); - - this.preloading = true; - - new ImageReady(this.content[0], $.proxy(function(imageReady) { - this.loaded = true; - this.preloading = false; - this.preloaded = true; - - this.dimensions = { - width: imageReady.img.naturalWidth, - height: imageReady.img.naturalHeight - }; - }, this), null, { method: 'naturalWidth' }); - }, + // add the pages after this one first for the preloading order + for (var i = pos; i <= end; i++) { + var page = Pages.pages[Pages.uid][i - 1]; + if (page._position != pos) pages.push(page); + } - // the purpose of load is to set dimensions - // we use it to set dimensions even for content that doesn't load like youtube - load: function(callback, isPreload) { - // make sure the page is created - this.create(); + for (var i = pos; i >= begin; i--) { + var page = Pages.pages[Pages.uid][i - 1]; + if (page._position != pos) pages.push(page); + } - // exit early if already loaded - if (this.loaded) { - if (callback) callback(); - return; - } + return pages; + }, - // abort possible previous (pre)load - this.abort(); + preloadSurroundingImages: function () { + var pages = this._getSurroundingPages(); - // loading indicator, we don't show it when preloading frames - this.loading = true; + $.each( + pages, + function (_i, page) { + page.preload(); + }.bind(this) + ); + }, - // start spinner - // only when this url hasn't been loaded before - if (this.view.options.spinner && !loadedUrlCache[this.view.url]) { - Window.startLoading(); - } + // preload is a non-abortable preloader, + // so that it doesn't interfere with our regular load + preload: function () { + if ( + this.preloading || + this.preloaded || + this.view.type !== "image" || + !this.view.options.preload || + this.loaded // page might be loaded before it's preloaded so also stop there + ) { + return; + } - switch(this.view.type) { - case 'image': + // make sure the page is created + this.create(); - // if we had an error before just go through - if (this.error) { - if (callback) callback(); - return; - } + this.preloading = true; - this.imageReady = new ImageReady(this.content[0], $.proxy(function(imageReady) { - // mark as loaded - this._markAsLoaded(); + new ImageReady( + this.content[0], + function (imageReady) { + this.loaded = true; + this.preloading = false; + this.preloaded = true; this.dimensions = { width: imageReady.img.naturalWidth, - height: imageReady.img.naturalHeight + height: imageReady.img.naturalHeight, }; + }.bind(this), + null, + { method: "naturalWidth" } + ); + }, - if (callback) callback(); - }, this), $.proxy(function() { - // mark as loaded - this._markAsLoaded(); + // the purpose of load is to set dimensions + // we use it to set dimensions even for content that doesn't load like youtube + load: function (callback, isPreload) { + // make sure the page is created + this.create(); - this.content.hide(); - this.container.append(this.error = $('
').addClass('strp-error')); - this.element.addClass('strp-has-error'); + // exit early if already loaded + if (this.loaded) { + if (callback) callback(); + return; + } - this.dimensions = { - width: this.error.outerWidth(), - height: this.error.outerHeight() - }; + // abort possible previous (pre)load + this.abort(); - if (callback) callback(); - }, this), { method: 'naturalWidth' }); + // loading indicator, we don't show it when preloading frames + this.loading = true; - break; + // start spinner + // only when this url hasn't been loaded before + if (this.view.options.spinner && !loadedUrlCache[this.view.url]) { + Window.startLoading(); + } - case 'vimeo': + switch (this.view.type) { + case "image": + // if we had an error before just go through + if (this.error) { + if (callback) callback(); + return; + } - this.vimeoReady = new VimeoReady(this.view.url, $.proxy(function(data) { + this.imageReady = new ImageReady( + this.content[0], + function (imageReady) { + // mark as loaded + this._markAsLoaded(); + + this.dimensions = { + width: imageReady.img.naturalWidth, + height: imageReady.img.naturalHeight, + }; + + if (callback) callback(); + }.bind(this), + function () { + // mark as loaded + this._markAsLoaded(); + + this.content.hide(); + this.container.append( + (this.error = $("
").addClass("strp-error")) + ); + this.element.addClass("strp-has-error"); + + this.dimensions = { + width: this.error.outerWidth(), + height: this.error.outerHeight(), + }; + + if (callback) callback(); + }.bind(this), + { method: "naturalWidth" } + ); + + break; + + case "vimeo": + this.vimeoReady = new VimeoReady( + this.view.url, + function (data) { + // mark as loaded + this._markAsLoaded(); + + this.dimensions = { + width: data.dimensions.width, + height: data.dimensions.height, + }; + + if (callback) callback(); + }.bind(this) + ); + + break; + + case "youtube": // mark as loaded this._markAsLoaded(); this.dimensions = { - width: data.dimensions.width, - height: data.dimensions.height + width: this.view.options.width, + height: this.view.options.height, }; if (callback) callback(); - }, this)); - - break; - - case 'youtube': - // mark as loaded - this._markAsLoaded(); - - this.dimensions = { - width: this.view.options.width, - height: this.view.options.height - }; - - if (callback) callback(); - break; - } - }, + break; + } + }, - // helper for load() - _markAsLoaded: function() { - this.loading = false; - this.loaded = true; + // helper for load() + _markAsLoaded: function () { + this.loading = false; + this.loaded = true; - // mark url as loaded so we can avoid - // showing the spinner again - loadedUrlCache[this.view.url] = true; + // mark url as loaded so we can avoid + // showing the spinner again + loadedUrlCache[this.view.url] = true; - Window.stopLoading(); - }, + Window.stopLoading(); + }, - isVideo: function() { - return /^(youtube|vimeo)$/.test(this.view.type); - }, + isVideo: function () { + return /^(youtube|vimeo)$/.test(this.view.type); + }, - insertVideo: function(callback) { - // don't insert a video twice - // and stop if not a video - if (this.playerIframe || !this.isVideo()) { - if (callback) callback(); - return; - } + insertVideo: function (callback) { + // don't insert a video twice + // and stop if not a video + if (this.playerIframe || !this.isVideo()) { + if (callback) callback(); + return; + } - var protocol = 'http' + (window.location && window.location.protocol == 'https:' ? 's' : '') + ':', + var protocol = + "http" + + (window.location && window.location.protocol === "https:" + ? "s" + : "") + + ":", playerVars = $.extend({}, this.view.options[this.view.type] || {}), queryString = $.param(playerVars), urls = { - vimeo: protocol + '//player.vimeo.com/video/{id}?{queryString}', - youtube: protocol + '//www.youtube.com/embed/{id}?{queryString}' + vimeo: protocol + "//player.vimeo.com/video/{id}?{queryString}", + youtube: protocol + "//www.youtube.com/embed/{id}?{queryString}", }, src = urls[this.view.type] - .replace('{id}', this.view._data.id) - .replace('{queryString}', queryString); - - this.content.append(this.playerIframe = $('