From 60d6c5f3e46b887806e252d5dea1f04715a81e0d Mon Sep 17 00:00:00 2001 From: Victor Häggqvist Date: Sat, 16 Jan 2016 22:00:36 +0100 Subject: write some docs and fixup demo --- README.md | 75 ---- README.rst | 121 ++++++ bower.json | 2 +- demo/LightBox.ActivityIndicator.js | 106 +++++ demo/LightBox.Captions.js | 108 +++++ demo/LightBox.CloseButton.js | 113 +++++ demo/LightBox.Core.js | 857 +++++++++++++++++++++++++++++++++++++ demo/LightBox.Navigation.js | 138 ++++++ demo/LightBox.Overlay.js | 96 +++++ demo/index.html | 277 ++++++++---- demotemplate.html.jinja | 0 dist/touch-imagelightbox.css | 270 +----------- docs/Makefile | 216 ++++++++++ docs/api.rst | 50 +++ docs/conf.py | 290 +++++++++++++ docs/hacking.rst | 20 + docs/index.rst | 26 ++ docs/plugins.rst | 25 ++ gulpfile.js | 33 +- package.json | 1 + prepdemoimages.py | 46 ++ src/CSSUtil.js | 2 - 22 files changed, 2442 insertions(+), 430 deletions(-) delete mode 100644 README.md create mode 100644 README.rst create mode 100644 demo/LightBox.ActivityIndicator.js create mode 100644 demo/LightBox.Captions.js create mode 100644 demo/LightBox.CloseButton.js create mode 100644 demo/LightBox.Core.js create mode 100644 demo/LightBox.Navigation.js create mode 100644 demo/LightBox.Overlay.js create mode 100644 demotemplate.html.jinja create mode 100644 docs/Makefile create mode 100644 docs/api.rst create mode 100644 docs/conf.py create mode 100644 docs/hacking.rst create mode 100644 docs/index.rst create mode 100644 docs/plugins.rst create mode 100755 prepdemoimages.py diff --git a/README.md b/README.md deleted file mode 100644 index 90ceb36..0000000 --- a/README.md +++ /dev/null @@ -1,75 +0,0 @@ -Touch Imagelightbox -============== -Imagelightbox was originly created by [Osvaldas Valutis](http://osvaldas.info/image-lightbox-responsive-touch-friendly), though it was only accesible through his site. I put it here to make it more maintainable. - -View a demo here: https://victorhaggqvist.github.io/touch-imagelightbox/ - -#How to get it -Via bower.io `bower install touch-imagelightbox` - -Or with git `git clone https://github.com/victorhaggqvist/touch-imagelightbox.git` - -Or download the [zip](https://github.com/victorhaggqvist/touch-imagelightbox/archive/master.zip). - -#Requirements -jQuery - -NOTE: The bower install will not get jQuery for you, if you want to get jQuery from bower too use `bower install jquery` - -#Usage -Credits again to http://osvaldas.info/image-lightbox-responsive-touch-friendly -```html - - - -``` - -Checkout the demos at https://victorhaggqvist.github.io/touch-imagelightbox/. - -The js used in the demos are here, https://github.com/victorhaggqvist/touch-imagelightbox/blob/gh-pages/demo.js - -The CSS (and SCSS source) used to achive the demos comes with the bower package. -###Options and defaults -```js -$(selector).imageLightbox({ - selector: 'id="imagelightbox"', // string; - allowedTypes: 'png|jpg|jpeg|gif', // string; - animationSpeed: 250, // integer; - preloadNext: true, // bool; silently preload the next image - enableKeyboard: true, // bool; enable keyboard shortcuts (arrows Left/Right and Esc) - quitOnEnd: false, // bool; quit after viewing the last image - quitOnImgClick: false, // bool; quit when the viewed image is clicked - quitOnDocClick: true, // bool; quit when anything but the viewed image is clicked - onStart: false, // function/bool; calls function when the lightbox starts - onEnd: false, // function/bool; calls function when the lightbox quits - onLoadStart: false, // function/bool; calls function when the image load begins - onLoadEnd: false // function/bool; calls function when the image finishes loading -}); -``` - -###Other methodes -```js -var $instance = $(selector).imageLightbox(); - -// switches to the other image; accepts integer argument (an index of the desired image) -$instance.switchImageLightbox( index ); - -// quits the lightbox -$instance.quitImageLightbox(); -``` - -#How to build -Image Lightbox is buildt using the Grunt toolchain. The CSS is build using SASS and Compass, which means you need Ruby, the SASS and Compass gems to make it. - -Note: Remenber that you ATM need a alpha build of Compass to make it work with Grunt (`gem install compass --pre`). - -If you have Node just do a `npm install` then `grunt` and you will have a new build in the `dist/` directory. - -#License -MIT diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..0b324aa --- /dev/null +++ b/README.rst @@ -0,0 +1,121 @@ +Image LightBox +============== +A lightbox without bells and whistles. + +View a demo here: https://victorhaggqvist.github.io/touch-imagelightbox/ + +Version 0.2.0 +------------- +The original Imagelightbox and up to version 0.1.5 of `touch-imagelightbox` was a jQuery plugin. + +Version 0.2.0 is a major rewrite of the original Imagelightbox to change it's architecture and remove the jQuery dependency. + + +How to get it +------------- +Via bower + +.. code-block:: bash + + bower install touch-imagelightbox + +Or with git + +.. code-block:: bash + + git clone https://github.com/victorhaggqvist/touch-imagelightbox.git + +Requirements +------------ +As of version 0.2.0 there are no additional requirements. + +For versions <= 0.1.5 jQuery is required. + +NOTE: The bower install will not get jQuery for you, if you want to get jQuery from bower too use :code:`bower install jquery` + +Usage +----- +To only utilize the LightBox Core, with no plugins. At this point both Core and Plugins CSS is bundled. + +.. code-block:: html + + + + + +Plugins can be loaded all at once with :code:`LightBox.Plugins.js` or individually :code:`LightBox.[plugin].js` + +.. code-block:: html + + + + + + +Checkout the demos at https://victorhaggqvist.github.io/touch-imagelightbox/. + +For more about plugins see :doc:`plugins`. + +Options +------- +LightBox can be customised using options. To set custom options pass a options object as a second parameter. + +.. code-block:: js + + var options = { + preloadNext: false + }; + new LightBox.Core('a[lightbox="foo"]', options); + +Available options and defaults + ++----------------------+------------------------+-------------------+---------------------------------------+ +| Option | Default | type | Description | ++======================+========================+===================+=======================================+ +| selectorId | imagelightbox | string | The id the lightbox image will get | ++----------------------+------------------------+-------------------+---------------------------------------+ +| allowedTypes | png\|jpg\|jpeg\|gif | string | Image types allowed | ++----------------------+------------------------+-------------------+---------------------------------------+ +| animationSpeed | 250 | integer | How fast images would fade away | ++----------------------+------------------------+-------------------+---------------------------------------+ +| preloadNext | true | bool | Silently preload the next image | ++----------------------+------------------------+-------------------+---------------------------------------+ +| enableKeyboard | true | bool | Enable keyboard shortcuts (arrows | +| | | | Left/Right and Esc) | ++----------------------+------------------------+-------------------+---------------------------------------+ +| quitOnEnd | false | bool | Quit after viewing the last image | ++----------------------+------------------------+-------------------+---------------------------------------+ +| quitOnImgClick | false | bool | Quit when the viewed image is clicked | ++----------------------+------------------------+-------------------+---------------------------------------+ +| quitOnDocClick | true | bool | Quit when anything but the viewed | +| | | | image is clicked | ++----------------------+------------------------+-------------------+---------------------------------------+ + + + +Building +-------- + +.. code-block:: bash + + git clone https://github.com/victorhaggqvist/touch-imagelightbox.git + cd touch-imagelightbox + npm install + gulp build + + +Credits +------- +Imagelightbox was originally created by `Osvaldas Valutis`_. + +.. _Osvaldas Valutis: http://osvaldas.info/image-lightbox-responsive-touch-friendly + +License +------- +MIT diff --git a/bower.json b/bower.json index 0587c7b..4f5bc66 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "touch-imagelightbox", - "version": "0.1.5", + "version": "0.2.0", "authors": [ "Victor Häggqvist " ], diff --git a/demo/LightBox.ActivityIndicator.js b/demo/LightBox.ActivityIndicator.js new file mode 100644 index 0000000..479372e --- /dev/null +++ b/demo/LightBox.ActivityIndicator.js @@ -0,0 +1,106 @@ +var LightBox = LightBox || {}; LightBox["ActivityIndicator"] = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports) { + + 'use strict'; + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + /** + * + * @author Victor Häggqvist + * @since 2016-01-14 + */ + + var ActivityIndicator = function () { + function ActivityIndicator() { + _classCallCheck(this, ActivityIndicator); + + this.element = document.createElement('div'); + this.element.id = 'imagelightbox-loading'; + this.element.appendChild(document.createElement('div')); + } + + /** + * + * @param {LightBox} lightbox + */ + + _createClass(ActivityIndicator, [{ + key: 'register', + value: function register(lightbox) { + lightbox.addOnLoadStartListener(this.activityIndicatorOn.bind(this)); + lightbox.addOnLoadEndListener(this.activityIndicatorOff.bind(this)); + lightbox.addOnEndListener(this.activityIndicatorOff.bind(this)); + } + }, { + key: 'activityIndicatorOn', + value: function activityIndicatorOn() { + document.body.appendChild(this.element); + } + }, { + key: 'activityIndicatorOff', + value: function activityIndicatorOff() { + try { + document.body.removeChild(this.element); + } catch (e) {} + } + }]); + + return ActivityIndicator; + }(); + + exports.default = ActivityIndicator; + module.exports = exports['default']; + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/demo/LightBox.Captions.js b/demo/LightBox.Captions.js new file mode 100644 index 0000000..8207f97 --- /dev/null +++ b/demo/LightBox.Captions.js @@ -0,0 +1,108 @@ +var LightBox = LightBox || {}; LightBox["Captions"] = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports) { + + 'use strict'; + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + /** + * @author Victor Häggqvist + * @since 2016-01-16 + */ + + var Captions = function () { + function Captions() { + _classCallCheck(this, Captions); + + this.element = document.createElement('div'); + this.element.id = 'imagelightbox-caption'; + } + + _createClass(Captions, [{ + key: 'register', + value: function register(lightbox) { + this.lightbox = lightbox; + lightbox.addOnLoadStartListener(this.hideCaption.bind(this)); + lightbox.addOnLoadEndListener(this.showCaption.bind(this)); + lightbox.addOnEndListener(this.hideCaption.bind(this)); + } + }, { + key: 'showCaption', + value: function showCaption() { + var img = this.lightbox.target.querySelector('img'); + + if (img === null) return; + + var caption = img.getAttribute('alt'); + if (caption !== null && caption.length > 0) { + this.element.innerHTML = img.alt; + document.body.appendChild(this.element); + } + } + }, { + key: 'hideCaption', + value: function hideCaption() { + try { + document.body.removeChild(this.element); + } catch (e) {} + } + }]); + + return Captions; + }(); + + exports.default = Captions; + module.exports = exports['default']; + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/demo/LightBox.CloseButton.js b/demo/LightBox.CloseButton.js new file mode 100644 index 0000000..287ad0e --- /dev/null +++ b/demo/LightBox.CloseButton.js @@ -0,0 +1,113 @@ +var LightBox = LightBox || {}; LightBox["CloseButton"] = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports) { + + 'use strict'; + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + /** + * @author Victor Häggqvist + * @since 2016-01-14 + */ + + var CloseButton = function () { + function CloseButton() { + var closeOnDocumentClick = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; + + _classCallCheck(this, CloseButton); + + this.closeOnDocumentClick = closeOnDocumentClick; + this.element = document.createElement('a'); + this.element.id = 'imagelightbox-close'; + this.element.innerHTML = 'Close'; + } + + _createClass(CloseButton, [{ + key: 'register', + value: function register(lightbox) { + this.lightbox = lightbox; + lightbox.addOnStartListener(this.showButton.bind(this)); + lightbox.addOnEndListener(this.hideButton.bind(this)); + } + }, { + key: 'showButton', + value: function showButton() { + var _this = this; + + this.lightbox.options.quitOnDocClick = this.closeOnDocumentClick; + ['click', 'touchend'].forEach(function (name) { + _this.element.addEventListener(name, _this.exitLightbox.bind(_this)); + }); + + document.body.appendChild(this.element); + } + }, { + key: 'hideButton', + value: function hideButton() { + document.body.removeChild(this.element); + } + }, { + key: 'exitLightbox', + value: function exitLightbox() { + this.lightbox.quitLightbox(); + } + }]); + + return CloseButton; + }(); + + exports.default = CloseButton; + module.exports = exports['default']; + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/demo/LightBox.Core.js b/demo/LightBox.Core.js new file mode 100644 index 0000000..e5b8e25 --- /dev/null +++ b/demo/LightBox.Core.js @@ -0,0 +1,857 @@ +var LightBox = LightBox || {}; LightBox["Core"] = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** + * @author Victor Häggqvist + * @since 2016-01-12 + */ + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _CSSUtil = __webpack_require__(1); + + var _LightDirection = __webpack_require__(2); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var log = __webpack_require__(3); + + log.setDefaultLevel(log.levels.DEBUG); + + var LightBox = function () { + function LightBox(targetSelector) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + _classCallCheck(this, LightBox); + + log.info('LightBox'); + this.targets = document.querySelectorAll(targetSelector); + log.debug(this.targets); + + log.debug('HAS_TOUCH ' + LightBox.HAS_TOUCH); + var defaultOptions = { + allowedTypes: 'png|jpg|jpeg|gif', + restrictTypes: false, + selectorId: 'imagelightbox', + animationSpeed: 350, + preloadNext: true, + enableKeyboard: true, + quitOnEnd: false, + quitOnImgClick: false, + quitOnDocClick: true, + requestFullscreenOnMobile: true + }; + + this.options = Object.assign(options, defaultOptions); + log.info(this.options); + + this.target = null; + this.image = null; + this.imageWidth = 0; + this.imageHeight = 0; + this.swipeDiff = 0; + this.inProgress = false; + + this.swipeStart = 0; + this.swipeEnd = 0; + + this.onStartListeners = []; + this.onEndListeners = []; + this.onLoadStartListeners = []; + this.onLoadEndListeners = []; + + this.bindEvents(); + } + + _createClass(LightBox, [{ + key: 'bindEvents', + value: function bindEvents() { + var _this = this; + + Array.prototype.forEach.call(this.targets, function (ele) { + ele.addEventListener('click', _this.onImageClick.bind(_this)); + }); + window.addEventListener('resize', this.windowResizeListener.bind(this)); + + if (this.options.quitOnDocClick) { + document.body.addEventListener(LightBox.HAS_TOUCH ? 'touchend' : 'click', this.documentClick.bind(this)); + } + + if (this.options.enableKeyboard) { + document.body.addEventListener('keyup', this.handleKeyboard.bind(this)); + } + } + }, { + key: 'handleKeyboard', + value: function handleKeyboard(e) { + if (this.image === null) return true; + + e.preventDefault(); + + if (e.keyCode === 27) this.quitLightbox(); + + if (e.keyCode === 37 || e.keyCode === 39) { + var gotoIndex = Array.prototype.indexOf.call(this.targets, this.target) - (e.keyCode === 37 ? 1 : -1); + + if (gotoIndex > this.targets.length - 1) { + this.target = this.targets[0]; + } else if (gotoIndex < 0) { + this.target = this.targets[this.targets.length - 1]; + } else { + this.target = this.targets[gotoIndex]; + } + + this.loadImage(); + } + } + }, { + key: 'documentClick', + value: function documentClick() { + log.debug('document click'); + + if (this.image !== null && this.target.href === this.image.src) { + log.info('quitting'); + if (this.options.quitOnDocClick) this.quitLightbox(); + } + } + }, { + key: 'quitLightbox', + value: function quitLightbox() { + var _this2 = this; + + log.debug('quitLightbox'); + if (this.image === null) return false; + + _CSSUtil.CSSUtil.setTransitionProperty(this.image, 'opacity ' + this.options.animationSpeed / 1000 + 's linear'); + setTimeout(function () { + // without timeout it's to fast to make it fade and just jumps to 1 instant + _this2.image.style.opacity = 0; + }, 5); + + setTimeout(function () { + _this2.removeImage(); + _this2.inProgress = false; + + _this2.onEndListeners.forEach(function (l) { + return l(); + }); + }, this.options.animationSpeed); + } + }, { + key: 'onImageClick', + value: function onImageClick(event) { + log.debug(event); + var element = event.srcElement.parentElement; + if (!this.isTargetValid(element)) return true; + + event.preventDefault(); + + //if (LightBox.HAS_TOUCH) { + // log.debug('requesting fullscreen'); + // document.body.webkitRequestFullscreen() + //} + + if (this.inProgress) return; + + this.inProgress = false; + + this.onStartListeners.forEach(function (l) { + return l(); + }); + + this.target = element; + + this.loadImage(); + } + }, { + key: 'isTargetValid', + value: function isTargetValid(element) { + if (this.options.restrictTypes === false) return true; + + var validTypes = new RegExp("(\.(" + this.options.allowedTypes + ")$)"); + + return element.tagName.toLowerCase() === 'a' && validTypes.test(element.href); + } + }, { + key: 'loadImage', + value: function loadImage() { + var _this3 = this; + + var direction = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; + + log.info('loadImage'); + if (this.inProgress) return false; + log.debug('not progress'); + + if (this.image !== null) { + log.debug('has current image'); + if (direction !== false && (this.targets.length < 2 || this.options.quitOnEnd === true && (direction === _LightDirection.LightDirection.RIGHT && Array.prototype.indexOf(this.targets, this.target) === 0 || direction === _LightDirection.LightDirection.LEFT && Array.prototype.indexOf(this.targets, this.target) === targets.length - 1))) { + this.quitLightbox(); + return false; + } + + log.debug('unload'); + _CSSUtil.CSSUtil.setTransitionProperty(this.image, 'opacity ' + this.options.animationSpeed / 1000 + 's linear'); + + var transitionArgs = '0px'; + if (direction !== false) { + transitionArgs = 100 * direction - this.swipeDiff + 'px'; + } + + this.image.style.transform = 'translateX(' + transitionArgs + ')'; + + setTimeout(function () { + // without timeout it's to fast to make it fade and just jumps to 1 instant + _this3.image.style.opacity = 0; + }, 5); + + setTimeout(function () { + log.debug('remove from dom'); + _this3.removeImage(); + }, this.options.animationSpeed); + + this.swipeDiff = 0; + } + + this.inProgress = true; + this.onLoadStartListeners.forEach(function (l) { + return l(); + }); + + setTimeout(function () { + log.debug('loadImage in'); + var image = new Image(); + _this3.image = image; + image.onload = function () { + image.id = _this3.options.selectorId; + log.debug('img loaded'); + document.body.appendChild(image); + _this3.setImage(); + + image.style.opacity = 0; + + var interpretedSpeed = _this3.options.animationSpeed / 1000; + log.debug(interpretedSpeed); + _CSSUtil.CSSUtil.setTransitionProperty(image, 'opacity ' + interpretedSpeed + 's ease'); + image.style.transform = 'translateX(0px)'; + + setTimeout(function () { + // without timeout it's to fast to make it fade and just jumps to 1 instant + image.style.opacity = 1; + }, 10); + + setTimeout(function () { + _this3.inProgress = false; + _this3.onLoadEndListeners.forEach(function (l) { + return l(); + }); + }, _this3.options.animationSpeed); + + if (_this3.options.preloadNext) { + var index = Array.prototype.indexOf.call(_this3.targets, _this3.target); + var next = _this3.targets[index + 1]; + + if (next !== null && next !== undefined) { + log.debug('preloading next'); + var nextImg = new Image(); + nextImg.src = next.href; + } else { + log.debug('no preloading'); + } + } + }; + image.src = _this3.target.href; + + _this3.swipeStart = 0; + _this3.swipeEnd = 0; + //this.imagePosLeft = 0; + + if (LightBox.HAS_POINTERS) { + image.addEventListener('pointerup', _this3.imageClickEvent.bind(_this3)); + image.addEventListener('MSPointerUp', _this3.imageClickEvent.bind(_this3)); + } else { + image.addEventListener('click', _this3.imageClickEvent.bind(_this3)); + } + + ['touchstart', 'pointerdown', 'MSPointerDown'].forEach(function (name) { + image.addEventListener(name, _this3.imageTouchStart.bind(_this3)); + }); + + ['touchmove', 'pointermove', 'MSPointerMove'].forEach(function (name) { + image.addEventListener(name, _this3.imageTouchMove.bind(_this3)); + }); + + ['touchend', 'touchcancel', 'pointerup', 'MSPointerUp'].forEach(function (name) { + image.addEventListener(name, _this3.imageTouchEnd.bind(_this3)); + }); + }, this.options.animationSpeed + 100); + } + }, { + key: 'removeImage', + value: function removeImage() { + var image = document.querySelector('#' + this.options.selectorId); + document.body.removeChild(image); + this.image = null; + } + }, { + key: 'imageClickEvent', + value: function imageClickEvent(e) { + e.preventDefault(); + log.debug('click'); + + if (this.options.quitOnImgClick) { + this.quitLightbox(); + return false; + } + + if (this.wasTouched(e)) return true; + + var posX = e.pageX - e.target.offsetLeft; + log.debug(posX); + + var gotoIndex = Array.prototype.indexOf.call(this.targets, this.target) - (this.imageWidth / 2 > posX ? 1 : -1); + + if (gotoIndex > this.targets.length - 1) { + this.target = this.targets[0]; + } else if (gotoIndex < 0) { + this.target = this.targets[this.targets.length - 1]; + } else { + this.target = this.targets[gotoIndex]; + } + + this.loadImage(); + } + }, { + key: 'imageTouchStart', + value: function imageTouchStart(e) { + if (!this.wasTouched(e) || this.options.quitOnImgClick) return true; + + this.swipeStart = e.pageX || e.touches[0].pageX; + } + }, { + key: 'imageTouchMove', + value: function imageTouchMove(e) { + if (!this.wasTouched(e) || this.options.quitOnImgClick) return true; + + e.preventDefault(); + this.swipeEnd = e.pageX || e.touches[0].pageX; + this.swipeDiff = this.swipeStart - this.swipeEnd; + + this.image.style.transform = 'translateX(' + -this.swipeDiff + 'px)'; + //CSSUtil.setTransitionProperty(this.image, 'transform 0s linear'); + } + }, { + key: 'imageTouchEnd', + value: function imageTouchEnd(e) { + if (!this.wasTouched(e) || this.options.quitOnImgClick) return true; + + log.debug(this.swipeDiff); + if (Math.abs(this.swipeDiff) > 50) { + var gotoIndex = Array.prototype.indexOf.call(this.targets, this.target) - (this.swipeDiff < 0 ? 1 : -1); + + if (gotoIndex > this.targets.length - 1) { + this.target = this.targets[0]; + } else if (gotoIndex < 0) { + this.target = this.targets[this.targets.length - 1]; + } else { + this.target = this.targets[gotoIndex]; + } + + var direction = this.swipeDiff > 0 ? _LightDirection.LightDirection.RIGHT : _LightDirection.LightDirection.LEFT; + this.loadImage(direction); + } else { + this.image.style.transform = 'translateX(0px)'; + //CSSUtil.setTransitionProperty(this.image, 'transform '+ options.animationSpeed / 1000 +'s linear'); + } + } + }, { + key: 'setImage', + value: function setImage() { + var _this4 = this; + + if (!this.image) return false; + + var screenWidth = window.innerWidth * 0.8; + var screenHeight = window.innerHeight * 0.9; + + var tmpImage = new Image(); + tmpImage.src = this.image.src; + tmpImage.onload = function () { + _this4.imageWidth = tmpImage.width; + _this4.imageHeight = tmpImage.height; + + if (_this4.imageWidth > screenWidth || _this4.imageHeight > screenHeight) { + var ratio = _this4.imageWidth / _this4.imageHeight > screenWidth / screenHeight ? _this4.imageWidth / screenWidth : _this4.imageHeight / screenHeight; + _this4.imageWidth /= ratio; + _this4.imageHeight /= ratio; + } + + _this4.image.style.width = _this4.imageWidth + 'px'; + _this4.image.style.height = _this4.imageHeight + 'px'; + _this4.image.style.top = (window.innerHeight - _this4.imageHeight) / 2 + 'px'; + _this4.image.style.left = (window.innerWidth - _this4.imageWidth) / 2 + 'px'; + }; + } + }, { + key: 'wasTouched', + value: function wasTouched(event) { + if (LightBox.HAS_TOUCH) return true; + + if (!LightBox.HAS_POINTERS || typeof event === 'undefined' || typeof event.pointerType === 'undefined') return false; + + if (typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined') { + if (event.MSPOINTER_TYPE_MOUSE !== event.pointerType) return true; + } else { + if (event.pointerType !== 'mouse') return true; + } + + return false; + } + }, { + key: 'switchToIndex', + value: function switchToIndex(index) { + if (index >= 0 && index < this.targets.length) { + this.target = this.targets[index]; + this.loadImage(); + } + } + }, { + key: 'windowResizeListener', + value: function windowResizeListener() { + log.debug('resized'); + this.setImage(); + } + }, { + key: 'addOnStartListener', + value: function addOnStartListener(listener) { + this.onStartListeners.push(listener); + } + }, { + key: 'addOnEndListener', + value: function addOnEndListener(listener) { + this.onEndListeners.push(listener); + } + }, { + key: 'addOnLoadStartListener', + value: function addOnLoadStartListener(listener) { + this.onLoadStartListeners.push(listener); + } + }, { + key: 'addOnLoadEndListener', + value: function addOnLoadEndListener(listener) { + this.onLoadEndListeners.push(listener); + } + }, { + key: 'registerPlugin', + value: function registerPlugin(plugin) { + plugin.register(this); + } + }]); + + return LightBox; + }(); + + exports.default = LightBox; + + LightBox.HAS_TOUCH = 'ontouchstart' in window; + LightBox.HAS_POINTERS = window.navigator.pointerEnabled || window.navigator.msPointerEnabled; + module.exports = exports['default']; + +/***/ }, +/* 1 */ +/***/ function(module, exports) { + + 'use strict'; + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + /** + * Created by Victor Häggqvist on 1/12/16. + */ + + var CSSUtil = exports.CSSUtil = function () { + function CSSUtil() { + _classCallCheck(this, CSSUtil); + } + + _createClass(CSSUtil, null, [{ + key: 'setTransitionProperty', + + /** + * transion need to be set on property + * + * using key-value dont work + * + * @param ele DOMElement + * @param value + */ + value: function setTransitionProperty(ele, value) { + var style = ele.style; + if (style.transition === '') { + style.transition = value; + return; + } + if (style.WebkitTransition === '') { + style.WebkitTransition = value; + return; + } + if (style.MozTransition === '') { + style.MozTransition = value; + return; + } + if (style.OTransition === '') { + style.OTransition = value; + } + } + }, { + key: 'cssTransitionSupport', + value: function cssTransitionSupport() { + var d = document.body || document.documentElement, + s = d.style; + if (s.WebkitTransition === '') return '-webkit-'; + if (s.MozTransition === '') return '-moz-'; + if (s.OTransition === '') return '-o-'; + if (s.transition === '') return ''; + return false; + } + }, { + key: 'cssTransitionTranslateX', + value: function cssTransitionTranslateX(element, positionX, speed) { + var prefix = CSSUtil.cssTransitionSupport(); + element.style[prefix + 'transform'] = 'translateX(' + positionX + ')'; + element.style[prefix + 'transition'] = prefix + 'transform ' + speed + 's linear'; + } + }]); + + return CSSUtil; + }(); + + CSSUtil.isCssTransitionSupport = CSSUtil.cssTransitionSupport() !== false; + +/***/ }, +/* 2 */ +/***/ function(module, exports) { + + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + /** + * Created by Victor Häggqvist on 1/14/16. + */ + + var LightDirection = exports.LightDirection = function LightDirection() { + _classCallCheck(this, LightDirection); + }; + + LightDirection.LEFT = 1; + LightDirection.RIGHT = -1; + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module) {'use strict'; + + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; + + /* + * loglevel - https://github.com/pimterry/loglevel + * + * Copyright (c) 2013 Tim Perry + * Licensed under the MIT license. + */ + (function (root, definition) { + "use strict"; + + if (( false ? 'undefined' : _typeof(module)) === 'object' && module.exports && "function" === 'function') { + module.exports = definition(); + } else if ("function" === 'function' && _typeof(__webpack_require__(5)) === 'object') { + !(__WEBPACK_AMD_DEFINE_FACTORY__ = (definition), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else { + root.log = definition(); + } + })(undefined, function () { + "use strict"; + + var noop = function noop() {}; + var undefinedType = "undefined"; + + function realMethod(methodName) { + if ((typeof console === 'undefined' ? 'undefined' : _typeof(console)) === undefinedType) { + return false; // We can't build a real method without a console to log to + } else if (console[methodName] !== undefined) { + return bindMethod(console, methodName); + } else if (console.log !== undefined) { + return bindMethod(console, 'log'); + } else { + return noop; + } + } + + function bindMethod(obj, methodName) { + var method = obj[methodName]; + if (typeof method.bind === 'function') { + return method.bind(obj); + } else { + try { + return Function.prototype.bind.call(method, obj); + } catch (e) { + // Missing bind shim or IE8 + Modernizr, fallback to wrapping + return function () { + return Function.prototype.apply.apply(method, [obj, arguments]); + }; + } + } + } + + // these private functions always need `this` to be set properly + + function enableLoggingWhenConsoleArrives(methodName, level, loggerName) { + return function () { + if ((typeof console === 'undefined' ? 'undefined' : _typeof(console)) !== undefinedType) { + replaceLoggingMethods.call(this, level, loggerName); + this[methodName].apply(this, arguments); + } + }; + } + + function replaceLoggingMethods(level, loggerName) { + /*jshint validthis:true */ + for (var i = 0; i < logMethods.length; i++) { + var methodName = logMethods[i]; + this[methodName] = i < level ? noop : this.methodFactory(methodName, level, loggerName); + } + } + + function defaultMethodFactory(methodName, level, loggerName) { + /*jshint validthis:true */ + return realMethod(methodName) || enableLoggingWhenConsoleArrives.apply(this, arguments); + } + + var logMethods = ["trace", "debug", "info", "warn", "error"]; + + function Logger(name, defaultLevel, factory) { + var self = this; + var currentLevel; + var storageKey = "loglevel"; + if (name) { + storageKey += ":" + name; + } + + function persistLevelIfPossible(levelNum) { + var levelName = (logMethods[levelNum] || 'silent').toUpperCase(); + + // Use localStorage if available + try { + window.localStorage[storageKey] = levelName; + return; + } catch (ignore) {} + + // Use session cookie as fallback + try { + window.document.cookie = encodeURIComponent(storageKey) + "=" + levelName + ";"; + } catch (ignore) {} + } + + function getPersistedLevel() { + var storedLevel; + + try { + storedLevel = window.localStorage[storageKey]; + } catch (ignore) {} + + if ((typeof storedLevel === 'undefined' ? 'undefined' : _typeof(storedLevel)) === undefinedType) { + try { + var cookie = window.document.cookie; + var location = cookie.indexOf(encodeURIComponent(storageKey) + "="); + if (location) { + storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1]; + } + } catch (ignore) {} + } + + // If the stored level is not valid, treat it as if nothing was stored. + if (self.levels[storedLevel] === undefined) { + storedLevel = undefined; + } + + return storedLevel; + } + + /* + * + * Public API + * + */ + + self.levels = { "TRACE": 0, "DEBUG": 1, "INFO": 2, "WARN": 3, + "ERROR": 4, "SILENT": 5 }; + + self.methodFactory = factory || defaultMethodFactory; + + self.getLevel = function () { + return currentLevel; + }; + + self.setLevel = function (level, persist) { + if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) { + level = self.levels[level.toUpperCase()]; + } + if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) { + currentLevel = level; + if (persist !== false) { + // defaults to true + persistLevelIfPossible(level); + } + replaceLoggingMethods.call(self, level, name); + if ((typeof console === 'undefined' ? 'undefined' : _typeof(console)) === undefinedType && level < self.levels.SILENT) { + return "No console available for logging"; + } + } else { + throw "log.setLevel() called with invalid level: " + level; + } + }; + + self.setDefaultLevel = function (level) { + if (!getPersistedLevel()) { + self.setLevel(level, false); + } + }; + + self.enableAll = function (persist) { + self.setLevel(self.levels.TRACE, persist); + }; + + self.disableAll = function (persist) { + self.setLevel(self.levels.SILENT, persist); + }; + + // Initialize with the right level + var initialLevel = getPersistedLevel(); + if (initialLevel == null) { + initialLevel = defaultLevel == null ? "WARN" : defaultLevel; + } + self.setLevel(initialLevel, false); + } + + /* + * + * Package-level API + * + */ + + var defaultLogger = new Logger(); + + var _loggersByName = {}; + defaultLogger.getLogger = function getLogger(name) { + if (typeof name !== "string" || name === "") { + throw new TypeError("You must supply a name when creating a logger."); + } + + var logger = _loggersByName[name]; + if (!logger) { + logger = _loggersByName[name] = new Logger(name, defaultLogger.getLevel(), defaultLogger.methodFactory); + } + return logger; + }; + + // Grab the current global log variable in case of overwrite + var _log = (typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== undefinedType ? window.log : undefined; + defaultLogger.noConflict = function () { + if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== undefinedType && window.log === defaultLogger) { + window.log = _log; + } + + return defaultLogger; + }; + + return defaultLogger; + }); + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module))) + +/***/ }, +/* 4 */ +/***/ function(module, exports) { + + "use strict"; + + module.exports = function (module) { + if (!module.webpackPolyfill) { + module.deprecate = function () {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + }; + +/***/ }, +/* 5 */ +/***/ function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__; + + /* WEBPACK VAR INJECTION */}.call(exports, {})) + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/demo/LightBox.Navigation.js b/demo/LightBox.Navigation.js new file mode 100644 index 0000000..abcc5b4 --- /dev/null +++ b/demo/LightBox.Navigation.js @@ -0,0 +1,138 @@ +var LightBox = LightBox || {}; LightBox["Navigation"] = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports) { + + 'use strict'; + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + /** + * @author Victor Häggqvist + * @since 1/15/16 + */ + + var Navigation = function () { + function Navigation() { + _classCallCheck(this, Navigation); + } + + _createClass(Navigation, [{ + key: 'register', + value: function register(lightbox) { + this.lightbox = lightbox; + lightbox.addOnStartListener(this.showNavigation.bind(this)); + lightbox.addOnEndListener(this.hideNavigation.bind(this)); + lightbox.addOnLoadEndListener(this.updateNavigation.bind(this)); + } + }, { + key: 'showNavigation', + value: function showNavigation() { + var _this = this; + + this.sink = document.createElement('div'); + this.sink.id = 'imagelightbox-nav-sink'; + this.nav = document.createElement('div'); + this.nav.id = 'imagelightbox-nav'; + this.sink.appendChild(this.nav); + + Array.prototype.forEach.call(this.lightbox.targets, function (_) { + _this.nav.appendChild(document.createElement('a')); + }); + + document.body.appendChild(this.sink); + + var navItems = this.nav.querySelectorAll('a'); + Array.prototype.forEach.call(navItems, function (item, i) { + ['click', 'touchend'].forEach(function (name) { + item.addEventListener(name, _this.navClick.bind(_this, i)); + }); + }); + + // make the nav actually centered, flex center dont make it + var rect = this.nav.getBoundingClientRect(); + var diff = rect.width / 2; + this.nav.style.marginLeft = '-' + diff + 'px'; + } + }, { + key: 'updateNavigation', + value: function updateNavigation() { + Array.prototype.forEach.call(this.nav.childNodes, function (n) { + n.classList.remove('active'); + }); + + var current = Array.prototype.indexOf.call(this.lightbox.targets, this.lightbox.target); + this.nav.childNodes[current].classList.add('active'); + } + }, { + key: 'hideNavigation', + value: function hideNavigation() { + try { + document.body.removeChild(this.sink); + } catch (e) {} + } + }, { + key: 'navClick', + value: function navClick(index, e) { + e.stopPropagation(); + e.cancelBubble = true; + this.lightbox.switchToIndex(index); + } + }]); + + return Navigation; + }(); + + exports.default = Navigation; + module.exports = exports['default']; + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/demo/LightBox.Overlay.js b/demo/LightBox.Overlay.js new file mode 100644 index 0000000..e52a586 --- /dev/null +++ b/demo/LightBox.Overlay.js @@ -0,0 +1,96 @@ +var LightBox = LightBox || {}; LightBox["Overlay"] = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports) { + + 'use strict'; + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + /** + * @author Victor Häggqvist + * @since 2016-01-14 + */ + + var Overlay = function () { + function Overlay() { + _classCallCheck(this, Overlay); + + this.element = document.createElement('div'); + this.element.id = 'imagelightbox-overlay'; + } + + _createClass(Overlay, [{ + key: 'register', + value: function register(lightbox) { + lightbox.addOnStartListener(this.overlayOn.bind(this)); + lightbox.addOnEndListener(this.overlayOff.bind(this)); + } + }, { + key: 'overlayOn', + value: function overlayOn() { + document.body.appendChild(this.element); + } + }, { + key: 'overlayOff', + value: function overlayOff() { + document.body.removeChild(this.element); + } + }]); + + return Overlay; + }(); + + exports.default = Overlay; + module.exports = exports['default']; + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/demo/index.html b/demo/index.html index 7bc02cd..d1e167c 100644 --- a/demo/index.html +++ b/demo/index.html @@ -9,99 +9,214 @@ Image Lightbox Demo - - + -Fork me on GitHub + +
-

Image LightboxResponsive & Touch-Friendly

- -

View source of demos on Github.

+

Image LightboxResponsive & Touch-Friendly

+

View source of demos on Github.

-

With activity indication

-
    -
  • Sunrise
  • -
  • transalpina
  • -
  • Water, rocks, sun, sea and cloud!
  • -
-

With overlay & activity indication

-
    -
  • Sunday nature
  • -
  • Light after Darkness
  • -
  • A Dragonfly!
  • -
-

With "close" button & activity indication

-
    -
  • Marumi DHG Macro 200 + Tamron 17-50mm. 2.8 -
  • -
  • Times Square in the rain
  • -
  • Manchester City Centre - Northern Quarter Viewed from the 15th Floor
  • -
-

With caption & activity indication

-
    -
  • City sunset
  • -
  • City Lights
  • -
  • Ready . . . Set ....................
  • -
-

With navigation & activity indication

-
    -
  • Lights ou
  • -
  • Golden Gate Bridge
  • -
  • Red Spruce Peak
  • -
-

Combination

-
    -
  • The Lou Ruvo Center for Brain Health, Las Vegas, Nevada
  • -
  • Nightfall over South End of Stockholm
  • -
  • Grand Canyon Morning #dailyshoot
  • -
+ + +

Core

+ + + +

With activity indication

+ + + +

With overlay & activity indication

+ + + +

With "close" button & activity indication

+ + + +

With caption & activity indication

+ + + +

With navigation & activity indication

+ + + +

Combination

+ + +
- - - - + + + + + + diff --git a/demotemplate.html.jinja b/demotemplate.html.jinja new file mode 100644 index 0000000..e69de29 diff --git a/dist/touch-imagelightbox.css b/dist/touch-imagelightbox.css index cb28641..f1ca31d 100644 --- a/dist/touch-imagelightbox.css +++ b/dist/touch-imagelightbox.css @@ -1,269 +1 @@ -html { - -ms-touch-action: manipulation; - touch-action: manipulation; -} - -#imagelightbox { - -ms-touch-action: none; - touch-action: none; - -moz-box-shadow: rgba(0, 0, 0, 0.75) 0 0 50px; - -webkit-box-shadow: rgba(0, 0, 0, 0.75) 0 0 50px; - box-shadow: rgba(0, 0, 0, 0.75) 0 0 50px; - cursor: pointer; - position: fixed; - z-index: 10000; -} - -#imagelightbox-loading, -#imagelightbox-loading div { - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; -} - -#imagelightbox-loading { - -moz-box-shadow: rgba(0, 0, 0, 0.75) 0 0 40px; - -webkit-box-shadow: rgba(0, 0, 0, 0.75) 0 0 40px; - box-shadow: rgba(0, 0, 0, 0.75) 0 0 40px; - background: #444; - background: rgba(0, 0, 0, 0.5); - height: 20px; - left: 50%; - margin: -20px 0 0 -20px; - padding: 10px; - position: fixed; - top: 50%; - width: 20px; - z-index: 10003; -} -#imagelightbox-loading div { - -moz-animation: imagelightbox-loading .5s ease infinite; - -o-animation: imagelightbox-loading .5s ease infinite; - -webkit-animation: imagelightbox-loading .5s ease infinite; - animation: imagelightbox-loading .5s ease infinite; - background-color: #fff; - height: 20px; - width: 20px; -} - -@-webkit-keyframes imagelightbox-loading { - 0% { - opacity: .5; - -webkit-transform: scale(0.75); - } - - 50% { - opacity: 1; - -webkit-transform: scale(1); - } - - 100% { - opacity: .5; - -webkit-transform: scale(0.75); - } -} -@-moz-keyframes imagelightbox-loading { - 0% { - opacity: .5; - -moz-transform: scale(0.75); - } - - 50% { - opacity: 1; - -moz-transform: scale(1); - } - - 100% { - opacity: .5; - -moz-transform: scale(0.75); - } -} -@-o-keyframes imagelightbox-loading { - 0% { - opacity: .5; - -o-transform: scale(0.75); - } - - 50% { - opacity: 1; - -o-transform: scale(1); - } - - 100% { - opacity: .5; - -o-transform: scale(0.75); - } -} -@keyframes imagelightbox-loading { - 0% { - opacity: .5; - transform: scale(0.75); - } - - 50% { - opacity: 1; - transform: scale(1); - } - - 100% { - opacity: .5; - transform: scale(0.75); - } -} -#imagelightbox-overlay { - background: #fff; - background: rgba(255, 255, 255, 0.9); - bottom: 0; - left: 0; - position: fixed; - right: 0; - top: 0; - z-index: 9998; -} - -#imagelightbox-close { - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; - background-color: #666; - height: 40px; - position: fixed; - right: 40px; - text-align: left; - text-indent: -9999px; - top: 40px; - -moz-transition: color .3s ease; - -ms-transition: color .3s ease; - -o-transition: color .3s ease; - -webkit-transition: color .3s ease; - transition: color .3s ease; - width: 40px; - z-index: 10002; -} -#imagelightbox-close:hover { - background-color: #111; -} -#imagelightbox-close:before, #imagelightbox-close:after { - background-color: #fff; - bottom: 20%; - content: ''; - left: 50%; - margin-left: -1px; - position: absolute; - top: 20%; - width: 2px; -} -#imagelightbox-close:before { - -moz-transform: rotate(45deg); - -ms-transform: rotate(45deg); - -webkit-transform: rotate(45deg); - transform: rotate(45deg); -} -#imagelightbox-close:after { - -moz-transform: rotate(-45deg); - -ms-transform: rotate(-45deg); - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); -} - -#imagelightbox-caption { - background-color: #666; - bottom: 0; - color: #fff; - left: 0; - padding: 10px; - position: fixed; - right: 0; - text-align: center; - z-index: 10001; -} - -#imagelightbox-nav { - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; - -moz-transform: translateX(-50%); - -ms-transform: translateX(-50%); - -webkit-transform: translateX(-50%); - transform: translateX(-50%); - background-color: #444; - background-color: rgba(0, 0, 0, 0.5); - bottom: 60px; - left: 50%; - padding: 5px 2px 1px; - position: fixed; - z-index: 10001; -} -#imagelightbox-nav a { - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; - border: 1px solid #fff; - display: inline-block; - height: 20px; - margin: 0 5px; - width: 20px; -} -#imagelightbox-nav .active { - background-color: #fff; -} - -#imagelightbox-loading, -#imagelightbox-overlay, -#imagelightbox-close, -#imagelightbox-caption, -#imagelightbox-nav { - -moz-animation: fade-in .25s linear; - -o-animation: fade-in .25s linear; - -webkit-animation: fade-in .25s linear; - animation: fade-in .25s linear; -} - -@-webkit-keyframes fade-in { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} -@-moz-keyframes fade-in { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} -@-o-keyframes fade-in { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} -@keyframes fade-in { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} -@media only screen and (max-width: 660px) { - #imagelightbox-close { - right: 20px; - top: 20px; - } - - #imagelightbox-nav { - bottom: 20px; - } -} - -/*# sourceMappingURL=touch-imagelightbox.css.map */ +#imagelightbox-loading,#imagelightbox-loading div{border-radius:50%}#imagelightbox-loading{box-shadow:rgba(0,0,0,.75)0 0 40px;background:rgba(0,0,0,.5);height:20px;left:50%;margin:-20px 0 0 -20px;padding:10px;position:fixed;top:50%;width:20px;z-index:10003;animation:fade-in .25s linear}#imagelightbox-loading div{animation:imagelightbox-loading .5s ease infinite;background-color:#fff;height:20px;width:20px}@keyframes imagelightbox-loading{0%{opacity:.5;transform:scale(.75)}50%{opacity:1;transform:scale(1)}100%{opacity:.5;transform:scale(.75)}}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}#imagelightbox-overlay{background:rgba(255,255,255,.9);bottom:0;left:0;position:fixed;right:0;top:0;z-index:9998;animation:fade-in .25s linear}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}#imagelightbox-close{border-radius:50%;background-color:#666;height:40px;position:fixed;right:40px;text-align:left;text-indent:-9999px;top:40px;transition:color .3s ease;width:40px;z-index:10002;cursor:pointer;animation:fade-in .25s linear}#imagelightbox-close:hover{background-color:#111}#imagelightbox-close:before,#imagelightbox-close:after{background-color:#fff;bottom:20%;content:'';left:50%;margin-left:-1px;position:absolute;top:20%;width:2px}#imagelightbox-close:before{rotate:45deg}#imagelightbox-close:after{rotate:-45deg}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}@media only screen and (max-width:660px){#imagelightbox-close{right:20px;top:20px}}#imagelightbox-nav-sink{display:flex;justify-content:center}#imagelightbox-nav{border-radius:20px;animation:fade-in .25s linear;background-color:rgba(0,0,0,.5);bottom:60px;padding:5px 2px 1px;position:fixed;z-index:10001}#imagelightbox-nav a{border-radius:50%;border:1px solid #fff;display:inline-block;height:20px;margin:0 5px;width:20px}#imagelightbox-nav .active{background-color:#fff}@media only screen and (max-width:660px){#imagelightbox-nav{bottom:20px}}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}#imagelightbox-caption{background-color:#666;bottom:0;color:#fff;left:0;padding:10px;position:fixed;right:0;text-align:center;z-index:10001;animation:fade-in .25s linear}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}html{-ms-touch-action:manipulation;touch-action:manipulation}#imagelightbox{-ms-touch-action:none;touch-action:none;box-shadow:rgba(0,0,0,.75)0 0 50px;cursor:pointer;position:fixed;z-index:10000} \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..dff940f --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,216 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/LightBox.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/LightBox.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/LightBox" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/LightBox" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 0000000..a57f144 --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,50 @@ +Core API +======== + +A `LightBox.Core` object have the following public API that can be considered stable. I you are creating a plugin you might want to check :doc:`hacking`. + + +**quitLightbox()** +Exit and remove the lightbox + + +**switchToIndex(** index **)** +Switch to image *index* in targets array + +index + **int** + + +**addOnStartListener(** listener **)** +Add a OnStartListener + +listener + **function** + + +**addOnEndListener(** listener **)** +Add a OnEndListener + +listener + **function** + + +**addOnLoadStartListener(** listener **)** +Add a OnLoadStartListener + +listener + **function** + + +**addOnLoadEndListener(** listener **)** +Add a OnLoadEndListener + +listener + **function** + + +**registerPlugin(** plugin **)** +Register a plugin + +plugin + **Object** diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..3d87f00 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# LightBox documentation build configuration file, created by +# sphinx-quickstart on Sat Jan 16 00:40:58 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'Image LightBox' +copyright = '2016, Victor Häggqvist' +author = 'Victor Häggqvist' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.2.0' +# The full version, including alpha/beta/rc tags. +release = '0.2.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# html_theme = 'sphinx_rtd_theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'LightBoxdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'LightBox.tex', 'LightBox Documentation', + 'Victor Häggqvist', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'lightbox', 'LightBox Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'LightBox', 'LightBox Documentation', + author, 'LightBox', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/docs/hacking.rst b/docs/hacking.rst new file mode 100644 index 0000000..14d3810 --- /dev/null +++ b/docs/hacking.rst @@ -0,0 +1,20 @@ +Hacking +======= +A plugin are expected to implement a function :code:`register(lightbox)` which will be called when passed the plugin to `LightBox.Core::registerPlugin`. See the full API at :doc:`api`. + +A basic plugin could look like this. + +.. code-block:: js + :caption: LightBox.Contrib.MyExitPlugin.js + + class MyExitPlugin { + + register(lightbox) { + lightbox.addOnEndListener(this.exited.bind(this)); + } + + exited() { + console.log('lightbox exited'); + } + + } diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..5c34224 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,26 @@ +.. LightBox documentation master file, created by + sphinx-quickstart on Sat Jan 16 00:40:58 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. include:: ../README.rst + + +Contents: + +.. toctree:: + :maxdepth: 2 + + plugins + api + hacking + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/docs/plugins.rst b/docs/plugins.rst new file mode 100644 index 0000000..f40112d --- /dev/null +++ b/docs/plugins.rst @@ -0,0 +1,25 @@ +Plugins +======= + +The plugins currently available in the standard distribution of Image LightBox are the following. + +ActivityIndicator + Displays an indicator when images are loading. + +Overlay + Overlays the page with a semitransparent layer when images are displayed. + +CloseButton + Displays a button in the top right corner that one should press to exit the lightbox + +Captions + Assuming a gallery of images with markup such as bellow, the `alt` attribute of the `img` tag will be used for caption of the image. + + .. code-block:: html + + + My Caption + + +Navigation + Displays navigation dots that can be used to jump between images. diff --git a/gulpfile.js b/gulpfile.js index c081b81..8fb1871 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -8,6 +8,7 @@ var csso = require('gulp-csso'); var size = require('gulp-size'); var uglify = require('gulp-uglify'); var webpack = require('webpack-stream'); +var concat = require('gulp-concat'); gulp.task('style', function () { return gulp.src('./style/touch-imagelightbox.scss') @@ -50,11 +51,39 @@ gulp.task('pack', function() { .pipe(gulp.dest('./demo')); }); -gulp.task('default', ['pack']); - gulp.task('watch', function () { webpackOptions.watch = true; gulp.src('') .pipe(webpack(webpackOptions)) .pipe(gulp.dest('./demo')); }); + +gulp.task('lint', function() { + return gulp.src('./src/**/*.js') + .pipe(eslint()) + .pipe(eslint.format()) + .pipe(eslint.failAfterError()); +}); + + +gulp.task('uglify', ['pack'], function() { + return gulp.src('./demo/LightBox.*.js') + .pipe(uglify()) + .pipe(gulp.dest('dist')); +}); + +gulp.task('buildjs', ['uglify'], function() { + return gulp.src(['./dist/LightBox.*.js', '!./dist/LightBox.Core.js', '!./dist/LightBox.Plugins.js']) + .pipe(concat('LightBox.Plugins.js')) + .pipe(gulp.dest('./dist')); +}); + +gulp.task('csso', ['style'], function() { + return gulp.src('./demo/touch-imagelightbox.css') + .pipe(csso()) + .pipe(gulp.dest('./dist')); +}); + +gulp.task('build', ['buildjs','csso']); + +gulp.task('default', ['pack']); diff --git a/package.json b/package.json index 960874a..de61ad6 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "gulp": "^3.9.0", "gulp-autoprefixer": "^3.1.0", "gulp-babel": "^6.1.1", + "gulp-concat": "^2.6.0", "gulp-csso": "^1.0.1", "gulp-eslint": "^1.1.1", "gulp-rename": "^1.2.2", diff --git a/prepdemoimages.py b/prepdemoimages.py new file mode 100755 index 0000000..da881c1 --- /dev/null +++ b/prepdemoimages.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +import requests +from collections import namedtuple +from jinja2 import FileSystemLoader, Environment + +template_env = Environment(loader=FileSystemLoader('.')) +template = template_env.get_template('demotemplate.html.jinja') + +Demo = namedtuple('Demo', ['name', 'images']) + +demos = [ + Demo(name='Core', images=[]), + Demo(name='With activity indication', images=[]), + Demo(name='With overlay & activity indication', images=[]), + Demo(name='With "close" button & activity indication', images=[]), + Demo(name='With caption & activity indication', images=[]), + Demo(name='With navigation & activity indication', images=[]), + Demo(name='Combination', images=[]), +] + +maxnum = len(demos)*3 + +def put_image(img): + done = False + for d in demos: + if len(d.images) == 3: + done = True + else: + d.images.append(img) + if len(d.images) == 4: + done = True + else: + return False + return done + + +headers = { + 'Authorization': 'Client-ID 3004ee20c6b4822a4ab148506fef3be12eab826823b6d15a84dcdb4dec086f7c' +} +r = requests.get('https://api.unsplash.com/photos?per_page='+str(maxnum), headers=headers) + +images = r.json() +for img in images: + put_image(img) + +print(template.render(demos=demos)) diff --git a/src/CSSUtil.js b/src/CSSUtil.js index c4172b8..962fe59 100644 --- a/src/CSSUtil.js +++ b/src/CSSUtil.js @@ -45,11 +45,9 @@ export class CSSUtil { } static cssTransitionTranslateX(element, positionX, speed) { - let options = {}; let prefix = CSSUtil.cssTransitionSupport(); element.style[prefix + 'transform'] = 'translateX(' + positionX + ')'; element.style[prefix + 'transition'] = prefix + 'transform ' + speed + 's linear'; - //element.style = Object.assign(options, element.style); } } -- cgit v1.2.3