Commit 1b525fd9 by Manzar Hussain

libraries for slideshow

parent 8dce5882
The MIT License (MIT)
Copyright (c) 2013-16 Bjørn Klinggaard
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
#hey, be lazy
[![Downloads](https://img.shields.io/npm/dm/blazy.svg?style=flat)](https://www.npmjs.com/package/blazy)
[![Latest Stable Version](https://img.shields.io/npm/v/blazy.svg?style=flat)](https://www.npmjs.com/package/blazy)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/dinbror/blazy/blob/master/LICENSE)
bLazy is a lightweight script for lazy loading and multi-serving images, iframes, videos and more (less than 1.4KB minified and gzipped). It’s written in pure JavaScript why it doesn’t depend on 3rd-party libraries such as jQuery. It lets you lazy load and multi-serve your images so you can save bandwidth and server requests. The user will have faster load times and save data usage if he/she doesn't browse the whole page.
**Table of Contents**<br>
1. [Demo](https://github.com/dinbror/blazy#demo)<br>
2. [Usage & API](https://github.com/dinbror/blazy#usage--api)<br>
3. [Why be lazy?](https://github.com/dinbror/blazy#why-be-lazy)<br>
4. [Changelog](https://github.com/dinbror/blazy#changelog)<br>
5. [License](https://github.com/dinbror/blazy#license)<br>
## DEMO ##
[http://dinbror.dk/blazy/](http://dinbror.dk/blazy/?ref=github)
More examples:
[http://dinbror.dk/blazy/examples/](http://dinbror.dk/blazy/examples/?ref=github)
Codepen playground:
http://codepen.io/dinbror/pen/HzCAJ
## USAGE & API ##
[http://dinbror.dk/blog/blazy/](http://dinbror.dk/blog/blazy/?ref=github)
### INSTALL
You can install blazy.js with npm:
``` npm
npm install blazy --save
```
or bower:
``` bower
bower install blazy --save
```
### CDN
If you don't want to host the script yourself you can link to the latest minified file:
`//cdn.jsdelivr.net/blazy/latest/blazy.min.js` on [jsDelivr](http://www.jsdelivr.com/#!blazy).
Exchange `latest` with the specific version number if you want to lock it in.
## WHY BE LAZY? ##
* bLazy is used on big sites with millions of monthly visitors so it has been tested out in the real world.
* bLazy is written in pure JavaScript why it doesn’t depend on 3rd-party libraries such as jQuery.
* bLazy is lightweight, less than 1.4KB and less than 1.25KB if you don't need IE7- support.
* bLazy is very fast. It has focus on performance why it also auto-destroys when it's done lazy loading.
* bLazy can lazy load all types of images including background images.
* bLazy is future-proof. It supports srcset and the picture element.
* bLazy can serve retina images on retina devices.
* bLazy can lazy load everything with a src like iframes, HTML5 videos, scripts, unity games etc.
* bLazy supports all browsers used today including legacy browsers like IE7 and 8.
* bLazy supports all main module formats like AMD, CommonJS and globals.
## WISHLIST/NEW FEATURES REQUESTED BY YOU
* Only preload "first frame" of progressive jpegs.
* Add support for CSS background property; [image-set](https://cloudfour.com/examples/image-set/) ([caniuse](http://caniuse.com/#feat=css-image-set)).
* Add a class when the lazyloading begins.
* Option to keen load once on screen images have loaded.
* Add option to disable success/error classes
* Animate the container that contains the image you lazy load. You can do that today by adding/removing a class in the success callback.
## CHANGELOG
### v 1.8.2 (2016/10/25) ###
* Added null check in public `load` function.
* Bugfix: Fixed `this` issue defaulting to window when passing `revalidate` or `destroy` in setTimeout as reference [#73](https://github.com/dinbror/blazy/issues/73) and [#112](https://github.com/dinbror/blazy/pull/112). Thanks [PeteDuncanson](https://github.com/PeteDuncanson).
* Bugfix: If parts of container is outside window use the viewport boundaries [#113](https://github.com/dinbror/blazy/issues/113) and [#114](https://github.com/dinbror/blazy/pull/114). Thanks [dbirkbeck](https://github.com/dbirkbeck).
### v 1.8.1 (2016/10/22) ###
* Bugfix: Created polyfill and check for support of `Element.closest` which was introduced in the container fix in v. 1.8.0.
### v 1.8.0 (2016/10/16) ###
* Bugfix: Non-visible images being loaded inside container [#23](https://github.com/dinbror/blazy/issues/23) and [#96](https://github.com/dinbror/blazy/issues/96).
### v 1.7.1 (2016/10/14) ###
* Bugfix: In safari the picture element always loaded the default/fallback image [#92](https://github.com/dinbror/blazy/issues/92).
### v 1.7.0 (2016/10/10) ###
* Bugfix: When lazyloading picture elements it also loaded the fallback/regular image [#92](https://github.com/dinbror/blazy/issues/92) and [108](https://github.com/dinbror/blazy/pull/108). Thanks [@idoshamun](https://github.com/idoshamun)
* Refactored loadElement function to avoid redundancy.
### v 1.6.4 (2016/10/08) ###
* Bugfix: When lazyloading srcset images it also loaded the fallback/regular image [#99](https://github.com/dinbror/blazy/pull/99). Thanks [@m0uH](https://github.com/m0uH)
### v 1.6.3 (2016/09/30) ###
* Changed event listener to passive listener [#106](https://github.com/dinbror/blazy/pull/106). Thanks [@idoshamun](https://github.com/idoshamun)
* Added support for web components (shadow dom) [#107](https://github.com/dinbror/blazy/pull/107). Thanks again [@idoshamun](https://github.com/idoshamun)
### v 1.6.2 (2016/05/09) ###
* Fixed bug introduced in v.1.6.0, not using retina/breakpoint src [#90](https://github.com/dinbror/blazy/issues/90).
### v 1.6.1 (2016/05/02) ###
* Implemented a workaround for onload/onerror bug introduced in chrome v50, [LINK](https://productforums.google.com/forum/#!topic/chrome/p51Lk7vnP2o). Fixed [#85](https://github.com/dinbror/blazy/issues/85).
### v 1.6.0 (2016/04/30) ###
* Added support for srcset and the picture element. Fixed [#69](https://github.com/dinbror/blazy/issues/69), [#75](https://github.com/dinbror/blazy/issues/75), [#77](https://github.com/dinbror/blazy/issues/77) and [#82](https://github.com/dinbror/blazy/issues/82).
* Added support for lazy load of videos with sources. Fixed [#81](https://github.com/dinbror/blazy/issues/81).
* Bugfix. Ensuring that error and success classes won't be added multiple times. Fixed [#84](https://github.com/dinbror/blazy/issues/84).
* Marked `breakpoints` as obsolete. Will be removed in upcoming version. Use srcset and/or the picture element instead.
### v 1.5.4 (2016/03/06) ###
* Fixed two Safari bugs: [#66](https://github.com/dinbror/blazy/issues/66) and [#78](https://github.com/dinbror/blazy/issues/78). Ensuring "DOM ready".
### v 1.5.3 (2016/03/01) ###
* Implemented [#30](https://github.com/dinbror/blazy/pull/30). Keeping data source until success.
* Fixed [#47](https://github.com/dinbror/blazy/pull/47). After implementing #30 you can now get the image src and more information in the error/success callbacks.
* Added example page to repo `/example/index.html`.
### v 1.5.2 (2015/12/01) ###
* Fixed minor bug where the error class was added when calling `revalidate()`.
* Minor refactoring
### v 1.5.1 (2015/11/14) ###
* Fixed toArray function so it now works in IE7 + 8 again. Bug introduced in 1.4.0. Thanks for reporting [@imcotton](https://github.com/imcotton).
* Fixed [#41](https://github.com/dinbror/blazy/pull/41). Added options for validate and saveViewportOffset delay.
### v 1.5.0 (2015/10/30) ###
* Added new feature. Now you can lazy load everything with a src attribute like iframes, unity games etc.
* Fixed [#45](https://github.com/dinbror/blazy/issues/45). Now you can pass an option if you always want to load invisible images/elements.
* Fixed [#49](https://github.com/dinbror/blazy/issues/49). Expanded the `load` function so it's now possible to pass a list of elements instead of only one element. Tested with getElementById, getElementsByClassName, querySelectorAll, querySelector and jQuery selector.
* Fixed [#63](https://github.com/dinbror/blazy/issues/63).
### v 1.4.1 (2015/10/12) ###
* Fixed [#60](https://github.com/dinbror/blazy/issues/60). An "Uncaught TypeError" when options is null introduced in the refactoring in version 1.4.0.
### v 1.4.0 (2015/09/28) ###
* Fixed [#56](https://github.com/dinbror/blazy/issues/56). Now it's possible to create multiple versions of blazy without overriding options.
### v 1.3.1 (2015/02/01) ###
* Added support for CommonJS-like environments that support module.exports like [node](http://nodejs.org/).
### v 1.3.0 (2015/01/23) ###
* Fixed [#34](https://github.com/dinbror/blazy/issues/34). Expanded public `load` function with force attribute, so you can force hidden images to be loaded.
* Fixed [#24](https://github.com/dinbror/blazy/issues/24), [#32](https://github.com/dinbror/blazy/issues/32) and [#35](https://github.com/dinbror/blazy/issues/35). Updated "elementInView" function with intersection check. Thanks @teohhanhui.
### v 1.2.2 (2014/05/04) ###
* Fixed [#15](https://github.com/dinbror/blazy/issues/15), when you resize the browser window in another tab bLazy didn't trigger new images in view. Thanks joshribakoff.
### v 1.2.1 (2014/03/23) ###
* When lazy loading background images it now only updates the background-image css attribute. Thanks Saku.
### v 1.2.0 (2014/02/15) ###
* Important note: renamed option multi to `breakpoints` because it's much more descriptive.
* Added [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) support.
* Minor refactoring.
### v 1.1.3 (2014/01/21) ###
* Fixed hardcoded retina check (isRetina = true).
* Fixed "Uncaught TypeError" when data-src is null. Instead it'll trigger the `error` callback.
### v 1.1.2 (2014/01/03) ###
* New feature: After many requests I added the possibility to handle retina images (if you’re not doing retina-first).
* New feature: Now you can also lazy load background images.
* Added new option, `separator`. Used if you want to pass retina images, default separator is ‘|’. (data-src=“image.jpg|image&#64;2x.jpg”).
### v 1.1.1 (2013/12/27) ###
* Fixed #1, resize/scroll events may be detached when adding elements by ajax.
* Added new option, `errorClass`. Classname an image will get if something goes wrong, default is ‘b-error’.
* Renamed option loadedClass to `successClass` so naming is aligned. Default is still ‘b-loaded’.
### v 1.1.0 (2013/11/22) ###
* Renamed success callback from onLoaded to `success`.
* Added onerror callback; `error`.
* Added the possibility to pass multiple containers instead of one.
### v 1.0.5 (2013/10/7) ###
* Fixed "Uncaught TypeError" when container isn't default (window).
### v 1.0.4 (2013/8/29) ###
* Added null check so we won't try to load an image if it's missing a data source.
### v 1.0.3 (2013/8/27) ###
* Added new option, `loadedClass`. Classname an image will get when loaded.
* Added support for horizontal lazy loading.
* Reduced throttle time for validate.
### v 1.0.2 (2013/8/7) ###
* Fixed typo in unbindEvent function.
* Added support for IE7 as promised (fallback for querySelectorAll).
### v 1.0.1 (2013/8/6) ###
* Performance improvements.
* Added throttle function to ensure that we don't call resize/scroll functions too often.
* Cleaning image markup when image has loaded.
##LICENSE:
Copyright (c) 2013-16 Bjørn Klinggaard. Licensed under the [The MIT License (MIT)](http://opensource.org/licenses/MIT).
/*!
hey, [be]Lazy.js - v1.8.2 - 2016.10.25
A fast, small and dependency free lazy load script (https://github.com/dinbror/blazy)
(c) Bjoern Klinggaard - @bklinggaard - http://dinbror.dk/blazy
*/
;
(function(root, blazy) {
if (typeof define === 'function' && define.amd) {
// AMD. Register bLazy as an anonymous module
define(blazy);
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = blazy();
} else {
// Browser globals. Register bLazy on window
root.Blazy = blazy();
}
})(this, function() {
'use strict';
//private vars
var _source, _viewport, _isRetina, _supportClosest, _attrSrc = 'src', _attrSrcset = 'srcset';
// constructor
return function Blazy(options) {
//IE7- fallback for missing querySelectorAll support
if (!document.querySelectorAll) {
var s = document.createStyleSheet();
document.querySelectorAll = function(r, c, i, j, a) {
a = document.all, c = [], r = r.replace(/\[for\b/gi, '[htmlFor').split(',');
for (i = r.length; i--;) {
s.addRule(r[i], 'k:v');
for (j = a.length; j--;) a[j].currentStyle.k && c.push(a[j]);
s.removeRule(0);
}
return c;
};
}
//options and helper vars
var scope = this;
var util = scope._util = {};
util.elements = [];
util.destroyed = true;
scope.options = options || {};
scope.options.error = scope.options.error || false;
scope.options.offset = scope.options.offset || 100;
scope.options.root = scope.options.root || document;
scope.options.success = scope.options.success || false;
scope.options.selector = scope.options.selector || '.b-lazy';
scope.options.separator = scope.options.separator || '|';
scope.options.containerClass = scope.options.container;
scope.options.container = scope.options.containerClass ? document.querySelectorAll(scope.options.containerClass) : false;
scope.options.errorClass = scope.options.errorClass || 'b-error';
scope.options.breakpoints = scope.options.breakpoints || false;
scope.options.loadInvisible = scope.options.loadInvisible || false;
scope.options.successClass = scope.options.successClass || 'b-loaded';
scope.options.validateDelay = scope.options.validateDelay || 25;
scope.options.saveViewportOffsetDelay = scope.options.saveViewportOffsetDelay || 50;
scope.options.srcset = scope.options.srcset || 'data-srcset';
scope.options.src = _source = scope.options.src || 'data-src';
_supportClosest = Element.prototype.closest;
_isRetina = window.devicePixelRatio > 1;
_viewport = {};
_viewport.top = 0 - scope.options.offset;
_viewport.left = 0 - scope.options.offset;
/* public functions
************************************/
scope.revalidate = function() {
initialize(scope);
};
scope.load = function(elements, force) {
var opt = this.options;
if (elements && elements.length === undefined) {
loadElement(elements, force, opt);
} else {
each(elements, function(element) {
loadElement(element, force, opt);
});
}
};
scope.destroy = function() {
var util = scope._util;
if (scope.options.container) {
each(scope.options.container, function(object) {
unbindEvent(object, 'scroll', util.validateT);
});
}
unbindEvent(window, 'scroll', util.validateT);
unbindEvent(window, 'resize', util.validateT);
unbindEvent(window, 'resize', util.saveViewportOffsetT);
util.count = 0;
util.elements.length = 0;
util.destroyed = true;
};
//throttle, ensures that we don't call the functions too often
util.validateT = throttle(function() {
validate(scope);
}, scope.options.validateDelay, scope);
util.saveViewportOffsetT = throttle(function() {
saveViewportOffset(scope.options.offset);
}, scope.options.saveViewportOffsetDelay, scope);
saveViewportOffset(scope.options.offset);
//handle multi-served image src (obsolete)
each(scope.options.breakpoints, function(object) {
if (object.width >= window.screen.width) {
_source = object.src;
return false;
}
});
// start lazy load
setTimeout(function() {
initialize(scope);
}); // "dom ready" fix
};
/* Private helper functions
************************************/
function initialize(self) {
var util = self._util;
// First we create an array of elements to lazy load
util.elements = toArray(self.options);
util.count = util.elements.length;
// Then we bind resize and scroll events if not already binded
if (util.destroyed) {
util.destroyed = false;
if (self.options.container) {
each(self.options.container, function(object) {
bindEvent(object, 'scroll', util.validateT);
});
}
bindEvent(window, 'resize', util.saveViewportOffsetT);
bindEvent(window, 'resize', util.validateT);
bindEvent(window, 'scroll', util.validateT);
}
// And finally, we start to lazy load.
validate(self);
}
function validate(self) {
var util = self._util;
for (var i = 0; i < util.count; i++) {
var element = util.elements[i];
if (elementInView(element, self.options) || hasClass(element, self.options.successClass)) {
self.load(element);
util.elements.splice(i, 1);
util.count--;
i--;
}
}
if (util.count === 0) {
self.destroy();
}
}
function elementInView(ele, options) {
var rect = ele.getBoundingClientRect();
if(options.container && _supportClosest){
// Is element inside a container?
var elementContainer = ele.closest(options.containerClass);
if(elementContainer){
var containerRect = elementContainer.getBoundingClientRect();
// Is container in view?
if(inView(containerRect, _viewport)){
var top = containerRect.top - options.offset;
var right = containerRect.right + options.offset;
var bottom = containerRect.bottom + options.offset;
var left = containerRect.left - options.offset;
var containerRectWithOffset = {
top: top > _viewport.top ? top : _viewport.top,
right: right < _viewport.right ? right : _viewport.right,
bottom: bottom < _viewport.bottom ? bottom : _viewport.bottom,
left: left > _viewport.left ? left : _viewport.left
};
// Is element in view of container?
return inView(rect, containerRectWithOffset);
} else {
return false;
}
}
}
return inView(rect, _viewport);
}
function inView(rect, viewport){
// Intersection
return rect.right >= viewport.left &&
rect.bottom >= viewport.top &&
rect.left <= viewport.right &&
rect.top <= viewport.bottom;
}
function loadElement(ele, force, options) {
// if element is visible, not loaded or forced
if (!hasClass(ele, options.successClass) && (force || options.loadInvisible || (ele.offsetWidth > 0 && ele.offsetHeight > 0))) {
var dataSrc = getAttr(ele, _source) || getAttr(ele, options.src); // fallback to default 'data-src'
if (dataSrc) {
var dataSrcSplitted = dataSrc.split(options.separator);
var src = dataSrcSplitted[_isRetina && dataSrcSplitted.length > 1 ? 1 : 0];
var srcset = getAttr(ele, options.srcset);
var isImage = equal(ele, 'img');
var parent = ele.parentNode;
var isPicture = parent && equal(parent, 'picture');
// Image or background image
if (isImage || ele.src === undefined) {
var img = new Image();
// using EventListener instead of onerror and onload
// due to bug introduced in chrome v50
// (https://productforums.google.com/forum/#!topic/chrome/p51Lk7vnP2o)
var onErrorHandler = function() {
if (options.error) options.error(ele, "invalid");
addClass(ele, options.errorClass);
unbindEvent(img, 'error', onErrorHandler);
unbindEvent(img, 'load', onLoadHandler);
};
var onLoadHandler = function() {
// Is element an image
if (isImage) {
if(!isPicture) {
handleSources(ele, src, srcset);
}
// or background-image
} else {
ele.style.backgroundImage = 'url("' + src + '")';
}
itemLoaded(ele, options);
unbindEvent(img, 'load', onLoadHandler);
unbindEvent(img, 'error', onErrorHandler);
};
// Picture element
if (isPicture) {
img = ele; // Image tag inside picture element wont get preloaded
each(parent.getElementsByTagName('source'), function(source) {
handleSource(source, _attrSrcset, options.srcset);
});
}
bindEvent(img, 'error', onErrorHandler);
bindEvent(img, 'load', onLoadHandler);
handleSources(img, src, srcset); // Preload
} else { // An item with src like iframe, unity games, simpel video etc
ele.src = src;
itemLoaded(ele, options);
}
} else {
// video with child source
if (equal(ele, 'video')) {
each(ele.getElementsByTagName('source'), function(source) {
handleSource(source, _attrSrc, options.src);
});
ele.load();
itemLoaded(ele, options);
} else {
if (options.error) options.error(ele, "missing");
addClass(ele, options.errorClass);
}
}
}
}
function itemLoaded(ele, options) {
addClass(ele, options.successClass);
if (options.success) options.success(ele);
// cleanup markup, remove data source attributes
removeAttr(ele, options.src);
removeAttr(ele, options.srcset);
each(options.breakpoints, function(object) {
removeAttr(ele, object.src);
});
}
function handleSource(ele, attr, dataAttr) {
var dataSrc = getAttr(ele, dataAttr);
if (dataSrc) {
setAttr(ele, attr, dataSrc);
removeAttr(ele, dataAttr);
}
}
function handleSources(ele, src, srcset){
if(srcset) {
setAttr(ele, _attrSrcset, srcset); //srcset
}
ele.src = src; //src
}
function setAttr(ele, attr, value){
ele.setAttribute(attr, value);
}
function getAttr(ele, attr) {
return ele.getAttribute(attr);
}
function removeAttr(ele, attr){
ele.removeAttribute(attr);
}
function equal(ele, str) {
return ele.nodeName.toLowerCase() === str;
}
function hasClass(ele, className) {
return (' ' + ele.className + ' ').indexOf(' ' + className + ' ') !== -1;
}
function addClass(ele, className) {
if (!hasClass(ele, className)) {
ele.className += ' ' + className;
}
}
function toArray(options) {
var array = [];
var nodelist = (options.root).querySelectorAll(options.selector);
for (var i = nodelist.length; i--; array.unshift(nodelist[i])) {}
return array;
}
function saveViewportOffset(offset) {
_viewport.bottom = (window.innerHeight || document.documentElement.clientHeight) + offset;
_viewport.right = (window.innerWidth || document.documentElement.clientWidth) + offset;
}
function bindEvent(ele, type, fn) {
if (ele.attachEvent) {
ele.attachEvent && ele.attachEvent('on' + type, fn);
} else {
ele.addEventListener(type, fn, { capture: false, passive: true });
}
}
function unbindEvent(ele, type, fn) {
if (ele.detachEvent) {
ele.detachEvent && ele.detachEvent('on' + type, fn);
} else {
ele.removeEventListener(type, fn, { capture: false, passive: true });
}
}
function each(object, fn) {
if (object && fn) {
var l = object.length;
for (var i = 0; i < l && fn(object[i], i) !== false; i++) {}
}
}
function throttle(fn, minDelay, scope) {
var lastCall = 0;
return function() {
var now = +new Date();
if (now - lastCall < minDelay) {
return;
}
lastCall = now;
fn.apply(scope, arguments);
};
}
});
/*!
hey, [be]Lazy.js - v1.8.2 - 2016.10.25
A fast, small and dependency free lazy load script (https://github.com/dinbror/blazy)
(c) Bjoern Klinggaard - @bklinggaard - http://dinbror.dk/blazy
*/
(function(q,m){"function"===typeof define&&define.amd?define(m):"object"===typeof exports?module.exports=m():q.Blazy=m()})(this,function(){function q(b){var c=b._util;c.elements=E(b.options);c.count=c.elements.length;c.destroyed&&(c.destroyed=!1,b.options.container&&l(b.options.container,function(a){n(a,"scroll",c.validateT)}),n(window,"resize",c.saveViewportOffsetT),n(window,"resize",c.validateT),n(window,"scroll",c.validateT));m(b)}function m(b){for(var c=b._util,a=0;a<c.count;a++){var d=c.elements[a],e;a:{var g=d;e=b.options;var p=g.getBoundingClientRect();if(e.container&&y&&(g=g.closest(e.containerClass))){g=g.getBoundingClientRect();e=r(g,f)?r(p,{top:g.top-e.offset,right:g.right+e.offset,bottom:g.bottom+e.offset,left:g.left-e.offset}):!1;break a}e=r(p,f)}if(e||t(d,b.options.successClass))b.load(d),c.elements.splice(a,1),c.count--,a--}0===c.count&&b.destroy()}function r(b,c){return b.right>=c.left&&b.bottom>=c.top&&b.left<=c.right&&b.top<=c.bottom}function z(b,c,a){if(!t(b,a.successClass)&&(c||a.loadInvisible||0<b.offsetWidth&&0<b.offsetHeight))if(c=b.getAttribute(u)||b.getAttribute(a.src)){c=c.split(a.separator);var d=c[A&&1<c.length?1:0],e=b.getAttribute(a.srcset),g="img"===b.nodeName.toLowerCase(),p=(c=b.parentNode)&&"picture"===c.nodeName.toLowerCase();if(g||void 0===b.src){var h=new Image,w=function(){a.error&&a.error(b,"invalid");v(b,a.errorClass);k(h,"error",w);k(h,"load",f)},f=function(){g?p||B(b,d,e):b.style.backgroundImage='url("'+d+'")';x(b,a);k(h,"load",f);k(h,"error",w)};p&&(h=b,l(c.getElementsByTagName("source"),function(b){var c=a.srcset,e=b.getAttribute(c);e&&(b.setAttribute("srcset",e),b.removeAttribute(c))}));n(h,"error",w);n(h,"load",f);B(h,d,e)}else b.src=d,x(b,a)}else"video"===b.nodeName.toLowerCase()?(l(b.getElementsByTagName("source"),function(b){var c=a.src,e=b.getAttribute(c);e&&(b.setAttribute("src",e),b.removeAttribute(c))}),b.load(),x(b,a)):(a.error&&a.error(b,"missing"),v(b,a.errorClass))}function x(b,c){v(b,c.successClass);c.success&&c.success(b);b.removeAttribute(c.src);b.removeAttribute(c.srcset);l(c.breakpoints,function(a){b.removeAttribute(a.src)})}function B(b,c,a){a&&b.setAttribute("srcset",a);b.src=c}function t(b,c){return-1!==(" "+b.className+" ").indexOf(" "+c+" ")}function v(b,c){t(b,c)||(b.className+=" "+c)}function E(b){var c=[];b=b.root.querySelectorAll(b.selector);for(var a=b.length;a--;c.unshift(b[a]));return c}function C(b){f.bottom=(window.innerHeight||document.documentElement.clientHeight)+b;f.right=(window.innerWidth||document.documentElement.clientWidth)+b}function n(b,c,a){b.attachEvent?b.attachEvent&&b.attachEvent("on"+c,a):b.addEventListener(c,a,{capture:!1,passive:!0})}function k(b,c,a){b.detachEvent?b.detachEvent&&b.detachEvent("on"+c,a):b.removeEventListener(c,a,{capture:!1,passive:!0})}function l(b,c){if(b&&c)for(var a=b.length,d=0;d<a&&!1!==c(b[d],d);d++);}function D(b,c,a){var d=0;return function(){var e=+new Date;e-d<c||(d=e,b.apply(a,arguments))}}var u,f,A,y;return function(b){if(!document.querySelectorAll){var c=document.createStyleSheet();document.querySelectorAll=function(a,b,d,h,f){f=document.all;b=[];a=a.replace(/\[for\b/gi,"[htmlFor").split(",");for(d=a.length;d--;){c.addRule(a[d],"k:v");for(h=f.length;h--;)f[h].currentStyle.k&&b.push(f[h]);c.removeRule(0)}return b}}var a=this,d=a._util={};d.elements=[];d.destroyed=!0;a.options=b||{};a.options.error=a.options.error||!1;a.options.offset=a.options.offset||100;a.options.root=a.options.root||document;a.options.success=a.options.success||!1;a.options.selector=a.options.selector||".b-lazy";a.options.separator=a.options.separator||"|";a.options.containerClass=a.options.container;a.options.container=a.options.containerClass?document.querySelectorAll(a.options.containerClass):!1;a.options.errorClass=a.options.errorClass||"b-error";a.options.breakpoints=a.options.breakpoints||!1;a.options.loadInvisible=a.options.loadInvisible||!1;a.options.successClass=a.options.successClass||"b-loaded";a.options.validateDelay=a.options.validateDelay||25;a.options.saveViewportOffsetDelay=a.options.saveViewportOffsetDelay||50;a.options.srcset=a.options.srcset||"data-srcset";a.options.src=u=a.options.src||"data-src";y=Element.prototype.closest;A=1<window.devicePixelRatio;f={};f.top=0-a.options.offset;f.left=0-a.options.offset;a.revalidate=function(){q(a)};a.load=function(a,b){var c=this.options;void 0===a.length?z(a,b,c):l(a,function(a){z(a,b,c)})};a.destroy=function(){var a=this._util;this.options.container&&l(this.options.container,function(b){k(b,"scroll",a.validateT)});k(window,"scroll",a.validateT);k(window,"resize",a.validateT);k(window,"resize",a.saveViewportOffsetT);a.count=0;a.elements.length=0;a.destroyed=!0};d.validateT=D(function(){m(a)},a.options.validateDelay,a);d.saveViewportOffsetT=D(function(){C(a.options.offset)},a.options.saveViewportOffsetDelay,a);C(a.options.offset);l(a.options.breakpoints,function(a){if(a.width>=window.screen.width)return u=a.src,!1});setTimeout(function(){q(a)})}});
\ No newline at end of file
{
"name": "bLazy",
"main": "blazy.js",
"version": "1.8.2",
"description": "A fast lightweight pure JavaScript script for lazy loading and multi-serving images, iframes, videos and more.",
"homepage": "https://github.com/dinbror/blazy",
"keywords": [
"blazy",
"lazy",
"lazyload",
"lazyloading",
"retina",
"responsive",
"image",
"images",
"picture",
"srcset",
"javascript",
"performance"
],
"authors": [
{
"name": "Bjørn Klinggaard",
"url": "http://dinbror.dk",
"email": "hello@dinbror.dk"
}
],
"license": "MIT",
"moduleType": [
"amd",
"CommonJS"
],
"ignore": []
}
<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>blazy.js - lazyload examples</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style> html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}table{border-collapse:collapse;border-spacing:0}
body {
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
}
h1 {
font-size: 75px;
font-weight: bold;
}
h2 {
font-size:40px;
padding: 20px 0 10px;
}
p{
padding:10px 0;
}
li{
padding: 3px 0;
}
.ratio{
padding-bottom:66.64%;
background-color: #1E1E1E;
height: 0;
width: 100%;
overflow: hidden;
position: relative;
}
.example {
overflow:hidden;
position:relative;
}
.example iframe {
position:absolute;
height:100%;
width:100%;
}
.header {
background: #ececec;
padding: 50px;
color: black;
}
.branding{
max-width: 900px;
margin: 0 auto;
}
.branding pre{
background: #f7f7f7;
color: black;
border-radius: 0;
}
.github {
background: url('http://dinbror.dk/blazy/assets/github.png') 0 0 no-repeat;
height: 149px;
width: 149px;
position: absolute;
top: 0;
right: 0;
}
.section {
margin: 0 auto;
max-width:900px;
}
.container {
background-color: #1E1E1E;
height:0;
padding-bottom:66%;
}
.horizontal.container{
overflow-x: scroll;
overflow-y: hidden;
}
.horizontal .list{
font-size:0;
width:300%;
}
.horizontal .list .wrapper {
display: inline-block;
width:33.3%;
}
.vertical.container{
overflow-x: hidden;
overflow-y: scroll;
}
.vertical .list{
width: 100%;
}
.vertical .list .wrapper{
width: 100%;
}
img {
max-width: 100%;
}
pre {
background: #212121;
color: white;
padding: 15px 10px 5px;
margin: 0 0 20px;
font-family:Menlo,monospace;
font-size: 14px;
overflow-x: auto;
}
.b-lazy, video{
display:inline-block;
position:absolute;
left:0;
top:0;
height:100%;
width:100%;
}
.list .b-lazy{
max-height:100%;
height:auto;
}
.b-lazy.animate{
opacity:0;
-ms-transform: scale(3);
-moz-transform: scale(3);
-webkit-transform: scale(3);
transform: scale(3);
-ms-transition: all 500ms;
-moz-transition: all 500ms;
-webkit-transition: all 500ms;
transition: all 500ms;
}
.b-loaded.animate {
opacity:1;
-ms-transform: scale(1);
-moz-transform: scale(1);
-webkit-transform: scale(1);
transform: scale(1);
}
@media (max-width: 600px) {
h1 {
font-size: 40px;
}
h2 {
font-size: 25px;
}
}
</style>
</head>
<body>
<div class="header">
<div class="branding">
<h1>blazy.js</h1>
<p>Blazy is a fast, SEO friendly and small but still feature-rich lazy load script. It was originally build for lazy loading images but it can also lazy load any element with a source attribute like iframes, unity games, html5 videos, scripts etc.</p>
<p>Blazy comes with a bunch of features like serving retina images for retina screens, multi-serve images depending on screensize and error handling. <a href="http://dinbror.dk/blog/blazy/?ref=example-page">For a list of all features and more details you can visit the blog post</a>. Blazy works in all modern browsers including IE7+.</p>
<h2>How to lazyload</h2>
<ol>
<li>Add blazy.js to your website</li>
<li>Add the 'b-lazy' class to the elements that should be lazy loaded</li>
<li>Initialize blazy whenever you're ready <br><br>
<pre>
var bLazy = new Blazy({
// Options
});
</pre>
</li>
</ol>
<h2>Examples</h2>
<ol>
<li><a href="#image">Lazy load images, regular, retina, srcset and picture element</a></li>
<li><a href="#background-image">Lazy load background image</a></li>
<li><a href="#image-inside-container">Lazy load inside container (vertical & horizotal)</a></li>
<li><a href="#iframe">Lazy load iframe</a></li>
<li><a href="#html5-video">Lazy load HTML5 video</a></li>
<li><a href="#script">Lazy load script file</a></li>
</ol>
</div>
<a class="github" href="https://github.com/dinbror/blazy/"></a>
</div>
<div class="section">
<div class="example" id="image">
<h2>1.1: Default lazyload image example</h2>
<div class="wrapper ratio">
<img class="b-lazy" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://cdn.dinbror.dk/assets/blazy/01.jpg" alt="Lazy load images example 1a" />
</div>
<pre>
&lt;img class="b-lazy" data-src=&quot;image.jpg&quot; /&gt;
</pre>
</div>
<div class="example">
<h2>1.2: Lazy load image example with css effect</h2>
<div class="wrapper ratio">
<img class="b-lazy animate" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://cdn.dinbror.dk/assets/blazy/02.jpg" alt="Lazy load images example 1b" />
</div>
<pre>
CSS:
.b-lazy {
opacity:0;
transform: scale(3);
transition: all 500ms;
}
.b-loaded {
opacity:1;
transform: scale(1);
}
</pre>
</div>
<div class="example">
<h2>1.3: Lazy load image example with low res image placeholder</h2>
<div class="wrapper ratio">
<img class="b-lazy" src="http://cdn.dinbror.dk/assets/blazy/03-low.jpg" data-src="http://cdn.dinbror.dk/assets/blazy/03.jpg" alt="Lazy load images example 1c" />
</div>
<pre>
&lt;img class="b-lazy" src=&quot;low-res-image.jpg&quot; data-src=&quot;image.jpg&quot; /&gt;
</pre>
</div>
<div class="example">
<h2>1.4: Lazy load image example with srcset</h2>
<div class="wrapper ratio">
<img
alt="Lazy load image example with srcset"
sizes="100vw"
data-srcset="http://placehold.it/1024x682?text=large 1024w,
http://placehold.it/600x400?text=medium 640w,
http://placehold.it/320x214?text=small 320w"
data-src="http://placehold.it/600x400?text=fallback"
class="b-lazy" />
</div>
<pre>
&lt;img class="b-lazy"
sizes=&quot;100vw&quot;
data-srcset=&quot;large.jpg 1024w, medium.jpg 640w, small.jpg 320w&quot;
data-src=&quot;medium.jpg&quot; /&gt;
</pre>
</div>
<div class="example">
<h2>1.5: Lazy load image example with picture element</h2>
<div class="wrapper ratio">
<picture>
<source
media="(min-width: 650px)"
data-srcset="http://placehold.it/1024x682?text=Min-650" />
<source
media="(min-width: 465px)"
data-srcset="http://placehold.it/600x400?text=Min-465" />
<img
class="b-lazy"
data-src="http://placehold.it/600x400?text=default"
alt="Lazy load image example with picture element" />
</picture>
</div>
<pre>
&lt;picture&gt;
&lt;source
media=&quot;(min-width: 650px)&quot;
data-srcset=&quot;image-650.jpg&quot; /&gt;
&lt;source
media=&quot;(min-width: 465px)&quot;
data-srcset=&quot;image-465.jpg&quot; /&gt;
&lt;img class=&quot;b-lazy&quot;
data-src=&quot;default.jpg&quot; /&gt;
&lt;/picture&gt;
</pre>
</div>
<div class="example">
<h2>1.6: Lazyload image with retina support example</h2>
<div class="wrapper ratio">
<img class="b-lazy" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://placehold.it/1024x682?text=Non-Retina|http://placehold.it/1024x682?text=Retina" alt="Lazy load images example 1a" />
</div>
<pre>
&lt;img class="b-lazy" data-src=&quot;image.jpg|retina-image.jpg&quot; /&gt;
</pre>
</div>
<div class="example" id="background-image">
<h2>2: Lazy load background image example</h2>
<div class="wrapper ratio">
<div class="b-lazy" data-src="http://cdn.dinbror.dk/assets/blazy/05.jpg"></div>
</div>
<pre>
&lt;div class="b-lazy" data-src=&quot;image.jpg&quot;&gt;&lt;/div&gt;
</pre>
</div>
<div class="example" id="image-inside-container">
<h2>3.1: Horizontal lazyload inside container example</h2>
<div class="container horizontal">
<ul class="list">
<li class="wrapper ratio">
<img class="b-lazy" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://cdn.dinbror.dk/assets/blazy/04.jpg" alt="Lazy load images example 3 image 1" />
</li>
<li class="wrapper ratio">
<img class="b-lazy" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://cdn.dinbror.dk/assets/blazy/05.jpg" alt="Lazy load images example 3 image 2" />
</li>
<li class="wrapper ratio">
<img class="b-lazy" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://cdn.dinbror.dk/assets/blazy/06.jpg" alt="Lazy load images example 3 image 3" />
</li>
</ul>
</div>
<pre>
var blazy = new Blazy({
container: '.container'
});
</pre>
</div>
<div class="example">
<h2>3.2: Vertical lazyload inside container example</h2>
<div class="container vertical">
<ul class="list">
<li class="wrapper ratio">
<img class="b-lazy" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://cdn.dinbror.dk/assets/blazy/04.jpg" alt="Lazy load images example 3 image 1" />
</li>
<li class="wrapper ratio">
<img class="b-lazy" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://cdn.dinbror.dk/assets/blazy/05.jpg" alt="Lazy load images example 3 image 2" />
</li>
<li class="wrapper ratio">
<img class="b-lazy" src=data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== data-src="http://cdn.dinbror.dk/assets/blazy/06.jpg" alt="Lazy load images example 3 image 3" />
</li>
</ul>
</div>
<pre>
var blazy = new Blazy({
container: '.container'
});
</pre>
</div>
<div class="example" id="iframe">
<h2>4: Lazy load iframe example</h2>
<div class="wrapper ratio">
<iframe class="b-lazy" data-src="https://www.youtube.com/embed/uKtjVQ5IJOQ" frameborder="0" allowfullscreen></iframe>
</div>
<pre>
&lt;iframe class=&quot;b-lazy&quot;
data-src=&quot;https://www.youtube.com/embed/uKtjVQ5IJOQ&quot;
frameborder=&quot;0&quot;
allowfullscreen>
&lt;/iframe&gt;
</pre>
</div>
<div class="example" id="html5-video">
<h2>5.1: Lazy load HTML5 video example</h2>
<div class="wrapper ratio">
<video class="b-lazy" data-src="http://cdn.dinbror.dk/assets/blazy/SampleVideo_1280x720_1mb.mp4" controls></video>
</div>
<pre>
&lt;video class="b-lazy" data-src=&quot;video.mp4&quot; controls&gt;&lt;/video&gt;
</pre>
</div>
<div class="example">
<h2>5.2: Lazy load HTML5 video advanced example</h2>
<div class="wrapper ratio">
<video class="b-lazy" controls>
<source data-src="http://cdn.dinbror.dk/assets/blazy/big_buck_bunny.mp4" type="video/mp4">
<source data-src="http://cdn.dinbror.dk/assets/blazy/big_buck_bunny.webm" type="video/webm">
Your browser doesn't support HTML5 video tag.
</video>
</div>
<pre>
&lt;video class="b-lazy" controls&gt;
&lt;source data-src=&quot;video.mp4&quot; type=&quot;video/mp4&quot;&gt;
&lt;source data-src=&quot;video.webm&quot; type=&quot;video/webm&quot;&gt;
Your browser doesn&#39;t support HTML5 video tag.
&lt;/video&gt;
</pre>
</div>
<div class="example" id="script">
<h2>6: Lazy load script example</h2>
<script class="b-lazy" data-src="script.js" async></script>
<p>Check the console log</p>
<pre>
&lt;script class="b-lazy" data-src=&quot;script.js&quot; async&gt;&lt;/script&gt;
</pre>
</div>
</div>
<script src="../polyfills/closest.js"></script>
<script src="../blazy.js"></script>
<script>
window.bLazy = new Blazy({
container: '.container',
success: function(element){
console.log("Element loaded: ", element.nodeName);
}
});
</script>
</body>
</html>
\ No newline at end of file
{
"name": "blazy",
"version": "1.8.2",
"description": "A fast lightweight pure JavaScript script for lazy loading and multi-serving images, iframes, videos and more.",
"main": "blazy.js",
"keywords": [
"blazy",
"blazyjs",
"blazy.js",
"lazy",
"lazyload",
"lazyloading",
"image",
"images",
"picture",
"srcset",
"iframe",
"video",
"unity",
"retina",
"responsive",
"performance"
],
"author": "Bjørn Klinggaard (http://dinbror.dk/blazy)",
"repository": {
"type": "git",
"url": "git://github.com/dinbror/blazy.git"
},
"bugs": {
"url": "https://github.com/dinbror/blazy/issues"
},
"license": "MIT",
"homepage": "https://github.com/dinbror/blazy",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"directories": {
"example": "example"
}
}
// Polyfill for Element.closest that falls back to Element.matches that falls back to querySelectorAll
// Created for blazy.js 1.8.1 - https://github.com/dinbror/blazy to ensure IE7+ support
(function () {
if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector ||
function(s) {
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
i = matches.length;
while (--i >= 0 && matches.item(i) !== this) {}
return i > -1;
};
}
if (!Element.prototype.closest) {
Element.prototype.closest = Element.prototype.closest ||
function(selector) {
var element = this;
while (element.matches && !element.matches(selector)) element = element.parentNode;
return element.matches ? element : null;
};
}
})();
\ No newline at end of file
jQuery Cycle Plugin
===================
Cycle is an easy-to-use slideshow plugin that provides many options and effects for creating beautiful slideshows.
Links
* [Home Page](http://jquery.malsup.com/cycle/)
* [Options Reference](http://jquery.malsup.com/cycle/options.html)
* [Effects Browser](http://jquery.malsup.com/cycle/browser.html)
* [Download](http://jquery.malsup.com/cycle/download.html)
\ No newline at end of file
{
"name": "cycle",
"title": "Cycle",
"description": "Wildly popular slideshow plugin for displaying image or non-image slideshows. Lots of available transition effects such as fade, scroll, shuffle, zoom, and many more. Lots of features and ease of use is what this plugin is all about.",
"keywords": [
"slideshow",
"carousel",
"slider",
"cycle"
],
"version": "3.0.3-2013.07.11",
"author": {
"name": "M. Alsup",
"url": "http://jquery.malsup.com"
},
"licenses": [
{
"type": "MIT",
"url": "http://malsup.github.com/mit-license.txt"
},
{
"type": "GPL",
"url": "http://malsup.github.com/gpl-license-v2.txt"
}
],
"bugs": "https://github.com/malsup/cycle/issues",
"homepage": "http://jquery.malsup.com/cycle/",
"docs": "http://jquery.malsup.com/cycle/",
"download": "http://malsup.github.com/jquery.cycle.all.js",
"dependencies": {
"jquery": ">=1.7"
}
}
/*!
* jQuery Cycle Plugin (with Transition Definitions)
* Examples and documentation at: http://jquery.malsup.com/cycle/
* Copyright (c) 2007-2013 M. Alsup
* Version: 3.0.3 (11-JUL-2013)
* Dual licensed under the MIT and GPL licenses.
* http://jquery.malsup.com/license.html
* Requires: jQuery v1.7.1 or later
*/
;(function($, undefined) {
"use strict";
var ver = '3.0.3';
function debug(s) {
if ($.fn.cycle.debug)
log(s);
}
function log() {
/*global console */
if (window.console && console.log)
console.log('[cycle] ' + Array.prototype.join.call(arguments,' '));
}
$.expr[':'].paused = function(el) {
return el.cyclePause;
};
// the options arg can be...
// a number - indicates an immediate transition should occur to the given slide index
// a string - 'pause', 'resume', 'toggle', 'next', 'prev', 'stop', 'destroy' or the name of a transition effect (ie, 'fade', 'zoom', etc)
// an object - properties to control the slideshow
//
// the arg2 arg can be...
// the name of an fx (only used in conjunction with a numeric value for 'options')
// the value true (only used in first arg == 'resume') and indicates
// that the resume should occur immediately (not wait for next timeout)
$.fn.cycle = function(options, arg2) {
var o = { s: this.selector, c: this.context };
// in 1.3+ we can fix mistakes with the ready state
if (this.length === 0 && options != 'stop') {
if (!$.isReady && o.s) {
log('DOM not ready, queuing slideshow');
$(function() {
$(o.s,o.c).cycle(options,arg2);
});
return this;
}
// is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
return this;
}
// iterate the matched nodeset
return this.each(function() {
var opts = handleArguments(this, options, arg2);
if (opts === false)
return;
opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink;
// stop existing slideshow for this container (if there is one)
if (this.cycleTimeout)
clearTimeout(this.cycleTimeout);
this.cycleTimeout = this.cyclePause = 0;
this.cycleStop = 0; // issue #108
var $cont = $(this);
var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children();
var els = $slides.get();
if (els.length < 2) {
log('terminating; too few slides: ' + els.length);
return;
}
var opts2 = buildOptions($cont, $slides, els, opts, o);
if (opts2 === false)
return;
var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.backwards);
// if it's an auto slideshow, kick it off
if (startTime) {
startTime += (opts2.delay || 0);
if (startTime < 10)
startTime = 10;
debug('first timeout: ' + startTime);
this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts.backwards);}, startTime);
}
});
};
function triggerPause(cont, byHover, onPager) {
var opts = $(cont).data('cycle.opts');
if (!opts)
return;
var paused = !!cont.cyclePause;
if (paused && opts.paused)
opts.paused(cont, opts, byHover, onPager);
else if (!paused && opts.resumed)
opts.resumed(cont, opts, byHover, onPager);
}
// process the args that were passed to the plugin fn
function handleArguments(cont, options, arg2) {
if (cont.cycleStop === undefined)
cont.cycleStop = 0;
if (options === undefined || options === null)
options = {};
if (options.constructor == String) {
switch(options) {
case 'destroy':
case 'stop':
var opts = $(cont).data('cycle.opts');
if (!opts)
return false;
cont.cycleStop++; // callbacks look for change
if (cont.cycleTimeout)
clearTimeout(cont.cycleTimeout);
cont.cycleTimeout = 0;
if (opts.elements)
$(opts.elements).stop();
$(cont).removeData('cycle.opts');
if (options == 'destroy')
destroy(cont, opts);
return false;
case 'toggle':
cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1;
checkInstantResume(cont.cyclePause, arg2, cont);
triggerPause(cont);
return false;
case 'pause':
cont.cyclePause = 1;
triggerPause(cont);
return false;
case 'resume':
cont.cyclePause = 0;
checkInstantResume(false, arg2, cont);
triggerPause(cont);
return false;
case 'prev':
case 'next':
opts = $(cont).data('cycle.opts');
if (!opts) {
log('options not found, "prev/next" ignored');
return false;
}
if (typeof arg2 == 'string')
opts.oneTimeFx = arg2;
$.fn.cycle[options](opts);
return false;
default:
options = { fx: options };
}
return options;
}
else if (options.constructor == Number) {
// go to the requested slide
var num = options;
options = $(cont).data('cycle.opts');
if (!options) {
log('options not found, can not advance slide');
return false;
}
if (num < 0 || num >= options.elements.length) {
log('invalid slide index: ' + num);
return false;
}
options.nextSlide = num;
if (cont.cycleTimeout) {
clearTimeout(cont.cycleTimeout);
cont.cycleTimeout = 0;
}
if (typeof arg2 == 'string')
options.oneTimeFx = arg2;
go(options.elements, options, 1, num >= options.currSlide);
return false;
}
return options;
function checkInstantResume(isPaused, arg2, cont) {
if (!isPaused && arg2 === true) { // resume now!
var options = $(cont).data('cycle.opts');
if (!options) {
log('options not found, can not resume');
return false;
}
if (cont.cycleTimeout) {
clearTimeout(cont.cycleTimeout);
cont.cycleTimeout = 0;
}
go(options.elements, options, 1, !options.backwards);
}
}
}
function removeFilter(el, opts) {
if (!$.support.opacity && opts.cleartype && el.style.filter) {
try { el.style.removeAttribute('filter'); }
catch(smother) {} // handle old opera versions
}
}
// unbind event handlers
function destroy(cont, opts) {
if (opts.next)
$(opts.next).unbind(opts.prevNextEvent);
if (opts.prev)
$(opts.prev).unbind(opts.prevNextEvent);
if (opts.pager || opts.pagerAnchorBuilder)
$.each(opts.pagerAnchors || [], function() {
this.unbind().remove();
});
opts.pagerAnchors = null;
$(cont).unbind('mouseenter.cycle mouseleave.cycle');
if (opts.destroy) // callback
opts.destroy(opts);
}
// one-time initialization
function buildOptions($cont, $slides, els, options, o) {
var startingSlideSpecified;
// support metadata plugin (v1.0 and v2.0)
var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null;
if (meta)
opts = $.extend(opts, meta);
if (opts.autostop)
opts.countdown = opts.autostopCount || els.length;
var cont = $cont[0];
$cont.data('cycle.opts', opts);
opts.$cont = $cont;
opts.stopCount = cont.cycleStop;
opts.elements = els;
opts.before = opts.before ? [opts.before] : [];
opts.after = opts.after ? [opts.after] : [];
// push some after callbacks
if (!$.support.opacity && opts.cleartype)
opts.after.push(function() { removeFilter(this, opts); });
if (opts.continuous)
opts.after.push(function() { go(els,opts,0,!opts.backwards); });
saveOriginalOpts(opts);
// clearType corrections
if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
clearTypeFix($slides);
// container requires non-static position so that slides can be position within
if ($cont.css('position') == 'static')
$cont.css('position', 'relative');
if (opts.width)
$cont.width(opts.width);
if (opts.height && opts.height != 'auto')
$cont.height(opts.height);
if (opts.startingSlide !== undefined) {
opts.startingSlide = parseInt(opts.startingSlide,10);
if (opts.startingSlide >= els.length || opts.startSlide < 0)
opts.startingSlide = 0; // catch bogus input
else
startingSlideSpecified = true;
}
else if (opts.backwards)
opts.startingSlide = els.length - 1;
else
opts.startingSlide = 0;
// if random, mix up the slide array
if (opts.random) {
opts.randomMap = [];
for (var i = 0; i < els.length; i++)
opts.randomMap.push(i);
opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
if (startingSlideSpecified) {
// try to find the specified starting slide and if found set start slide index in the map accordingly
for ( var cnt = 0; cnt < els.length; cnt++ ) {
if ( opts.startingSlide == opts.randomMap[cnt] ) {
opts.randomIndex = cnt;
}
}
}
else {
opts.randomIndex = 1;
opts.startingSlide = opts.randomMap[1];
}
}
else if (opts.startingSlide >= els.length)
opts.startingSlide = 0; // catch bogus input
opts.currSlide = opts.startingSlide || 0;
var first = opts.startingSlide;
// set position and zIndex on all the slides
$slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) {
var z;
if (opts.backwards)
z = first ? i <= first ? els.length + (i-first) : first-i : els.length-i;
else
z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
$(this).css('z-index', z);
});
// make sure first slide is visible
$(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case
removeFilter(els[first], opts);
// stretch slides
if (opts.fit) {
if (!opts.aspect) {
if (opts.width)
$slides.width(opts.width);
if (opts.height && opts.height != 'auto')
$slides.height(opts.height);
} else {
$slides.each(function(){
var $slide = $(this);
var ratio = (opts.aspect === true) ? $slide.width()/$slide.height() : opts.aspect;
if( opts.width && $slide.width() != opts.width ) {
$slide.width( opts.width );
$slide.height( opts.width / ratio );
}
if( opts.height && $slide.height() < opts.height ) {
$slide.height( opts.height );
$slide.width( opts.height * ratio );
}
});
}
}
if (opts.center && ((!opts.fit) || opts.aspect)) {
$slides.each(function(){
var $slide = $(this);
$slide.css({
"margin-left": opts.width ?
((opts.width - $slide.width()) / 2) + "px" :
0,
"margin-top": opts.height ?
((opts.height - $slide.height()) / 2) + "px" :
0
});
});
}
if (opts.center && !opts.fit && !opts.slideResize) {
$slides.each(function(){
var $slide = $(this);
$slide.css({
"margin-left": opts.width ? ((opts.width - $slide.width()) / 2) + "px" : 0,
"margin-top": opts.height ? ((opts.height - $slide.height()) / 2) + "px" : 0
});
});
}
// stretch container
var reshape = (opts.containerResize || opts.containerResizeHeight) && $cont.innerHeight() < 1;
if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9
var maxw = 0, maxh = 0;
for(var j=0; j < els.length; j++) {
var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight();
if (!w) w = e.offsetWidth || e.width || $e.attr('width');
if (!h) h = e.offsetHeight || e.height || $e.attr('height');
maxw = w > maxw ? w : maxw;
maxh = h > maxh ? h : maxh;
}
if (opts.containerResize && maxw > 0 && maxh > 0)
$cont.css({width:maxw+'px',height:maxh+'px'});
if (opts.containerResizeHeight && maxh > 0)
$cont.css({height:maxh+'px'});
}
var pauseFlag = false; // https://github.com/malsup/cycle/issues/44
if (opts.pause)
$cont.bind('mouseenter.cycle', function(){
pauseFlag = true;
this.cyclePause++;
triggerPause(cont, true);
}).bind('mouseleave.cycle', function(){
if (pauseFlag)
this.cyclePause--;
triggerPause(cont, true);
});
if (supportMultiTransitions(opts) === false)
return false;
// apparently a lot of people use image slideshows without height/width attributes on the images.
// Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that.
var requeue = false;
options.requeueAttempts = options.requeueAttempts || 0;
$slides.each(function() {
// try to get height/width of each slide
var $el = $(this);
this.cycleH = (opts.fit && opts.height) ? opts.height : ($el.height() || this.offsetHeight || this.height || $el.attr('height') || 0);
this.cycleW = (opts.fit && opts.width) ? opts.width : ($el.width() || this.offsetWidth || this.width || $el.attr('width') || 0);
if ( $el.is('img') ) {
var loading = (this.cycleH === 0 && this.cycleW === 0 && !this.complete);
// don't requeue for images that are still loading but have a valid size
if (loading) {
if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever
log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH);
setTimeout(function() {$(o.s,o.c).cycle(options);}, opts.requeueTimeout);
requeue = true;
return false; // break each loop
}
else {
log('could not determine size of image: '+this.src, this.cycleW, this.cycleH);
}
}
}
return true;
});
if (requeue)
return false;
opts.cssBefore = opts.cssBefore || {};
opts.cssAfter = opts.cssAfter || {};
opts.cssFirst = opts.cssFirst || {};
opts.animIn = opts.animIn || {};
opts.animOut = opts.animOut || {};
$slides.not(':eq('+first+')').css(opts.cssBefore);
$($slides[first]).css(opts.cssFirst);
if (opts.timeout) {
opts.timeout = parseInt(opts.timeout,10);
// ensure that timeout and speed settings are sane
if (opts.speed.constructor == String)
opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed,10);
if (!opts.sync)
opts.speed = opts.speed / 2;
var buffer = opts.fx == 'none' ? 0 : opts.fx == 'shuffle' ? 500 : 250;
while((opts.timeout - opts.speed) < buffer) // sanitize timeout
opts.timeout += opts.speed;
}
if (opts.easing)
opts.easeIn = opts.easeOut = opts.easing;
if (!opts.speedIn)
opts.speedIn = opts.speed;
if (!opts.speedOut)
opts.speedOut = opts.speed;
opts.slideCount = els.length;
opts.currSlide = opts.lastSlide = first;
if (opts.random) {
if (++opts.randomIndex == els.length)
opts.randomIndex = 0;
opts.nextSlide = opts.randomMap[opts.randomIndex];
}
else if (opts.backwards)
opts.nextSlide = opts.startingSlide === 0 ? (els.length-1) : opts.startingSlide-1;
else
opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;
// run transition init fn
if (!opts.multiFx) {
var init = $.fn.cycle.transitions[opts.fx];
if ($.isFunction(init))
init($cont, $slides, opts);
else if (opts.fx != 'custom' && !opts.multiFx) {
log('unknown transition: ' + opts.fx,'; slideshow terminating');
return false;
}
}
// fire artificial events
var e0 = $slides[first];
if (!opts.skipInitializationCallbacks) {
if (opts.before.length)
opts.before[0].apply(e0, [e0, e0, opts, true]);
if (opts.after.length)
opts.after[0].apply(e0, [e0, e0, opts, true]);
}
if (opts.next)
$(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,1);});
if (opts.prev)
$(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,0);});
if (opts.pager || opts.pagerAnchorBuilder)
buildPager(els,opts);
exposeAddSlide(opts, els);
return opts;
}
// save off original opts so we can restore after clearing state
function saveOriginalOpts(opts) {
opts.original = { before: [], after: [] };
opts.original.cssBefore = $.extend({}, opts.cssBefore);
opts.original.cssAfter = $.extend({}, opts.cssAfter);
opts.original.animIn = $.extend({}, opts.animIn);
opts.original.animOut = $.extend({}, opts.animOut);
$.each(opts.before, function() { opts.original.before.push(this); });
$.each(opts.after, function() { opts.original.after.push(this); });
}
function supportMultiTransitions(opts) {
var i, tx, txs = $.fn.cycle.transitions;
// look for multiple effects
if (opts.fx.indexOf(',') > 0) {
opts.multiFx = true;
opts.fxs = opts.fx.replace(/\s*/g,'').split(',');
// discard any bogus effect names
for (i=0; i < opts.fxs.length; i++) {
var fx = opts.fxs[i];
tx = txs[fx];
if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) {
log('discarding unknown transition: ',fx);
opts.fxs.splice(i,1);
i--;
}
}
// if we have an empty list then we threw everything away!
if (!opts.fxs.length) {
log('No valid transitions named; slideshow terminating.');
return false;
}
}
else if (opts.fx == 'all') { // auto-gen the list of transitions
opts.multiFx = true;
opts.fxs = [];
for (var p in txs) {
if (txs.hasOwnProperty(p)) {
tx = txs[p];
if (txs.hasOwnProperty(p) && $.isFunction(tx))
opts.fxs.push(p);
}
}
}
if (opts.multiFx && opts.randomizeEffects) {
// munge the fxs array to make effect selection random
var r1 = Math.floor(Math.random() * 20) + 30;
for (i = 0; i < r1; i++) {
var r2 = Math.floor(Math.random() * opts.fxs.length);
opts.fxs.push(opts.fxs.splice(r2,1)[0]);
}
debug('randomized fx sequence: ',opts.fxs);
}
return true;
}
// provide a mechanism for adding slides after the slideshow has started
function exposeAddSlide(opts, els) {
opts.addSlide = function(newSlide, prepend) {
var $s = $(newSlide), s = $s[0];
if (!opts.autostopCount)
opts.countdown++;
els[prepend?'unshift':'push'](s);
if (opts.els)
opts.els[prepend?'unshift':'push'](s); // shuffle needs this
opts.slideCount = els.length;
// add the slide to the random map and resort
if (opts.random) {
opts.randomMap.push(opts.slideCount-1);
opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
}
$s.css('position','absolute');
$s[prepend?'prependTo':'appendTo'](opts.$cont);
if (prepend) {
opts.currSlide++;
opts.nextSlide++;
}
if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
clearTypeFix($s);
if (opts.fit && opts.width)
$s.width(opts.width);
if (opts.fit && opts.height && opts.height != 'auto')
$s.height(opts.height);
s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();
$s.css(opts.cssBefore);
if (opts.pager || opts.pagerAnchorBuilder)
$.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);
if ($.isFunction(opts.onAddSlide))
opts.onAddSlide($s);
else
$s.hide(); // default behavior
};
}
// reset internal state; we do this on every pass in order to support multiple effects
$.fn.cycle.resetState = function(opts, fx) {
fx = fx || opts.fx;
opts.before = []; opts.after = [];
opts.cssBefore = $.extend({}, opts.original.cssBefore);
opts.cssAfter = $.extend({}, opts.original.cssAfter);
opts.animIn = $.extend({}, opts.original.animIn);
opts.animOut = $.extend({}, opts.original.animOut);
opts.fxFn = null;
$.each(opts.original.before, function() { opts.before.push(this); });
$.each(opts.original.after, function() { opts.after.push(this); });
// re-init
var init = $.fn.cycle.transitions[fx];
if ($.isFunction(init))
init(opts.$cont, $(opts.elements), opts);
};
// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt
function go(els, opts, manual, fwd) {
var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide];
// opts.busy is true if we're in the middle of an animation
if (manual && opts.busy && opts.manualTrump) {
// let manual transitions requests trump active ones
debug('manualTrump in go(), stopping active transition');
$(els).stop(true,true);
opts.busy = 0;
clearTimeout(p.cycleTimeout);
}
// don't begin another timeout-based transition if there is one active
if (opts.busy) {
debug('transition active, ignoring new tx request');
return;
}
// stop cycling if we have an outstanding stop request
if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual)
return;
// check to see if we should stop cycling based on autostop options
if (!manual && !p.cyclePause && !opts.bounce &&
((opts.autostop && (--opts.countdown <= 0)) ||
(opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
if (opts.end)
opts.end(opts);
return;
}
// if slideshow is paused, only transition on a manual trigger
var changed = false;
if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) {
changed = true;
var fx = opts.fx;
// keep trying to get the slide size if we don't have it yet
curr.cycleH = curr.cycleH || $(curr).height();
curr.cycleW = curr.cycleW || $(curr).width();
next.cycleH = next.cycleH || $(next).height();
next.cycleW = next.cycleW || $(next).width();
// support multiple transition types
if (opts.multiFx) {
if (fwd && (opts.lastFx === undefined || ++opts.lastFx >= opts.fxs.length))
opts.lastFx = 0;
else if (!fwd && (opts.lastFx === undefined || --opts.lastFx < 0))
opts.lastFx = opts.fxs.length - 1;
fx = opts.fxs[opts.lastFx];
}
// one-time fx overrides apply to: $('div').cycle(3,'zoom');
if (opts.oneTimeFx) {
fx = opts.oneTimeFx;
opts.oneTimeFx = null;
}
$.fn.cycle.resetState(opts, fx);
// run the before callbacks
if (opts.before.length)
$.each(opts.before, function(i,o) {
if (p.cycleStop != opts.stopCount) return;
o.apply(next, [curr, next, opts, fwd]);
});
// stage the after callacks
var after = function() {
opts.busy = 0;
$.each(opts.after, function(i,o) {
if (p.cycleStop != opts.stopCount) return;
o.apply(next, [curr, next, opts, fwd]);
});
if (!p.cycleStop) {
// queue next transition
queueNext();
}
};
debug('tx firing('+fx+'); currSlide: ' + opts.currSlide + '; nextSlide: ' + opts.nextSlide);
// get ready to perform the transition
opts.busy = 1;
if (opts.fxFn) // fx function provided?
opts.fxFn(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ?
$.fn.cycle[opts.fx](curr, next, opts, after, fwd, manual && opts.fastOnEvent);
else
$.fn.cycle.custom(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
}
else {
queueNext();
}
if (changed || opts.nextSlide == opts.currSlide) {
// calculate the next slide
var roll;
opts.lastSlide = opts.currSlide;
if (opts.random) {
opts.currSlide = opts.nextSlide;
if (++opts.randomIndex == els.length) {
opts.randomIndex = 0;
opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
}
opts.nextSlide = opts.randomMap[opts.randomIndex];
if (opts.nextSlide == opts.currSlide)
opts.nextSlide = (opts.currSlide == opts.slideCount - 1) ? 0 : opts.currSlide + 1;
}
else if (opts.backwards) {
roll = (opts.nextSlide - 1) < 0;
if (roll && opts.bounce) {
opts.backwards = !opts.backwards;
opts.nextSlide = 1;
opts.currSlide = 0;
}
else {
opts.nextSlide = roll ? (els.length-1) : opts.nextSlide-1;
opts.currSlide = roll ? 0 : opts.nextSlide+1;
}
}
else { // sequence
roll = (opts.nextSlide + 1) == els.length;
if (roll && opts.bounce) {
opts.backwards = !opts.backwards;
opts.nextSlide = els.length-2;
opts.currSlide = els.length-1;
}
else {
opts.nextSlide = roll ? 0 : opts.nextSlide+1;
opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
}
}
}
if (changed && opts.pager)
opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass);
function queueNext() {
// stage the next transition
var ms = 0, timeout = opts.timeout;
if (opts.timeout && !opts.continuous) {
ms = getTimeout(els[opts.currSlide], els[opts.nextSlide], opts, fwd);
if (opts.fx == 'shuffle')
ms -= opts.speedOut;
}
else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic
ms = 10;
if (ms > 0)
p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.backwards); }, ms);
}
}
// invoked after transition
$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) {
$(pager).each(function() {
$(this).children().removeClass(clsName).eq(currSlide).addClass(clsName);
});
};
// calculate timeout value for current transition
function getTimeout(curr, next, opts, fwd) {
if (opts.timeoutFn) {
// call user provided calc fn
var t = opts.timeoutFn.call(curr,curr,next,opts,fwd);
while (opts.fx != 'none' && (t - opts.speed) < 250) // sanitize timeout
t += opts.speed;
debug('calculated timeout: ' + t + '; speed: ' + opts.speed);
if (t !== false)
return t;
}
return opts.timeout;
}
// expose next/prev function, caller must pass in state
$.fn.cycle.next = function(opts) { advance(opts,1); };
$.fn.cycle.prev = function(opts) { advance(opts,0);};
// advance slide forward or back
function advance(opts, moveForward) {
var val = moveForward ? 1 : -1;
var els = opts.elements;
var p = opts.$cont[0], timeout = p.cycleTimeout;
if (timeout) {
clearTimeout(timeout);
p.cycleTimeout = 0;
}
if (opts.random && val < 0) {
// move back to the previously display slide
opts.randomIndex--;
if (--opts.randomIndex == -2)
opts.randomIndex = els.length-2;
else if (opts.randomIndex == -1)
opts.randomIndex = els.length-1;
opts.nextSlide = opts.randomMap[opts.randomIndex];
}
else if (opts.random) {
opts.nextSlide = opts.randomMap[opts.randomIndex];
}
else {
opts.nextSlide = opts.currSlide + val;
if (opts.nextSlide < 0) {
if (opts.nowrap) return false;
opts.nextSlide = els.length - 1;
}
else if (opts.nextSlide >= els.length) {
if (opts.nowrap) return false;
opts.nextSlide = 0;
}
}
var cb = opts.onPrevNextEvent || opts.prevNextClick; // prevNextClick is deprecated
if ($.isFunction(cb))
cb(val > 0, opts.nextSlide, els[opts.nextSlide]);
go(els, opts, 1, moveForward);
return false;
}
function buildPager(els, opts) {
var $p = $(opts.pager);
$.each(els, function(i,o) {
$.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
});
opts.updateActivePagerLink(opts.pager, opts.startingSlide, opts.activePagerClass);
}
$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
var a;
if ($.isFunction(opts.pagerAnchorBuilder)) {
a = opts.pagerAnchorBuilder(i,el);
debug('pagerAnchorBuilder('+i+', el) returned: ' + a);
}
else
a = '<a href="#">'+(i+1)+'</a>';
if (!a)
return;
var $a = $(a);
// don't reparent if anchor is in the dom
if ($a.parents('body').length === 0) {
var arr = [];
if ($p.length > 1) {
$p.each(function() {
var $clone = $a.clone(true);
$(this).append($clone);
arr.push($clone[0]);
});
$a = $(arr);
}
else {
$a.appendTo($p);
}
}
opts.pagerAnchors = opts.pagerAnchors || [];
opts.pagerAnchors.push($a);
var pagerFn = function(e) {
e.preventDefault();
opts.nextSlide = i;
var p = opts.$cont[0], timeout = p.cycleTimeout;
if (timeout) {
clearTimeout(timeout);
p.cycleTimeout = 0;
}
var cb = opts.onPagerEvent || opts.pagerClick; // pagerClick is deprecated
if ($.isFunction(cb))
cb(opts.nextSlide, els[opts.nextSlide]);
go(els,opts,1,opts.currSlide < i); // trigger the trans
// return false; // <== allow bubble
};
if ( /mouseenter|mouseover/i.test(opts.pagerEvent) ) {
$a.hover(pagerFn, function(){/* no-op */} );
}
else {
$a.bind(opts.pagerEvent, pagerFn);
}
if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble)
$a.bind('click.cycle', function(){return false;}); // suppress click
var cont = opts.$cont[0];
var pauseFlag = false; // https://github.com/malsup/cycle/issues/44
if (opts.pauseOnPagerHover) {
$a.hover(
function() {
pauseFlag = true;
cont.cyclePause++;
triggerPause(cont,true,true);
}, function() {
if (pauseFlag)
cont.cyclePause--;
triggerPause(cont,true,true);
}
);
}
};
// helper fn to calculate the number of slides between the current and the next
$.fn.cycle.hopsFromLast = function(opts, fwd) {
var hops, l = opts.lastSlide, c = opts.currSlide;
if (fwd)
hops = c > l ? c - l : opts.slideCount - l;
else
hops = c < l ? l - c : l + opts.slideCount - c;
return hops;
};
// fix clearType problems in ie6 by setting an explicit bg color
// (otherwise text slides look horrible during a fade transition)
function clearTypeFix($slides) {
debug('applying clearType background-color hack');
function hex(s) {
s = parseInt(s,10).toString(16);
return s.length < 2 ? '0'+s : s;
}
function getBg(e) {
for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
var v = $.css(e,'background-color');
if (v && v.indexOf('rgb') >= 0 ) {
var rgb = v.match(/\d+/g);
return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
if (v && v != 'transparent')
return v;
}
return '#ffffff';
}
$slides.each(function() { $(this).css('background-color', getBg(this)); });
}
// reset common props before the next transition
$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) {
$(opts.elements).not(curr).hide();
if (typeof opts.cssBefore.opacity == 'undefined')
opts.cssBefore.opacity = 1;
opts.cssBefore.display = 'block';
if (opts.slideResize && w !== false && next.cycleW > 0)
opts.cssBefore.width = next.cycleW;
if (opts.slideResize && h !== false && next.cycleH > 0)
opts.cssBefore.height = next.cycleH;
opts.cssAfter = opts.cssAfter || {};
opts.cssAfter.display = 'none';
$(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0));
$(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1));
};
// the actual fn for effecting a transition
$.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) {
var $l = $(curr), $n = $(next);
var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut, animInDelay = opts.animInDelay, animOutDelay = opts.animOutDelay;
$n.css(opts.cssBefore);
if (speedOverride) {
if (typeof speedOverride == 'number')
speedIn = speedOut = speedOverride;
else
speedIn = speedOut = 1;
easeIn = easeOut = null;
}
var fn = function() {
$n.delay(animInDelay).animate(opts.animIn, speedIn, easeIn, function() {
cb();
});
};
$l.delay(animOutDelay).animate(opts.animOut, speedOut, easeOut, function() {
$l.css(opts.cssAfter);
if (!opts.sync)
fn();
});
if (opts.sync) fn();
};
// transition definitions - only fade is defined here, transition pack defines the rest
$.fn.cycle.transitions = {
fade: function($cont, $slides, opts) {
$slides.not(':eq('+opts.currSlide+')').css('opacity',0);
opts.before.push(function(curr,next,opts) {
$.fn.cycle.commonReset(curr,next,opts);
opts.cssBefore.opacity = 0;
});
opts.animIn = { opacity: 1 };
opts.animOut = { opacity: 0 };
opts.cssBefore = { top: 0, left: 0 };
}
};
$.fn.cycle.ver = function() { return ver; };
// override these globally if you like (they are all optional)
$.fn.cycle.defaults = {
activePagerClass: 'activeSlide', // class name used for the active pager link
after: null, // transition callback (scope set to element that was shown): function(currSlideElement, nextSlideElement, options, forwardFlag)
allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling
animIn: null, // properties that define how the slide animates in
animInDelay: 0, // allows delay before next slide transitions in
animOut: null, // properties that define how the slide animates out
animOutDelay: 0, // allows delay before current slide transitions out
aspect: false, // preserve aspect ratio during fit resizing, cropping if necessary (must be used with fit option)
autostop: 0, // true to end slideshow after X transitions (where X == slide count)
autostopCount: 0, // number of transitions (optionally used with autostop to define X)
backwards: false, // true to start slideshow at last slide and move backwards through the stack
before: null, // transition callback (scope set to element to be shown): function(currSlideElement, nextSlideElement, options, forwardFlag)
center: null, // set to true to have cycle add top/left margin to each slide (use with width and height options)
cleartype: !$.support.opacity, // true if clearType corrections should be applied (for IE)
cleartypeNoBg: false, // set to true to disable extra cleartype fixing (leave false to force background color setting on slides)
containerResize: 1, // resize container to fit largest slide
containerResizeHeight: 0, // resize containers height to fit the largest slide but leave the width dynamic
continuous: 0, // true to start next transition immediately after current one completes
cssAfter: null, // properties that defined the state of the slide after transitioning out
cssBefore: null, // properties that define the initial state of the slide before transitioning in
delay: 0, // additional delay (in ms) for first transition (hint: can be negative)
easeIn: null, // easing for "in" transition
easeOut: null, // easing for "out" transition
easing: null, // easing method for both in and out transitions
end: null, // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options)
fastOnEvent: 0, // force fast transitions when triggered manually (via pager or prev/next); value == time in ms
fit: 0, // force slides to fit container
fx: 'fade', // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle')
fxFn: null, // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag)
height: 'auto', // container height (if the 'fit' option is true, the slides will be set to this height as well)
manualTrump: true, // causes manual transition to stop an active transition instead of being ignored
metaAttr: 'cycle', // data- attribute that holds the option data for the slideshow
next: null, // element, jQuery object, or jQuery selector string for the element to use as event trigger for next slide
nowrap: 0, // true to prevent slideshow from wrapping
onPagerEvent: null, // callback fn for pager events: function(zeroBasedSlideIndex, slideElement)
onPrevNextEvent: null, // callback fn for prev/next events: function(isNext, zeroBasedSlideIndex, slideElement)
pager: null, // element, jQuery object, or jQuery selector string for the element to use as pager container
pagerAnchorBuilder: null, // callback fn for building anchor links: function(index, DOMelement)
pagerEvent: 'click.cycle', // name of event which drives the pager navigation
pause: 0, // true to enable "pause on hover"
pauseOnPagerHover: 0, // true to pause when hovering over pager link
prev: null, // element, jQuery object, or jQuery selector string for the element to use as event trigger for previous slide
prevNextEvent: 'click.cycle',// event which drives the manual transition to the previous or next slide
random: 0, // true for random, false for sequence (not applicable to shuffle fx)
randomizeEffects: 1, // valid when multiple effects are used; true to make the effect sequence random
requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded
requeueTimeout: 250, // ms delay for requeue
rev: 0, // causes animations to transition in reverse (for effects that support it such as scrollHorz/scrollVert/shuffle)
shuffle: null, // coords for shuffle animation, ex: { top:15, left: 200 }
skipInitializationCallbacks: false, // set to true to disable the first before/after callback that occurs prior to any transition
slideExpr: null, // expression for selecting slides (if something other than all children is required)
slideResize: 1, // force slide width/height to fixed size before every transition
speed: 1000, // speed of the transition (any valid fx speed value)
speedIn: null, // speed of the 'in' transition
speedOut: null, // speed of the 'out' transition
startingSlide: undefined,// zero-based index of the first slide to be displayed
sync: 1, // true if in/out transitions should occur simultaneously
timeout: 4000, // milliseconds between slide transitions (0 to disable auto advance)
timeoutFn: null, // callback for determining per-slide timeout value: function(currSlideElement, nextSlideElement, options, forwardFlag)
updateActivePagerLink: null,// callback fn invoked to update the active pager link (adds/removes activePagerClass style)
width: null // container width (if the 'fit' option is true, the slides will be set to this width as well)
};
})(jQuery);
/*!
* jQuery Cycle Plugin Transition Definitions
* This script is a plugin for the jQuery Cycle Plugin
* Examples and documentation at: http://malsup.com/jquery/cycle/
* Copyright (c) 2007-2010 M. Alsup
* Version: 2.73
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function($) {
"use strict";
//
// These functions define slide initialization and properties for the named
// transitions. To save file size feel free to remove any of these that you
// don't need.
//
$.fn.cycle.transitions.none = function($cont, $slides, opts) {
opts.fxFn = function(curr,next,opts,after){
$(next).show();
$(curr).hide();
after();
};
};
// not a cross-fade, fadeout only fades out the top slide
$.fn.cycle.transitions.fadeout = function($cont, $slides, opts) {
$slides.not(':eq('+opts.currSlide+')').css({ display: 'block', 'opacity': 1 });
opts.before.push(function(curr,next,opts,w,h,rev) {
$(curr).css('zIndex',opts.slideCount + (rev !== true ? 1 : 0));
$(next).css('zIndex',opts.slideCount + (rev !== true ? 0 : 1));
});
opts.animIn.opacity = 1;
opts.animOut.opacity = 0;
opts.cssBefore.opacity = 1;
opts.cssBefore.display = 'block';
opts.cssAfter.zIndex = 0;
};
// scrollUp/Down/Left/Right
$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
$cont.css('overflow','hidden');
opts.before.push($.fn.cycle.commonReset);
var h = $cont.height();
opts.cssBefore.top = h;
opts.cssBefore.left = 0;
opts.cssFirst.top = 0;
opts.animIn.top = 0;
opts.animOut.top = -h;
};
$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
$cont.css('overflow','hidden');
opts.before.push($.fn.cycle.commonReset);
var h = $cont.height();
opts.cssFirst.top = 0;
opts.cssBefore.top = -h;
opts.cssBefore.left = 0;
opts.animIn.top = 0;
opts.animOut.top = h;
};
$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
$cont.css('overflow','hidden');
opts.before.push($.fn.cycle.commonReset);
var w = $cont.width();
opts.cssFirst.left = 0;
opts.cssBefore.left = w;
opts.cssBefore.top = 0;
opts.animIn.left = 0;
opts.animOut.left = 0-w;
};
$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
$cont.css('overflow','hidden');
opts.before.push($.fn.cycle.commonReset);
var w = $cont.width();
opts.cssFirst.left = 0;
opts.cssBefore.left = -w;
opts.cssBefore.top = 0;
opts.animIn.left = 0;
opts.animOut.left = w;
};
$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
$cont.css('overflow','hidden').width();
opts.before.push(function(curr, next, opts, fwd) {
if (opts.rev)
fwd = !fwd;
$.fn.cycle.commonReset(curr,next,opts);
opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW);
opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW;
});
opts.cssFirst.left = 0;
opts.cssBefore.top = 0;
opts.animIn.left = 0;
opts.animOut.top = 0;
};
$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
$cont.css('overflow','hidden');
opts.before.push(function(curr, next, opts, fwd) {
if (opts.rev)
fwd = !fwd;
$.fn.cycle.commonReset(curr,next,opts);
opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1);
opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH;
});
opts.cssFirst.top = 0;
opts.cssBefore.left = 0;
opts.animIn.top = 0;
opts.animOut.left = 0;
};
// slideX/slideY
$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$(opts.elements).not(curr).hide();
$.fn.cycle.commonReset(curr,next,opts,false,true);
opts.animIn.width = next.cycleW;
});
opts.cssBefore.left = 0;
opts.cssBefore.top = 0;
opts.cssBefore.width = 0;
opts.animIn.width = 'show';
opts.animOut.width = 0;
};
$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$(opts.elements).not(curr).hide();
$.fn.cycle.commonReset(curr,next,opts,true,false);
opts.animIn.height = next.cycleH;
});
opts.cssBefore.left = 0;
opts.cssBefore.top = 0;
opts.cssBefore.height = 0;
opts.animIn.height = 'show';
opts.animOut.height = 0;
};
// shuffle
$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
var i, w = $cont.css('overflow', 'visible').width();
$slides.css({left: 0, top: 0});
opts.before.push(function(curr,next,opts) {
$.fn.cycle.commonReset(curr,next,opts,true,true,true);
});
// only adjust speed once!
if (!opts.speedAdjusted) {
opts.speed = opts.speed / 2; // shuffle has 2 transitions
opts.speedAdjusted = true;
}
opts.random = 0;
opts.shuffle = opts.shuffle || {left:-w, top:15};
opts.els = [];
for (i=0; i < $slides.length; i++)
opts.els.push($slides[i]);
for (i=0; i < opts.currSlide; i++)
opts.els.push(opts.els.shift());
// custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
opts.fxFn = function(curr, next, opts, cb, fwd) {
if (opts.rev)
fwd = !fwd;
var $el = fwd ? $(curr) : $(next);
$(next).css(opts.cssBefore);
var count = opts.slideCount;
$el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
var hops = $.fn.cycle.hopsFromLast(opts, fwd);
for (var k=0; k < hops; k++) {
if (fwd)
opts.els.push(opts.els.shift());
else
opts.els.unshift(opts.els.pop());
}
if (fwd) {
for (var i=0, len=opts.els.length; i < len; i++)
$(opts.els[i]).css('z-index', len-i+count);
}
else {
var z = $(curr).css('z-index');
$el.css('z-index', parseInt(z,10)+1+count);
}
$el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
$(fwd ? this : curr).hide();
if (cb) cb();
});
});
};
$.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
};
// turnUp/Down/Left/Right
$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,true,false);
opts.cssBefore.top = next.cycleH;
opts.animIn.height = next.cycleH;
opts.animOut.width = next.cycleW;
});
opts.cssFirst.top = 0;
opts.cssBefore.left = 0;
opts.cssBefore.height = 0;
opts.animIn.top = 0;
opts.animOut.height = 0;
};
$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,true,false);
opts.animIn.height = next.cycleH;
opts.animOut.top = curr.cycleH;
});
opts.cssFirst.top = 0;
opts.cssBefore.left = 0;
opts.cssBefore.top = 0;
opts.cssBefore.height = 0;
opts.animOut.height = 0;
};
$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,false,true);
opts.cssBefore.left = next.cycleW;
opts.animIn.width = next.cycleW;
});
opts.cssBefore.top = 0;
opts.cssBefore.width = 0;
opts.animIn.left = 0;
opts.animOut.width = 0;
};
$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,false,true);
opts.animIn.width = next.cycleW;
opts.animOut.left = curr.cycleW;
});
$.extend(opts.cssBefore, { top: 0, left: 0, width: 0 });
opts.animIn.left = 0;
opts.animOut.width = 0;
};
// zoom
$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,false,false,true);
opts.cssBefore.top = next.cycleH/2;
opts.cssBefore.left = next.cycleW/2;
$.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
$.extend(opts.animOut, { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 });
});
opts.cssFirst.top = 0;
opts.cssFirst.left = 0;
opts.cssBefore.width = 0;
opts.cssBefore.height = 0;
};
// fadeZoom
$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,false,false);
opts.cssBefore.left = next.cycleW/2;
opts.cssBefore.top = next.cycleH/2;
$.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
});
opts.cssBefore.width = 0;
opts.cssBefore.height = 0;
opts.animOut.opacity = 0;
};
// blindX
$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
var w = $cont.css('overflow','hidden').width();
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts);
opts.animIn.width = next.cycleW;
opts.animOut.left = curr.cycleW;
});
opts.cssBefore.left = w;
opts.cssBefore.top = 0;
opts.animIn.left = 0;
opts.animOut.left = w;
};
// blindY
$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
var h = $cont.css('overflow','hidden').height();
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts);
opts.animIn.height = next.cycleH;
opts.animOut.top = curr.cycleH;
});
opts.cssBefore.top = h;
opts.cssBefore.left = 0;
opts.animIn.top = 0;
opts.animOut.top = h;
};
// blindZ
$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
var h = $cont.css('overflow','hidden').height();
var w = $cont.width();
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts);
opts.animIn.height = next.cycleH;
opts.animOut.top = curr.cycleH;
});
opts.cssBefore.top = h;
opts.cssBefore.left = w;
opts.animIn.top = 0;
opts.animIn.left = 0;
opts.animOut.top = h;
opts.animOut.left = w;
};
// growX - grow horizontally from centered 0 width
$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,false,true);
opts.cssBefore.left = this.cycleW/2;
opts.animIn.left = 0;
opts.animIn.width = this.cycleW;
opts.animOut.left = 0;
});
opts.cssBefore.top = 0;
opts.cssBefore.width = 0;
};
// growY - grow vertically from centered 0 height
$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,true,false);
opts.cssBefore.top = this.cycleH/2;
opts.animIn.top = 0;
opts.animIn.height = this.cycleH;
opts.animOut.top = 0;
});
opts.cssBefore.height = 0;
opts.cssBefore.left = 0;
};
// curtainX - squeeze in both edges horizontally
$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,false,true,true);
opts.cssBefore.left = next.cycleW/2;
opts.animIn.left = 0;
opts.animIn.width = this.cycleW;
opts.animOut.left = curr.cycleW/2;
opts.animOut.width = 0;
});
opts.cssBefore.top = 0;
opts.cssBefore.width = 0;
};
// curtainY - squeeze in both edges vertically
$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,true,false,true);
opts.cssBefore.top = next.cycleH/2;
opts.animIn.top = 0;
opts.animIn.height = next.cycleH;
opts.animOut.top = curr.cycleH/2;
opts.animOut.height = 0;
});
opts.cssBefore.height = 0;
opts.cssBefore.left = 0;
};
// cover - curr slide covered by next slide
$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
var d = opts.direction || 'left';
var w = $cont.css('overflow','hidden').width();
var h = $cont.height();
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts);
opts.cssAfter.display = '';
if (d == 'right')
opts.cssBefore.left = -w;
else if (d == 'up')
opts.cssBefore.top = h;
else if (d == 'down')
opts.cssBefore.top = -h;
else
opts.cssBefore.left = w;
});
opts.animIn.left = 0;
opts.animIn.top = 0;
opts.cssBefore.top = 0;
opts.cssBefore.left = 0;
};
// uncover - curr slide moves off next slide
$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
var d = opts.direction || 'left';
var w = $cont.css('overflow','hidden').width();
var h = $cont.height();
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,true,true,true);
if (d == 'right')
opts.animOut.left = w;
else if (d == 'up')
opts.animOut.top = -h;
else if (d == 'down')
opts.animOut.top = h;
else
opts.animOut.left = -w;
});
opts.animIn.left = 0;
opts.animIn.top = 0;
opts.cssBefore.top = 0;
opts.cssBefore.left = 0;
};
// toss - move top slide and fade away
$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
var w = $cont.css('overflow','visible').width();
var h = $cont.height();
opts.before.push(function(curr, next, opts) {
$.fn.cycle.commonReset(curr,next,opts,true,true,true);
// provide default toss settings if animOut not provided
if (!opts.animOut.left && !opts.animOut.top)
$.extend(opts.animOut, { left: w*2, top: -h/2, opacity: 0 });
else
opts.animOut.opacity = 0;
});
opts.cssBefore.left = 0;
opts.cssBefore.top = 0;
opts.animIn.left = 0;
};
// wipe - clip animation
$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
var w = $cont.css('overflow','hidden').width();
var h = $cont.height();
opts.cssBefore = opts.cssBefore || {};
var clip;
if (opts.clip) {
if (/l2r/.test(opts.clip))
clip = 'rect(0px 0px '+h+'px 0px)';
else if (/r2l/.test(opts.clip))
clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
else if (/t2b/.test(opts.clip))
clip = 'rect(0px '+w+'px 0px 0px)';
else if (/b2t/.test(opts.clip))
clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
else if (/zoom/.test(opts.clip)) {
var top = parseInt(h/2,10);
var left = parseInt(w/2,10);
clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)';
}
}
opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';
var d = opts.cssBefore.clip.match(/(\d+)/g);
var t = parseInt(d[0],10), r = parseInt(d[1],10), b = parseInt(d[2],10), l = parseInt(d[3],10);
opts.before.push(function(curr, next, opts) {
if (curr == next) return;
var $curr = $(curr), $next = $(next);
$.fn.cycle.commonReset(curr,next,opts,true,true,false);
opts.cssAfter.display = 'block';
var step = 1, count = parseInt((opts.speedIn / 13),10) - 1;
(function f() {
var tt = t ? t - parseInt(step * (t/count),10) : 0;
var ll = l ? l - parseInt(step * (l/count),10) : 0;
var bb = b < h ? b + parseInt(step * ((h-b)/count || 1),10) : h;
var rr = r < w ? r + parseInt(step * ((w-r)/count || 1),10) : w;
$next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
(step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
})();
});
$.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
opts.animIn = { left: 0 };
opts.animOut = { left: 0 };
};
})(jQuery);
/*!
* jQuery Cycle Lite Plugin
* http://malsup.com/jquery/cycle/lite/
* Copyright (c) 2008-2012 M. Alsup
* Version: 1.7 (20-FEB-2013)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
* Requires: jQuery v1.3.2 or later
*/
;(function($) {
"use strict";
var ver = 'Lite-1.7';
var msie = /MSIE/.test(navigator.userAgent);
$.fn.cycle = function(options) {
return this.each(function() {
options = options || {};
if (this.cycleTimeout)
clearTimeout(this.cycleTimeout);
this.cycleTimeout = 0;
this.cyclePause = 0;
var $cont = $(this);
var $slides = options.slideExpr ? $(options.slideExpr, this) : $cont.children();
var els = $slides.get();
if (els.length < 2) {
if (window.console)
console.log('terminating; too few slides: ' + els.length);
return; // don't bother
}
// support metadata plugin (v1.0 and v2.0)
var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null;
if (meta)
opts = $.extend(opts, meta);
opts.before = opts.before ? [opts.before] : [];
opts.after = opts.after ? [opts.after] : [];
opts.after.unshift(function(){ opts.busy=0; });
// allow shorthand overrides of width, height and timeout
var cls = this.className;
opts.width = parseInt((cls.match(/w:(\d+)/)||[])[1], 10) || opts.width;
opts.height = parseInt((cls.match(/h:(\d+)/)||[])[1], 10) || opts.height;
opts.timeout = parseInt((cls.match(/t:(\d+)/)||[])[1], 10) || opts.timeout;
if ($cont.css('position') == 'static')
$cont.css('position', 'relative');
if (opts.width)
$cont.width(opts.width);
if (opts.height && opts.height != 'auto')
$cont.height(opts.height);
var first = 0;
$slides.css({position: 'absolute', top:0}).each(function(i) {
$(this).css('z-index', els.length-i);
});
$(els[first]).css('opacity',1).show(); // opacity bit needed to handle reinit case
if (msie)
els[first].style.removeAttribute('filter');
if (opts.fit && opts.width)
$slides.width(opts.width);
if (opts.fit && opts.height && opts.height != 'auto')
$slides.height(opts.height);
if (opts.pause)
$cont.hover(function(){this.cyclePause=1;}, function(){this.cyclePause=0;});
var txFn = $.fn.cycle.transitions[opts.fx];
if (txFn)
txFn($cont, $slides, opts);
$slides.each(function() {
var $el = $(this);
this.cycleH = (opts.fit && opts.height) ? opts.height : $el.height();
this.cycleW = (opts.fit && opts.width) ? opts.width : $el.width();
});
if (opts.cssFirst)
$($slides[first]).css(opts.cssFirst);
if (opts.timeout) {
// ensure that timeout and speed settings are sane
if (opts.speed.constructor == String)
opts.speed = {slow: 600, fast: 200}[opts.speed] || 400;
if (!opts.sync)
opts.speed = opts.speed / 2;
while((opts.timeout - opts.speed) < 250)
opts.timeout += opts.speed;
}
opts.speedIn = opts.speed;
opts.speedOut = opts.speed;
opts.slideCount = els.length;
opts.currSlide = first;
opts.nextSlide = 1;
// fire artificial events
var e0 = $slides[first];
if (opts.before.length)
opts.before[0].apply(e0, [e0, e0, opts, true]);
if (opts.after.length > 1)
opts.after[1].apply(e0, [e0, e0, opts, true]);
if (opts.click && !opts.next)
opts.next = opts.click;
if (opts.next)
$(opts.next).unbind('click.cycle').bind('click.cycle', function(){return advance(els,opts,opts.rev?-1:1);});
if (opts.prev)
$(opts.prev).unbind('click.cycle').bind('click.cycle', function(){return advance(els,opts,opts.rev?1:-1);});
if (opts.timeout)
this.cycleTimeout = setTimeout(function() {
go(els,opts,0,!opts.rev);
}, opts.timeout + (opts.delay||0));
});
};
function go(els, opts, manual, fwd) {
if (opts.busy)
return;
var p = els[0].parentNode, curr = els[opts.currSlide], next = els[opts.nextSlide];
if (p.cycleTimeout === 0 && !manual)
return;
if (manual || !p.cyclePause) {
if (opts.before.length)
$.each(opts.before, function(i,o) { o.apply(next, [curr, next, opts, fwd]); });
var after = function() {
if (msie)
this.style.removeAttribute('filter');
$.each(opts.after, function(i,o) { o.apply(next, [curr, next, opts, fwd]); });
queueNext(opts);
};
if (opts.nextSlide != opts.currSlide) {
opts.busy = 1;
$.fn.cycle.custom(curr, next, opts, after);
}
var roll = (opts.nextSlide + 1) == els.length;
opts.nextSlide = roll ? 0 : opts.nextSlide+1;
opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
} else {
queueNext(opts);
}
function queueNext(opts) {
if (opts.timeout)
p.cycleTimeout = setTimeout(function() { go(els,opts,0,!opts.rev); }, opts.timeout);
}
}
// advance slide forward or back
function advance(els, opts, val) {
var p = els[0].parentNode, timeout = p.cycleTimeout;
if (timeout) {
clearTimeout(timeout);
p.cycleTimeout = 0;
}
opts.nextSlide = opts.currSlide + val;
if (opts.nextSlide < 0) {
opts.nextSlide = els.length - 1;
}
else if (opts.nextSlide >= els.length) {
opts.nextSlide = 0;
}
go(els, opts, 1, val>=0);
return false;
}
$.fn.cycle.custom = function(curr, next, opts, cb) {
var $l = $(curr), $n = $(next);
$n.css(opts.cssBefore);
var fn = function() {$n.animate(opts.animIn, opts.speedIn, opts.easeIn, cb);};
$l.animate(opts.animOut, opts.speedOut, opts.easeOut, function() {
$l.css(opts.cssAfter);
if (!opts.sync)
fn();
});
if (opts.sync)
fn();
};
$.fn.cycle.transitions = {
fade: function($cont, $slides, opts) {
$slides.not(':eq(0)').hide();
opts.cssBefore = { opacity: 0, display: 'block' };
opts.cssAfter = { display: 'none' };
opts.animOut = { opacity: 0 };
opts.animIn = { opacity: 1 };
},
fadeout: function($cont, $slides, opts) {
opts.before.push(function(curr,next,opts,fwd) {
$(curr).css('zIndex',opts.slideCount + (fwd === true ? 1 : 0));
$(next).css('zIndex',opts.slideCount + (fwd === true ? 0 : 1));
});
$slides.not(':eq(0)').hide();
opts.cssBefore = { opacity: 1, display: 'block', zIndex: 1 };
opts.cssAfter = { display: 'none', zIndex: 0 };
opts.animOut = { opacity: 0 };
opts.animIn = { opacity: 1 };
}
};
$.fn.cycle.ver = function() { return ver; };
// @see: http://malsup.com/jquery/cycle/lite/
$.fn.cycle.defaults = {
animIn: {},
animOut: {},
fx: 'fade',
after: null,
before: null,
cssBefore: {},
cssAfter: {},
delay: 0,
fit: 0,
height: 'auto',
metaAttr: 'cycle',
next: null,
pause: false,
prev: null,
speed: 1000,
slideExpr: null,
sync: true,
timeout: 4000
};
})(jQuery);
hoverIntent jQuery Plug-in
==========================
hoverIntent is a plug-in that attempts to determine the user's intent... like a crystal ball, only with mouse movement! It is similar to [jQuery's hover method](http://api.jquery.com/hover/). However, instead of calling the handlerIn function immediately, hoverIntent waits until the user's mouse slows down enough before making the call.
Why? To delay or prevent the accidental firing of animations or ajax calls. Simple timeouts work for small areas, but if your target area is large it may execute regardless of intent. That's where hoverIntent comes in...
For more information, visit [briancherne.github.io/jquery-hoverIntent](//briancherne.github.io/jquery-hoverIntent/).
{
"name": "jquery-hoverintent",
"version": "1.9.0",
"homepage": "http://briancherne.github.io/jquery-hoverIntent/",
"repository": {
"type": "git",
"url": "https://github.com/briancherne/jquery-hoverIntent"
},
"authors": [
"Brian Cherne <brian@cherne.net>"
],
"description": "A jQuery plug-in that attempts to determine the user's intent on mouseover. To delay or prevent the accidental firing of callbacks.",
"main": "jquery.hoverIntent.js",
"keywords": [
"delay",
"hover",
"hoverintent",
"intent",
"jquery",
"mouseover",
"plugin"
],
"license": "MIT",
"dependencies": {
"jquery": ">=1.7.0"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>hoverIntent jQuery Plugin</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=IE8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- TODO: move scripts to bottom, styles to external file. -UA -->
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="./jquery.hoverIntent.js"></script>
<!-- LAYOUT CSS // NOT REQUIRED for hoverIntent, just for prettification -->
<style type="text/css" media="screen">
body {background:#fff; font-family:sans-serif; font-size:.9em; color:#000; margin:0; padding:1em; line-height:1.3em; max-width:55em;}
h2 {width:100%; border-bottom:#cc9 1px solid; margin:0 0 .5em 0; padding:1em 0 0 0; font-size:1.2em;}
h3 {display:block; margin:0; padding:0 0 1px 0; font-size:1em; font-weight:bold;}
p {margin:0; padding:0 0 1em 0; clear:both;}
pre {background:#eee; color:#666; padding:.8em; margin:0; font-size:.9em; font-family:sans-serif; overflow:auto;}
a {color:#787850; text-decoration:underline;}
a:hover {text-decoration:none;}
ul {margin:0; padding:0 0 0 1em; clear:both;}
ul li {margin:0; padding:0 0 1em .2em;}
</style>
<!-- DEMO CSS // NOT REQUIRED for hoverIntent to work, just for demo purposes -->
<style type="text/css" media="screen">
ul.demo {display:block; width:100%; height:75px; padding:0; margin:0; background:#9cc; list-style-type:none;}
ul.demo li {background:#fcc; display:block; width:25%; height:50px; padding:0; margin:0; float:left; position:relative; overflow:hidden; cursor:default; font-size:0.9em; line-height:1.1em;}
ul.demo li.p2 {background:#ffc;}
ul.demo li.p3 {background:#cfc;}
ul.demo li.p4 {background:#ccf;}
ul.demo li span { display:block; margin:4px; background:#eef; cursor:default;}
</style>
<!-- DEMO JS -->
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
$("#demo1 li").hover(makeTall,makeShort);
$("#demo2 li").hoverIntent(makeTall,makeShort);
$("#demo3 li").hoverIntent(toggleHeight);
$("#demo4").hoverIntent(makeTall,makeShort,'li');
$("#demo5").hoverIntent(toggleHeight,'li');
$("#demo6").hoverIntent({
over: makeTall,
out: makeShort,
selector: 'li'
});
}); // close document.ready
function makeTall(){$(this).animate({"height":75},200);}
function makeShort(){$(this).animate({"height":50},200);}
function toggleHeight(e){var h=(e.type==="mouseenter") ? 75 : 50; $(this).stop().animate({"height":h},200);}
</script>
</head>
<body>
<h1>hoverIntent jQuery Plugin</h1>
<h2>What is hoverIntent?</h2>
<p>hoverIntent is a plug-in that attempts to determine the user's intent... like a crystal ball, only with mouse movement! It is similar to <a href="http://api.jquery.com/hover/">jQuery's hover method</a>. However, instead of calling the handlerIn function immediately, hoverIntent waits until the user's mouse slows down enough before making the call.</p>
<p>Why? To delay or prevent the accidental firing of animations or ajax calls. Simple timeouts work for small areas, but if your target area is large it may execute regardless of intent. That's where hoverIntent comes in...</p>
<p style="text-align:center;"><a href="https://github.com/briancherne/jquery-hoverIntent">https://github.com/briancherne/jquery-hoverIntent</a></p>
<h2>Examples</h2>
<noscript><p style="background:yellow;padding:1em;margin:1em;"><em>WARNING: If you can see this message <strong>JavaScript is disabled</strong>. This plug-in requires JavaScript to be enabled in order for the examples to work. (This is really a note to myself so the next time I look at this page with JavaScript accidentally turned off I don't freak out and wonder why it's not working)</em></p></noscript>
<h3>jQuery's .hover() ... for reference</h3>
<pre>$("#demo1 li").hover( makeTall, makeShort );</pre>
<ul class="demo" id="demo1">
<li class="p1">&nbsp;</li>
<li class="p2">&nbsp;</li>
<li class="p3">&nbsp;</li>
<li class="p4"><span>hover ignores over/out events from children</span></li>
</ul>
<p>jQuery's built-in hover calls handlerIn and handlerOut functions immediately. If you move your cursor back and forth quickly across the tiles you'll see how the immediate execution can lead to problems.</p>
<h3>.hoverIntent( handlerIn, handlerOut )</h3>
<pre>$("#demo2 li").hoverIntent( makeTall, makeShort );</pre>
<ul class="demo" id="demo2">
<li class="p1">&nbsp;</li>
<li class="p2">&nbsp;</li>
<li class="p3">&nbsp;</li>
<li class="p4"><span>hoverIntent also ignores over/out events from children</span></li>
</ul>
<p>hoverIntent is interchangeable with jQuery's hover. It can use the same exact handlerIn and handlerOut functions. It passes the same <strong>this</strong> and <strong>event</strong> objects to those functions.</p>
<h3>.hoverIntent( handlerInOut )</h3>
<pre>$("#demo3 li").hoverIntent( toggleHeight );</pre>
<ul class="demo" id="demo3">
<li class="p1">&nbsp;</li>
<li class="p2">&nbsp;</li>
<li class="p3">&nbsp;</li>
<li class="p4">&nbsp;</li>
</ul>
<p>hoverIntent can also take a single handlerInOut, just like jQuery's hover.</p>
<h3>.hoverIntent( handlerIn, handlerOut, selector )</h3>
<pre>$("#demo4").hoverIntent( makeTall, makeShort, 'li' );</pre>
<ul class="demo" id="demo4">
<li class="p1">&nbsp;</li>
<li class="p2">&nbsp;</li>
<li class="p3">&nbsp;</li>
<li class="p4">&nbsp;</li>
</ul>
<p>Unlike jQuery's hover, hoverIntent supports event delegation! Just pass in a selector of a descendant element.</p>
<h3>.hoverIntent( handlerInOut, selector )</h3>
<pre>$("#demo5").hoverIntent( toggleHeight, 'li' );</pre>
<ul class="demo" id="demo5">
<li class="p1">&nbsp;</li>
<li class="p2">&nbsp;</li>
<li class="p3">&nbsp;</li>
<li class="p4">&nbsp;</li>
</ul>
<p>Unlike jQuery's hover, hoverIntent supports event delegation with handlerInOut.</p>
<h3>.hoverIntent( object )</h3>
<pre>
$("#demo6").hoverIntent({
over: makeTall,
out: makeShort,
selector: 'li'
});
</pre>
<ul class="demo" id="demo6">
<li class="p1">&nbsp;</li>
<li class="p2">&nbsp;</li>
<li class="p3">&nbsp;</li>
<li class="p4">&nbsp;</li>
</ul>
<p>To control hoverIntent more precisely and override the default configuration options, pass it an object as the first parameter. The object must at least contain an "over" function. If the "over" function is sent alone, it will act just like handlerInOut.</p>
<h2>Common Configuration Options</h2>
<p>These are the common options you'll want to use. Note, nothing prevents you from sending <a href="http://api.jquery.com/jQuery.noop/">an empty function</a> as the handlerIn or handlerOut functions.</p>
<h3>over:</h3>
<p>Required. The handlerIn function you'd like to call on "mouseenter with intent". Your function receives the same "this" and "event" objects as it would from jQuery's hover method. If the "over" function is sent alone (without "out") then it will be used in both cases like the handlerInOut param.</p>
<h3>out:</h3>
<p>The handlerOut function you'd like to call on "mouseleave after timeout". Your function receives the same "this" and "event" objects as it would from jQuery's hover method. Note, hoverIntent will only call the "out" function if the "over" function has been called.</p>
<h3>timeout:</h3>
<p>A simple delay, in milliseconds, before the "out" function is called. If the user mouses back over the element before the timeout has expired the "out" function will not be called (nor will the "over" function be called). This is primarily to protect against sloppy/human mousing trajectories that temporarily (and unintentionally) take the user off of the target element... giving them time to return. <em>Default timeout: 0</em></p>
<h3>selector:</h3>
<p>A selector string for event delegation. Used to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element. Read <a href="http://api.jquery.com/on/#direct-and-delegated-events">jQuery's API Documentation for the .on() method</a> for more information.</p>
<h2>Advanced Configuration Options</h2>
<p><strong style="color:#600">Modify these only if you are brave, test tirelessly, and completely understand what you are doing.</strong> When choosing the default settings for hoverIntent I tried to find the best possible balance between responsiveness and frequency of false positives.</p>
<h3 style="color:#600">sensitivity:</h3>
<p>If the mouse travels fewer than this number of pixels between polling intervals, then the "over" function will be called. With the minimum sensitivity threshold of 1, the mouse must not move between polling intervals. With higher sensitivity thresholds you are more likely to receive a false positive. Note that hoverIntent r7 and earlier perform this comparison using rectilinear distance, whereas more recent versions compare against Euclidean (straight-line) distance for better accuracy and intuition. If you are upgrading from an older version, you may want to verify that the desired behavior is preserved. <em>Default sensitivity: 6</em></p>
<h3 style="color:#600">interval:</h3>
<p>The number of milliseconds hoverIntent waits between reading/comparing mouse coordinates. When the user's mouse first enters the element its coordinates are recorded. The soonest the "over" function can be called is after a single polling interval. Setting the polling interval higher will increase the delay before the first possible "over" call, but also increases the time to the next point of comparison. <em>Default interval: 100</em></p>
<h2>Known Defects</h2>
<p>hoverIntent r5 suffers from <a href="http://code.google.com/p/chromium/issues/detail?id=68629">a defect in Google Chrome that improperly triggers mouseout when entering a child input[type="text"] element</a>. hoverIntent r6 uses the same mouseenter/mouseleave special events as jQuery's built-in hover, and jQuery 1.5.1 patched this issue. Thanks to Colin Stuart for tipping me off about this and for providing isolated code to demonstrate/test.</p>
<p id="chrome9defect" style="background:#eee;margin-bottom:1em;">This page uses a modern version of jQuery and hoverIntent, so when your cursor goes over the text input nothing should change (it should continue to read "enter parent" because you are still over this grey paragraph). <br/><input type="text" value=""/><br/> However, if you were using Google Chrome and if this page were using jQuery 1.5 (or earlier) and hoverIntent r5 (or earlier), moving the cursor over the text input would improperly trigger the mouseout event, and the value would change to "leave parent".</p>
<script type="text/javascript">
function enter(e){$("input", e.target).val("enter parent");}
function leave(e){$("input", e.target).val("leave parent");}
$("#chrome9defect").hoverIntent(enter,leave);
</script>
<p>If you place an element flush against the edge of the browser chrome, sometimes Internet Explorer does not trigger a "mouseleave" event if your cursor leaves the element/browser in that direction. hoverIntent cannot correct for this.</p>
<h2>Release History</h2>
<ul>
<li><a href="https://github.com/briancherne/jquery-hoverIntent/releases">All newer releases</a></li>
<li>v1.9.0 = (2015, 2017) Refactored plugin to fix a long-standing bug that prevented multiple instances of the plugin to be active on the same element. Exports plugin as an <a href="http://requirejs.org/docs/whyamd.html">AMD</a> module so it can be used with AMD loaders. The <code>pageX</code> and <code>pageY</code> properties of the event passed to the "over" handler now reflect current mouse position. <em>Note that this may be a breaking change for some; if your "over" handler requires the unmodified coordinates from original mouseover, you can read them from the <code>event.originalEvent</code></em>. Many other improvements and bug fixes.</li>
<li>v1.8.1 = (2014) Minor update: fixes bower.json to indicate that the plugin works with all versions of jQuery &gt;= 1.9.1.</li>
<li>v1.8.0 = (2014) Changed to <a href="http://semver.org">Semantic Versioning</a> (from r8 to v1.8.0). Removed <a href="https://en.wikipedia.org/wiki/Zero-width_no-break_space">U+FEFF character</a> from beginning of JS file. Removed stray "jQuery" in favor of "$" for noConflict situations. Changed measurements to use Euclidean (instead of rectilinear) distance. Thanks to <a href="https://github.com/briancherne/jquery-hoverIntent/graphs/contributors">the GitHub community</a> for patches, suggestions, and fixes!</li>
<li>r7 = (2013) Added event delegation via "selector" param/property. Added namespaced events for better isolation. Added handlerInOut support.</li>
<li>r6 = (2011) Identical to r5 except that the Google Chrome defect is fixed once you upgrade to jQuery 1.5.1 (or later).</li>
<li>r5 = (2007) Added state to prevent unmatched function calls. This and previous releases suffer from <a href="http://code.google.com/p/chromium/issues/detail?id=68861">a defect in Google Chrome that improperly triggers mouseout when entering a child input[type=text] element</a>.</li>
<li>r4 = Fixed polling interval timing issue (now uses a self-calling timeout to avoid interval irregularities).</li>
<li>r3 = Developer-only release for debugging.</li>
<li>r2 = Added timeout and interval references to DOM object -- keeps timers separate from each other. Added configurable options. Added timeout option to delay onMouseLeave function call. Fixed two-interval mouseOver bug (now setting pX and pY onMouseEnter instead of hardcoded value).</li>
<li>r1 = Initial release to jQuery discussion forum for feedback.</li>
</ul>
</body>
</html>
/*!
* hoverIntent v1.9.0 // 2017.09.01 // jQuery v1.7.0+
* http://briancherne.github.io/jquery-hoverIntent/
*
* You may use hoverIntent under the terms of the MIT license. Basically that
* means you are free to use hoverIntent as long as this header is left intact.
* Copyright 2007-2017 Brian Cherne
*/
/* hoverIntent is similar to jQuery's built-in "hover" method except that
* instead of firing the handlerIn function immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the event. The handlerOut function is only
* called after a matching handlerIn.
*
* // basic usage ... just like .hover()
* .hoverIntent( handlerIn, handlerOut )
* .hoverIntent( handlerInOut )
*
* // basic usage ... with event delegation!
* .hoverIntent( handlerIn, handlerOut, selector )
* .hoverIntent( handlerInOut, selector )
*
* // using a basic configuration object
* .hoverIntent( config )
*
* @param handlerIn function OR configuration object
* @param handlerOut function OR selector for delegation OR undefined
* @param selector selector OR undefined
* @author Brian Cherne <brian(at)cherne(dot)net>
*/
;(function(factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (jQuery && !jQuery.fn.hoverIntent) {
factory(jQuery);
}
})(function($) {
'use strict';
// default configuration values
var _cfg = {
interval: 100,
sensitivity: 6,
timeout: 0
};
// counter used to generate an ID for each instance
var INSTANCE_COUNT = 0;
// current X and Y position of mouse, updated during mousemove tracking (shared across instances)
var cX, cY;
// saves the current pointer position coordinates based on the given mousemove event
var track = function(ev) {
cX = ev.pageX;
cY = ev.pageY;
};
// compares current and previous mouse positions
var compare = function(ev,$el,s,cfg) {
// compare mouse positions to see if pointer has slowed enough to trigger `over` function
if ( Math.sqrt( (s.pX-cX)*(s.pX-cX) + (s.pY-cY)*(s.pY-cY) ) < cfg.sensitivity ) {
$el.off(s.event,track);
delete s.timeoutId;
// set hoverIntent state as active for this element (permits `out` handler to trigger)
s.isActive = true;
// overwrite old mouseenter event coordinates with most recent pointer position
ev.pageX = cX; ev.pageY = cY;
// clear coordinate data from state object
delete s.pX; delete s.pY;
return cfg.over.apply($el[0],[ev]);
} else {
// set previous coordinates for next comparison
s.pX = cX; s.pY = cY;
// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
s.timeoutId = setTimeout( function(){compare(ev, $el, s, cfg);} , cfg.interval );
}
};
// triggers given `out` function at configured `timeout` after a mouseleave and clears state
var delay = function(ev,$el,s,out) {
delete $el.data('hoverIntent')[s.id];
return out.apply($el[0],[ev]);
};
$.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
// instance ID, used as a key to store and retrieve state information on an element
var instanceId = INSTANCE_COUNT++;
// extend the default configuration and parse parameters
var cfg = $.extend({}, _cfg);
if ( $.isPlainObject(handlerIn) ) {
cfg = $.extend(cfg, handlerIn);
if ( !$.isFunction(cfg.out) ) {
cfg.out = cfg.over;
}
} else if ( $.isFunction(handlerOut) ) {
cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
} else {
cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
}
// A private function for handling mouse 'hovering'
var handleHover = function(e) {
// cloned event to pass to handlers (copy required for event object to be passed in IE)
var ev = $.extend({},e);
// the current target of the mouse event, wrapped in a jQuery object
var $el = $(this);
// read hoverIntent data from element (or initialize if not present)
var hoverIntentData = $el.data('hoverIntent');
if (!hoverIntentData) { $el.data('hoverIntent', (hoverIntentData = {})); }
// read per-instance state from element (or initialize if not present)
var state = hoverIntentData[instanceId];
if (!state) { hoverIntentData[instanceId] = state = { id: instanceId }; }
// state properties:
// id = instance ID, used to clean up data
// timeoutId = timeout ID, reused for tracking mouse position and delaying "out" handler
// isActive = plugin state, true after `over` is called just until `out` is called
// pX, pY = previously-measured pointer coordinates, updated at each polling interval
// event = string representing the namespaced event used for mouse tracking
// clear any existing timeout
if (state.timeoutId) { state.timeoutId = clearTimeout(state.timeoutId); }
// namespaced event used to register and unregister mousemove tracking
var mousemove = state.event = 'mousemove.hoverIntent.hoverIntent'+instanceId;
// handle the event, based on its type
if (e.type === 'mouseenter') {
// do nothing if already active
if (state.isActive) { return; }
// set "previous" X and Y position based on initial entry point
state.pX = ev.pageX; state.pY = ev.pageY;
// update "current" X and Y position based on mousemove
$el.off(mousemove,track).on(mousemove,track);
// start polling interval (self-calling timeout) to compare mouse coordinates over time
state.timeoutId = setTimeout( function(){compare(ev,$el,state,cfg);} , cfg.interval );
} else { // "mouseleave"
// do nothing if not already active
if (!state.isActive) { return; }
// unbind expensive mousemove event
$el.off(mousemove,track);
// if hoverIntent state is true, then call the mouseOut function after the specified delay
state.timeoutId = setTimeout( function(){delay(ev,$el,state,cfg.out);} , cfg.timeout );
}
};
// listen for mouseenter and mouseleave
return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
};
});
/*!
* hoverIntent v1.9.0 // 2017.09.01 // jQuery v1.7.0+
* http://briancherne.github.io/jquery-hoverIntent/
*
* You may use hoverIntent under the terms of the MIT license. Basically that
* means you are free to use hoverIntent as long as this header is left intact.
* Copyright 2007-2017 Brian Cherne
*/
!function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery"],factory):jQuery&&!jQuery.fn.hoverIntent&&factory(jQuery)}(function($){"use strict";var cX,cY,_cfg={interval:100,sensitivity:6,timeout:0},INSTANCE_COUNT=0,track=function(ev){cX=ev.pageX,cY=ev.pageY},compare=function(ev,$el,s,cfg){if(Math.sqrt((s.pX-cX)*(s.pX-cX)+(s.pY-cY)*(s.pY-cY))<cfg.sensitivity)return $el.off(s.event,track),delete s.timeoutId,s.isActive=!0,ev.pageX=cX,ev.pageY=cY,delete s.pX,delete s.pY,cfg.over.apply($el[0],[ev]);s.pX=cX,s.pY=cY,s.timeoutId=setTimeout(function(){compare(ev,$el,s,cfg)},cfg.interval)},delay=function(ev,$el,s,out){return delete $el.data("hoverIntent")[s.id],out.apply($el[0],[ev])};$.fn.hoverIntent=function(handlerIn,handlerOut,selector){var instanceId=INSTANCE_COUNT++,cfg=$.extend({},_cfg);$.isPlainObject(handlerIn)?(cfg=$.extend(cfg,handlerIn),$.isFunction(cfg.out)||(cfg.out=cfg.over)):cfg=$.isFunction(handlerOut)?$.extend(cfg,{over:handlerIn,out:handlerOut,selector:selector}):$.extend(cfg,{over:handlerIn,out:handlerIn,selector:handlerOut});var handleHover=function(e){var ev=$.extend({},e),$el=$(this),hoverIntentData=$el.data("hoverIntent");hoverIntentData||$el.data("hoverIntent",hoverIntentData={});var state=hoverIntentData[instanceId];state||(hoverIntentData[instanceId]=state={id:instanceId}),state.timeoutId&&(state.timeoutId=clearTimeout(state.timeoutId));var mousemove=state.event="mousemove.hoverIntent.hoverIntent"+instanceId;if("mouseenter"===e.type){if(state.isActive)return;state.pX=ev.pageX,state.pY=ev.pageY,$el.off(mousemove,track).on(mousemove,track),state.timeoutId=setTimeout(function(){compare(ev,$el,state,cfg)},cfg.interval)}else{if(!state.isActive)return;$el.off(mousemove,track),state.timeoutId=setTimeout(function(){delay(ev,$el,state,cfg.out)},cfg.timeout)}};return this.on({"mouseenter.hoverIntent":handleHover,"mouseleave.hoverIntent":handleHover},cfg.selector)}});
\ No newline at end of file
{
"name": "jquery-hoverintent",
"version": "1.9.0",
"description": "A jQuery plugin that attempts to determine the user's intent on mouseover and thus delay or prevent the accidental firing of callbacks.",
"keywords": [
"browser",
"delay",
"events",
"hover",
"hoverintent",
"intent",
"jquery",
"jquery-plugin",
"mouse",
"mouseenter",
"mouseover",
"plugin"
],
"main": "jquery.hoverIntent.js",
"homepage": "http://briancherne.github.io/jquery-hoverIntent/",
"author": "Brian Cherne <brian@cherne.net>",
"contributors": [
"usmonster (https://github.com/usmonster)"
],
"repository": {
"type": "git",
"url": "https://github.com/briancherne/jquery-hoverIntent.git"
},
"bugs": {
"url": "https://github.com/briancherne/jquery-hoverIntent/issues"
},
"dependencies": {
"jquery": ">=1.7.0"
},
"peerDependencies": {
"jquery": ">=1.7.0"
},
"devDependencies": {
"uglify-js": "^3.0.28"
},
"scripts": {
"build": "uglifyjs jquery.hoverIntent.js -c --comments '/^!/' -o jquery.hoverIntent.min.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "MIT"
}
JSON in JavaScript
Douglas Crockford
douglas@crockford.com
2015-05-03
JSON is a light-weight, language independent, data interchange format.
See http://www.JSON.org/
The files in this collection implement JSON encoders/decoders in JavaScript.
JSON became a built-in feature of JavaScript when the ECMAScript Programming
Language Standard - Fifth Edition was adopted by the ECMA General Assembly
in December 2009. Most of the files in this collection are for applications
that are expected to run in obsolete web browsers. For most purposes, json2.js
is the best choice.
json2.js: This file creates a JSON property in the global object, if there
isn't already one, setting its value to an object containing a stringify
method and a parse method. The parse method uses the eval method to do the
parsing, guarding it with several regular expressions to defend against
accidental code execution hazards. On current browsers, this file does nothing,
preferring the built-in JSON object. There is no reason to use this file unless
fate compels you to support IE8, which is something that no one should ever
have to do again.
json_parse.js: This file contains an alternative JSON parse function that
uses recursive descent instead of eval.
json_parse_state.js: This files contains an alternative JSON parse function that
uses a state machine instead of eval.
cycle.js: This file contains two functions, JSON.decycle and JSON.retrocycle,
which make it possible to encode cyclical structures and dags in JSON, and to
then recover them. This is a capability that is not provided by ES5. JSONPath
is used to represent the links. [http://GOESSNER.net/articles/JsonPath/]
/*
cycle.js
2017-02-07
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
*/
// The file uses the WeakMap feature of ES6.
/*jslint es6, eval */
/*property
$ref, decycle, forEach, get, indexOf, isArray, keys, length, push,
retrocycle, set, stringify, test
*/
if (typeof JSON.decycle !== "function") {
JSON.decycle = function decycle(object, replacer) {
"use strict";
// Make a deep copy of an object or array, assuring that there is at most
// one instance of each object or array in the resulting structure. The
// duplicate references (which might be forming cycles) are replaced with
// an object of the form
// {"$ref": PATH}
// where the PATH is a JSONPath string that locates the first occurance.
// So,
// var a = [];
// a[0] = a;
// return JSON.stringify(JSON.decycle(a));
// produces the string '[{"$ref":"$"}]'.
// If a replacer function is provided, then it will be called for each value.
// A replacer function receives a value and returns a replacement value.
// JSONPath is used to locate the unique object. $ indicates the top level of
// the object or array. [NUMBER] or [STRING] indicates a child element or
// property.
var objects = new WeakMap(); // object to path mappings
return (function derez(value, path) {
// The derez function recurses through the object, producing the deep copy.
var old_path; // The path of an earlier occurance of value
var nu; // The new object or array
// If a replacer function was provided, then call it to get a replacement value.
if (replacer !== undefined) {
value = replacer(value);
}
// typeof null === "object", so go on if this value is really an object but not
// one of the weird builtin objects.
if (
typeof value === "object" && value !== null &&
!(value instanceof Boolean) &&
!(value instanceof Date) &&
!(value instanceof Number) &&
!(value instanceof RegExp) &&
!(value instanceof String)
) {
// If the value is an object or array, look to see if we have already
// encountered it. If so, return a {"$ref":PATH} object. This uses an
// ES6 WeakMap.
old_path = objects.get(value);
if (old_path !== undefined) {
return {$ref: old_path};
}
// Otherwise, accumulate the unique value and its path.
objects.set(value, path);
// If it is an array, replicate the array.
if (Array.isArray(value)) {
nu = [];
value.forEach(function (element, i) {
nu[i] = derez(element, path + "[" + i + "]");
});
} else {
// If it is an object, replicate the object.
nu = {};
Object.keys(value).forEach(function (name) {
nu[name] = derez(
value[name],
path + "[" + JSON.stringify(name) + "]"
);
});
}
return nu;
}
return value;
}(object, "$"));
};
}
if (typeof JSON.retrocycle !== "function") {
JSON.retrocycle = function retrocycle($) {
"use strict";
// Restore an object that was reduced by decycle. Members whose values are
// objects of the form
// {$ref: PATH}
// are replaced with references to the value found by the PATH. This will
// restore cycles. The object will be mutated.
// The eval function is used to locate the values described by a PATH. The
// root object is kept in a $ variable. A regular expression is used to
// assure that the PATH is extremely well formed. The regexp contains nested
// * quantifiers. That has been known to have extremely bad performance
// problems on some browsers for very long strings. A PATH is expected to be
// reasonably short. A PATH is allowed to belong to a very restricted subset of
// Goessner's JSONPath.
// So,
// var s = '[{"$ref":"$"}]';
// return JSON.retrocycle(JSON.parse(s));
// produces an array containing a single element which is the array itself.
var px = /^\$(?:\[(?:\d+|"(?:[^\\"\u0000-\u001f]|\\([\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*")\])*$/;
(function rez(value) {
// The rez function walks recursively through the object looking for $ref
// properties. When it finds one that has a value that is a path, then it
// replaces the $ref object with a reference to the value that is found by
// the path.
if (value && typeof value === "object") {
if (Array.isArray(value)) {
value.forEach(function (element, i) {
if (typeof element === "object" && element !== null) {
var path = element.$ref;
if (typeof path === "string" && px.test(path)) {
value[i] = eval(path);
} else {
rez(element);
}
}
});
} else {
Object.keys(value).forEach(function (name) {
var item = value[name];
if (typeof item === "object" && item !== null) {
var path = item.$ref;
if (typeof path === "string" && px.test(path)) {
value[name] = eval(path);
} else {
rez(item);
}
}
});
}
}
}($));
return $;
};
}
// json2.js
// 2016-10-28
// Public Domain.
// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
// See http://www.JSON.org/js.html
// This code should be minified before deployment.
// See http://javascript.crockford.com/jsmin.html
// USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
// NOT CONTROL.
// This file creates a global JSON object containing two methods: stringify
// and parse. This file provides the ES5 JSON capability to ES3 systems.
// If a project might run on IE8 or earlier, then this file should be included.
// This file does nothing on ES5 systems.
// JSON.stringify(value, replacer, space)
// value any JavaScript value, usually an object or array.
// replacer an optional parameter that determines how object
// values are stringified for objects. It can be a
// function or an array of strings.
// space an optional parameter that specifies the indentation
// of nested structures. If it is omitted, the text will
// be packed without extra whitespace. If it is a number,
// it will specify the number of spaces to indent at each
// level. If it is a string (such as "\t" or "&nbsp;"),
// it contains the characters used to indent at each level.
// This method produces a JSON text from a JavaScript value.
// When an object value is found, if the object contains a toJSON
// method, its toJSON method will be called and the result will be
// stringified. A toJSON method does not serialize: it returns the
// value represented by the name/value pair that should be serialized,
// or undefined if nothing should be serialized. The toJSON method
// will be passed the key associated with the value, and this will be
// bound to the value.
// For example, this would serialize Dates as ISO strings.
// Date.prototype.toJSON = function (key) {
// function f(n) {
// // Format integers to have at least two digits.
// return (n < 10)
// ? "0" + n
// : n;
// }
// return this.getUTCFullYear() + "-" +
// f(this.getUTCMonth() + 1) + "-" +
// f(this.getUTCDate()) + "T" +
// f(this.getUTCHours()) + ":" +
// f(this.getUTCMinutes()) + ":" +
// f(this.getUTCSeconds()) + "Z";
// };
// You can provide an optional replacer method. It will be passed the
// key and value of each member, with this bound to the containing
// object. The value that is returned from your method will be
// serialized. If your method returns undefined, then the member will
// be excluded from the serialization.
// If the replacer parameter is an array of strings, then it will be
// used to select the members to be serialized. It filters the results
// such that only members with keys listed in the replacer array are
// stringified.
// Values that do not have JSON representations, such as undefined or
// functions, will not be serialized. Such values in objects will be
// dropped; in arrays they will be replaced with null. You can use
// a replacer function to replace those with JSON values.
// JSON.stringify(undefined) returns undefined.
// The optional space parameter produces a stringification of the
// value that is filled with line breaks and indentation to make it
// easier to read.
// If the space parameter is a non-empty string, then that string will
// be used for indentation. If the space parameter is a number, then
// the indentation will be that many spaces.
// Example:
// text = JSON.stringify(["e", {pluribus: "unum"}]);
// // text is '["e",{"pluribus":"unum"}]'
// text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t");
// // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
// text = JSON.stringify([new Date()], function (key, value) {
// return this[key] instanceof Date
// ? "Date(" + this[key] + ")"
// : value;
// });
// // text is '["Date(---current time---)"]'
// JSON.parse(text, reviver)
// This method parses a JSON text to produce an object or array.
// It can throw a SyntaxError exception.
// The optional reviver parameter is a function that can filter and
// transform the results. It receives each of the keys and values,
// and its return value is used instead of the original value.
// If it returns what it received, then the structure is not modified.
// If it returns undefined then the member is deleted.
// Example:
// // Parse the text. Values that look like ISO date strings will
// // be converted to Date objects.
// myData = JSON.parse(text, function (key, value) {
// var a;
// if (typeof value === "string") {
// a =
// /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
// if (a) {
// return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
// +a[5], +a[6]));
// }
// }
// return value;
// });
// myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
// var d;
// if (typeof value === "string" &&
// value.slice(0, 5) === "Date(" &&
// value.slice(-1) === ")") {
// d = new Date(value.slice(5, -1));
// if (d) {
// return d;
// }
// }
// return value;
// });
// This is a reference implementation. You are free to copy, modify, or
// redistribute.
/*jslint
eval, for, this
*/
/*property
JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (typeof JSON !== "object") {
JSON = {};
}
(function () {
"use strict";
var rx_one = /^[\],:{}\s]*$/;
var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
function f(n) {
// Format integers to have at least two digits.
return n < 10
? "0" + n
: n;
}
function this_value() {
return this.valueOf();
}
if (typeof Date.prototype.toJSON !== "function") {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
? this.getUTCFullYear() + "-" +
f(this.getUTCMonth() + 1) + "-" +
f(this.getUTCDate()) + "T" +
f(this.getUTCHours()) + ":" +
f(this.getUTCMinutes()) + ":" +
f(this.getUTCSeconds()) + "Z"
: null;
};
Boolean.prototype.toJSON = this_value;
Number.prototype.toJSON = this_value;
String.prototype.toJSON = this_value;
}
var gap;
var indent;
var meta;
var rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
rx_escapable.lastIndex = 0;
return rx_escapable.test(string)
? "\"" + string.replace(rx_escapable, function (a) {
var c = meta[a];
return typeof c === "string"
? c
: "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
}) + "\""
: "\"" + string + "\"";
}
function str(key, holder) {
// Produce a string from holder[key].
var i; // The loop counter.
var k; // The member key.
var v; // The member value.
var length;
var mind = gap;
var partial;
var value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === "object" &&
typeof value.toJSON === "function") {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === "function") {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case "string":
return quote(value);
case "number":
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value)
? String(value)
: "null";
case "boolean":
case "null":
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce "null". The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is "object", we might be dealing with an object or an array or
// null.
case "object":
// Due to a specification blunder in ECMAScript, typeof null is "object",
// so watch out for that case.
if (!value) {
return "null";
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === "[object Array]") {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || "null";
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0
? "[]"
: gap
? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]"
: "[" + partial.join(",") + "]";
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === "object") {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === "string") {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (
gap
? ": "
: ":"
) + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (
gap
? ": "
: ":"
) + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0
? "{}"
: gap
? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
: "{" + partial.join(",") + "}";
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== "function") {
meta = { // table of character substitutions
"\b": "\\b",
"\t": "\\t",
"\n": "\\n",
"\f": "\\f",
"\r": "\\r",
"\"": "\\\"",
"\\": "\\\\"
};
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = "";
indent = "";
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === "number") {
for (i = 0; i < space; i += 1) {
indent += " ";
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === "string") {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== "function" &&
(typeof replacer !== "object" ||
typeof replacer.length !== "number")) {
throw new Error("JSON.stringify");
}
// Make a fake root object containing our value under the key of "".
// Return the result of stringifying the value.
return str("", {"": value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== "function") {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k;
var v;
var value = holder[key];
if (value && typeof value === "object") {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
rx_dangerous.lastIndex = 0;
if (rx_dangerous.test(text)) {
text = text.replace(rx_dangerous, function (a) {
return "\\u" +
("0000" + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with "()" and "new"
// because they can cause invocation, and "=" because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
// replace all simple value tokens with "]" characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or "]" or
// "," or ":" or "{" or "}". If that is so, then the text is safe for eval.
if (
rx_one.test(
text
.replace(rx_two, "@")
.replace(rx_three, "]")
.replace(rx_four, "")
)
) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The "{" operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval("(" + text + ")");
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return (typeof reviver === "function")
? walk({"": j}, "")
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError("JSON.parse");
};
}
}());
/*
json_parse.js
2016-05-02
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
This file creates a json_parse function.
json_parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = json_parse(text, function (key, value) {
var a;
if (typeof value === "string") {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
*/
/*jslint for */
/*property
at, b, call, charAt, f, fromCharCode, hasOwnProperty, message, n, name,
prototype, push, r, t, text
*/
var json_parse = (function () {
"use strict";
// This is a function that can parse a JSON text, producing a JavaScript
// data structure. It is a simple, recursive descent parser. It does not use
// eval or regular expressions, so it can be used as a model for implementing
// a JSON parser in other languages.
// We are defining the function inside of another function to avoid creating
// global variables.
var at; // The index of the current character
var ch; // The current character
var escapee = {
"\"": "\"",
"\\": "\\",
"/": "/",
b: "\b",
f: "\f",
n: "\n",
r: "\r",
t: "\t"
};
var text;
var error = function (m) {
// Call error when something is wrong.
throw {
name: "SyntaxError",
message: m,
at: at,
text: text
};
};
var next = function (c) {
// If a c parameter is provided, verify that it matches the current character.
if (c && c !== ch) {
error("Expected '" + c + "' instead of '" + ch + "'");
}
// Get the next character. When there are no more characters,
// return the empty string.
ch = text.charAt(at);
at += 1;
return ch;
};
var number = function () {
// Parse a number value.
var value;
var string = "";
if (ch === "-") {
string = "-";
next("-");
}
while (ch >= "0" && ch <= "9") {
string += ch;
next();
}
if (ch === ".") {
string += ".";
while (next() && ch >= "0" && ch <= "9") {
string += ch;
}
}
if (ch === "e" || ch === "E") {
string += ch;
next();
if (ch === "-" || ch === "+") {
string += ch;
next();
}
while (ch >= "0" && ch <= "9") {
string += ch;
next();
}
}
value = +string;
if (!isFinite(value)) {
error("Bad number");
} else {
return value;
}
};
var string = function () {
// Parse a string value.
var hex;
var i;
var value = "";
var uffff;
// When parsing for string values, we must look for " and \ characters.
if (ch === "\"") {
while (next()) {
if (ch === "\"") {
next();
return value;
}
if (ch === "\\") {
next();
if (ch === "u") {
uffff = 0;
for (i = 0; i < 4; i += 1) {
hex = parseInt(next(), 16);
if (!isFinite(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
value += String.fromCharCode(uffff);
} else if (typeof escapee[ch] === "string") {
value += escapee[ch];
} else {
break;
}
} else {
value += ch;
}
}
}
error("Bad string");
};
var white = function () {
// Skip whitespace.
while (ch && ch <= " ") {
next();
}
};
var word = function () {
// true, false, or null.
switch (ch) {
case "t":
next("t");
next("r");
next("u");
next("e");
return true;
case "f":
next("f");
next("a");
next("l");
next("s");
next("e");
return false;
case "n":
next("n");
next("u");
next("l");
next("l");
return null;
}
error("Unexpected '" + ch + "'");
};
var value; // Place holder for the value function.
var array = function () {
// Parse an array value.
var arr = [];
if (ch === "[") {
next("[");
white();
if (ch === "]") {
next("]");
return arr; // empty array
}
while (ch) {
arr.push(value());
white();
if (ch === "]") {
next("]");
return arr;
}
next(",");
white();
}
}
error("Bad array");
};
var object = function () {
// Parse an object value.
var key;
var obj = {};
if (ch === "{") {
next("{");
white();
if (ch === "}") {
next("}");
return obj; // empty object
}
while (ch) {
key = string();
white();
next(":");
if (Object.hasOwnProperty.call(obj, key)) {
error("Duplicate key '" + key + "'");
}
obj[key] = value();
white();
if (ch === "}") {
next("}");
return obj;
}
next(",");
white();
}
}
error("Bad object");
};
value = function () {
// Parse a JSON value. It could be an object, an array, a string, a number,
// or a word.
white();
switch (ch) {
case "{":
return object();
case "[":
return array();
case "\"":
return string();
case "-":
return number();
default:
return (ch >= "0" && ch <= "9")
? number()
: word();
}
};
// Return the json_parse function. It will have access to all of the above
// functions and variables.
return function (source, reviver) {
var result;
text = source;
at = 0;
ch = " ";
result = value();
white();
if (ch) {
error("Syntax error");
}
// If there is a reviver function, we recursively walk the new structure,
// passing each name/value pair to the reviver function for possible
// transformation, starting with a temporary root object that holds the result
// in an empty key. If there is not a reviver function, we simply return the
// result.
return (typeof reviver === "function")
? (function walk(holder, key) {
var k;
var v;
var val = holder[key];
if (val && typeof val === "object") {
for (k in val) {
if (Object.prototype.hasOwnProperty.call(val, k)) {
v = walk(val, k);
if (v !== undefined) {
val[k] = v;
} else {
delete val[k];
}
}
}
}
return reviver.call(holder, key, val);
}({"": result}, ""))
: result;
};
}());
/*
json_parse_state.js
2016-05-02
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
This file creates a json_parse function.
json_parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = json_parse(text, function (key, value) {
var a;
if (typeof value === "string") {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
*/
/*jslint for */
/*property
acomma, avalue, b, call, colon, container, exec, f, false, firstavalue,
firstokey, fromCharCode, go, hasOwnProperty, key, length, n, null, ocomma,
okey, ovalue, pop, prototype, push, r, replace, slice, state, t, test,
true
*/
var json_parse = (function () {
"use strict";
// This function creates a JSON parse function that uses a state machine rather
// than the dangerous eval function to parse a JSON text.
var state; // The state of the parser, one of
// 'go' The starting state
// 'ok' The final, accepting state
// 'firstokey' Ready for the first key of the object or
// the closing of an empty object
// 'okey' Ready for the next key of the object
// 'colon' Ready for the colon
// 'ovalue' Ready for the value half of a key/value pair
// 'ocomma' Ready for a comma or closing }
// 'firstavalue' Ready for the first value of an array or
// an empty array
// 'avalue' Ready for the next value of an array
// 'acomma' Ready for a comma or closing ]
var stack; // The stack, for controlling nesting.
var container; // The current container object or array
var key; // The current key
var value; // The current value
var escapes = { // Escapement translation table
"\\": "\\",
"\"": "\"",
"/": "/",
"t": "\t",
"n": "\n",
"r": "\r",
"f": "\f",
"b": "\b"
};
var string = { // The actions for string tokens
go: function () {
state = "ok";
},
firstokey: function () {
key = value;
state = "colon";
},
okey: function () {
key = value;
state = "colon";
},
ovalue: function () {
state = "ocomma";
},
firstavalue: function () {
state = "acomma";
},
avalue: function () {
state = "acomma";
}
};
var number = { // The actions for number tokens
go: function () {
state = "ok";
},
ovalue: function () {
state = "ocomma";
},
firstavalue: function () {
state = "acomma";
},
avalue: function () {
state = "acomma";
}
};
var action = {
// The action table describes the behavior of the machine. It contains an
// object for each token. Each object contains a method that is called when
// a token is matched in a state. An object will lack a method for illegal
// states.
"{": {
go: function () {
stack.push({state: "ok"});
container = {};
state = "firstokey";
},
ovalue: function () {
stack.push({container: container, state: "ocomma", key: key});
container = {};
state = "firstokey";
},
firstavalue: function () {
stack.push({container: container, state: "acomma"});
container = {};
state = "firstokey";
},
avalue: function () {
stack.push({container: container, state: "acomma"});
container = {};
state = "firstokey";
}
},
"}": {
firstokey: function () {
var pop = stack.pop();
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
},
ocomma: function () {
var pop = stack.pop();
container[key] = value;
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
}
},
"[": {
go: function () {
stack.push({state: "ok"});
container = [];
state = "firstavalue";
},
ovalue: function () {
stack.push({container: container, state: "ocomma", key: key});
container = [];
state = "firstavalue";
},
firstavalue: function () {
stack.push({container: container, state: "acomma"});
container = [];
state = "firstavalue";
},
avalue: function () {
stack.push({container: container, state: "acomma"});
container = [];
state = "firstavalue";
}
},
"]": {
firstavalue: function () {
var pop = stack.pop();
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
},
acomma: function () {
var pop = stack.pop();
container.push(value);
value = container;
container = pop.container;
key = pop.key;
state = pop.state;
}
},
":": {
colon: function () {
if (Object.hasOwnProperty.call(container, key)) {
throw new SyntaxError("Duplicate key '" + key + "\"");
}
state = "ovalue";
}
},
",": {
ocomma: function () {
container[key] = value;
state = "okey";
},
acomma: function () {
container.push(value);
state = "avalue";
}
},
"true": {
go: function () {
value = true;
state = "ok";
},
ovalue: function () {
value = true;
state = "ocomma";
},
firstavalue: function () {
value = true;
state = "acomma";
},
avalue: function () {
value = true;
state = "acomma";
}
},
"false": {
go: function () {
value = false;
state = "ok";
},
ovalue: function () {
value = false;
state = "ocomma";
},
firstavalue: function () {
value = false;
state = "acomma";
},
avalue: function () {
value = false;
state = "acomma";
}
},
"null": {
go: function () {
value = null;
state = "ok";
},
ovalue: function () {
value = null;
state = "ocomma";
},
firstavalue: function () {
value = null;
state = "acomma";
},
avalue: function () {
value = null;
state = "acomma";
}
}
};
function debackslashify(text) {
// Remove and replace any backslash escapement.
return text.replace(/\\(?:u(.{4})|([^u]))/g, function (ignore, b, c) {
return b
? String.fromCharCode(parseInt(b, 16))
: escapes[c];
});
}
return function (source, reviver) {
// A regular expression is used to extract tokens from the JSON text.
// The extraction process is cautious.
var result;
var tx = /^[\u0020\t\n\r]*(?:([,:\[\]{}]|true|false|null)|(-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)|"((?:[^\r\n\t\\\"]|\\(?:["\\\/trnfb]|u[0-9a-fA-F]{4}))*)")/;
// Set the starting state.
state = "go";
// The stack records the container, key, and state for each object or array
// that contains another object or array while processing nested structures.
stack = [];
// If any error occurs, we will catch it and ultimately throw a syntax error.
try {
// For each token...
while (true) {
result = tx.exec(source);
if (!result) {
break;
}
// result is the result array from matching the tokenizing regular expression.
// result[0] contains everything that matched, including any initial whitespace.
// result[1] contains any punctuation that was matched, or true, false, or null.
// result[2] contains a matched number, still in string form.
// result[3] contains a matched string, without quotes but with escapement.
if (result[1]) {
// Token: Execute the action for this state and token.
action[result[1]][state]();
} else if (result[2]) {
// Number token: Convert the number string into a number value and execute
// the action for this state and number.
value = +result[2];
number[state]();
} else {
// String token: Replace the escapement sequences and execute the action for
// this state and string.
value = debackslashify(result[3]);
string[state]();
}
// Remove the token from the string. The loop will continue as long as there
// are tokens. This is a slow process, but it allows the use of ^ matching,
// which assures that no illegal tokens slip through.
source = source.slice(result[0].length);
}
// If we find a state/token combination that is illegal, then the action will
// cause an error. We handle the error by simply changing the state.
} catch (e) {
state = e;
}
// The parsing is finished. If we are not in the final "ok" state, or if the
// remaining source contains anything except whitespace, then we did not have
//a well-formed JSON text.
if (state !== "ok" || (/[^\u0020\t\n\r]/.test(source))) {
throw (state instanceof SyntaxError)
? state
: new SyntaxError("JSON");
}
// If there is a reviver function, we recursively walk the new structure,
// passing each name/value pair to the reviver function for possible
// transformation, starting with a temporary root object that holds the current
// value in an empty key. If there is not a reviver function, we simply return
// that value.
return (typeof reviver === "function")
? (function walk(holder, key) {
var k;
var v;
var val = holder[key];
if (val && typeof val === "object") {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(val, k)) {
v = walk(val, k);
if (v !== undefined) {
val[k] = v;
} else {
delete val[k];
}
}
}
}
return reviver.call(holder, key, val);
}({"": value}, ""))
: value;
};
}());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment