├── .gitignore ├── LICENCE ├── README.md ├── bower_components └── webcomponentsjs │ ├── .bower.json │ ├── .eslintrc.json │ ├── .gitattributes │ ├── .github │ └── CODEOWNERS │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE.md │ ├── README.md │ ├── bower.json │ ├── closure-output.txt │ ├── custom-elements-es5-adapter.js │ ├── entrypoints │ ├── custom-elements-es5-adapter-index.js │ ├── webcomponents-hi-ce-index.js │ ├── webcomponents-hi-index.js │ ├── webcomponents-hi-sd-ce-index.js │ ├── webcomponents-hi-sd-ce-pf-index.js │ ├── webcomponents-hi-sd-index.js │ └── webcomponents-sd-ce-index.js │ ├── externs │ └── webcomponents.js │ ├── gulpfile.js │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── post-polyfill.js │ ├── pre-polyfill.js │ ├── promise.js │ └── unresolved.js │ ├── tests │ ├── ce-import-upgrade-async.html │ ├── ce-import-upgrade.html │ ├── ce-import.html │ ├── ce-upgrade-order.html │ ├── ce-upgradedocumenttree.html │ ├── dev-loader-swizzled.html │ ├── dev-loader.html │ ├── force-polyfills.html │ ├── imports │ │ ├── a1-define.html │ │ ├── a1-import.html │ │ ├── a1-instance.html │ │ ├── a1-reference.html │ │ ├── csp-import-1.html │ │ ├── csp-import-2.html │ │ ├── csp-script-1.js │ │ ├── csp-script-2.js │ │ ├── current-script.js │ │ ├── element-import-a.html │ │ ├── element-import-b.html │ │ ├── element-import.html │ │ ├── import-file.html │ │ ├── import-upgrade-order.html │ │ ├── script-1.html │ │ ├── script-2.html │ │ ├── simple-element-es5.html │ │ └── simple-element.html │ ├── integration-es5.html │ ├── integration.html │ ├── load.html │ ├── promise.html │ ├── runner.html │ ├── smoke.html │ ├── template-and-CE.html │ └── template-and-imports.html │ ├── wct.conf.json │ ├── webcomponents-hi-ce.js │ ├── webcomponents-hi-ce.js.map │ ├── webcomponents-hi-sd-ce.js │ ├── webcomponents-hi-sd-ce.js.map │ ├── webcomponents-hi-sd.js │ ├── webcomponents-hi-sd.js.map │ ├── webcomponents-hi.js │ ├── webcomponents-hi.js.map │ ├── webcomponents-lite.js │ ├── webcomponents-lite.js.map │ ├── webcomponents-loader.js │ ├── webcomponents-sd-ce.js │ └── webcomponents-sd-ce.js.map ├── dist ├── img-2.es5.js └── img-2.js ├── index.html ├── package-lock.json ├── package.json └── src └── img-2.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Leon Revill 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Img2 2 | Replace `` elements with `` to automatically pre-cache images and improve page performance. Displaying even a small number of high-quality images on a web page can be difficult to do without causing jank or slowing down the initial load of the page. This is why clever developers employ techniques with JavaScript to pre-cache images and lazy load them as they become visible on the user's screen. 3 | 4 | Img2 makes this super easy, just swap out your `` elements with `` and let it do the work for you. 5 | 6 | ## Img2 will automatically: 7 | 8 | 1. Only render initial images which are visible to the user 9 | 2. Pre-cache all other images off the main thread with a Web Worker 10 | 3. Lazy load images as they enter the user's viewport instantly from the cache 11 | 4. Display a blurred preview image while the user waits for initial images 12 | 13 | ___ 14 | 15 | [Live Demo](https://revillweb.github.io/img-2/) 16 | 17 | ___ 18 | 19 | ## Install 20 | 21 | `npm install --save img-2` 22 | 23 | ## Usage 24 | 25 | You can include Img2 into your project in various ways: 26 | 27 | ### As a ES6 Module 28 | 29 | `import "img-2"` 30 | 31 | ### Via ` 35 | ``` 36 | 37 | ### Via ` 41 | ``` 42 | 43 | Then you simply use the `` element in place of an `` element. 44 | 45 | ```html 46 | 47 |

Cat Photos

48 | 49 | 50 | ``` 51 | 52 | ### Attributes 53 | 54 | There are currently five attributes available on Img2, three of which are required. 55 | 56 | #### src 57 | 58 | The full-size source image to be pre-cached and lazy loaded. 59 | 60 | #### width & height 61 | 62 | Both of these are required to figure out the position of the image on screen to then determine if the image should be loaded right away or lazily loaded. 63 | 64 | #### src-preview 65 | 66 | A really small representation of the full-size image (e.g. 10px by 10px). This image will be displayed as a blurred preview while the full-size image is downloading if the image hasn't already been pre-cached. 67 | 68 | #### alt 69 | 70 | The alt text for the image, just maps on to the `alt` attribute of the `` element used in the component. 71 | 72 | ## Supported platforms & 73 | 74 | | Platform Support | Chrome | Chrome for Android | Firefox | Safari | iOS Safari | Edge | IE 11 | 75 | | ------------------ |:------:|:------:|:------:|:------:|:------:|:----:|:-----:| 76 | | Supported |✓|✓|✓|✓|✓|✓|✓|✓| 77 | | Polyfill(s) Required |-|-|✓|✓|✓|✓|✓|✓| 78 | 79 | Img-2 uses the [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to detect when an image is in the users visible viewport. For Safari and IE 11 you'll need to load the Intersection Observer polyfill. 80 | 81 | ```html 82 | 83 | ``` 84 | 85 | Img-2 uses Custom Elements and Shadow DOM so for FireFox, Edge and IE11 you'll need to use the webcomponents-loader from [webcomponentsjs](https://github.com/webcomponents/webcomponentsjs). 86 | 87 | ```html 88 | 89 | ``` 90 | 91 | If you need to support IE11 which doesn't support ES6 you'll want to conditionally load `img-2.es5.js`. 92 | 93 | ```js 94 | var supportsES6 = function() { 95 | try { 96 | new Function("(a = 0) => a"); 97 | return true; 98 | } 99 | catch (err) { 100 | return false; 101 | } 102 | }(); 103 | 104 | var $script = document.createElement("script"); 105 | $script.setAttribute("defer", ""); 106 | $script.src = (supportsES6 === true) ? "dist/img-2.js" : "dist/img-2.es5.js"; 107 | document.head.appendChild($script); 108 | ``` 109 | 110 | Take a look at `index.html` in the root of this repo for further examples. 111 | 112 | ### Contributing 113 | 114 | Any contributions are welcome, feel free to submit a pull request for review. 115 | 116 | ### To Do 117 | 118 | 1. Add srcset support 119 | 2. Consider A11y 120 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webcomponentsjs", 3 | "description": "Web components polyfill", 4 | "main": "webcomponents.js", 5 | "homepage": "http://webcomponents.org", 6 | "authors": [ 7 | "The Polymer Authors" 8 | ], 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/webcomponents/webcomponentsjs.git" 12 | }, 13 | "keywords": [ 14 | "webcomponents", 15 | "web-components", 16 | "polyfill", 17 | "shim" 18 | ], 19 | "license": "BSD-3-Clause", 20 | "ignore": [], 21 | "devDependencies": { 22 | "web-component-tester": "^v6.0.0" 23 | }, 24 | "version": "1.1.1", 25 | "_release": "1.1.1", 26 | "_resolution": { 27 | "type": "version", 28 | "tag": "v1.1.1", 29 | "commit": "2bb2c2c92008d2354b75c0fa633ea404c5c999c3" 30 | }, 31 | "_source": "https://github.com/Polymer/webcomponentsjs.git", 32 | "_target": "^1.1.1", 33 | "_originalSource": "webcomponentsjs", 34 | "_direct": true 35 | } -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "env": { 4 | "browser": true, 5 | "es6": true 6 | }, 7 | "parserOptions": { 8 | "ecmaVersion": 6, 9 | "sourceType": "module" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/.gitattributes: -------------------------------------------------------------------------------- 1 | /webcomponents*.js binary 2 | /webcomponents*.js.map binary 3 | /webcomponents-loader.js -binary 4 | /package-lock.json binary 5 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @azakus 2 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_components 3 | dist 4 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: required 3 | dist: trusty 4 | node_js: stable 5 | addons: 6 | firefox: latest 7 | apt: 8 | sources: 9 | - google-chrome 10 | packages: 11 | - google-chrome-stable 12 | before_script: 13 | - export DISPLAY=:99.0 14 | - sh -e /etc/init.d/xvfb start 15 | - sleep 3 16 | script: 17 | - npm install -g bower 18 | - bower install 19 | - wct -l chrome 20 | - wct -l firefox 21 | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then wct -s 'windows 10/microsoftedge@14' -s 'windows 8.1/internet explorer@11' -s 'os x 10.11/safari@10' -s 'os x 10.11/safari@9' -s 'Linux/chrome@41'; fi 22 | env: 23 | global: 24 | - secure: Fpp9LwJSGOdTrSIImQTlbzxozBsqe/2AJN5OfTXSe12FZxqzz50gevdxQcIlLypKaNyCtjb980DJbwdJR2cXUqaunLZAPWxrKa7ZPwamUxW+zVL7EHqy5zuvD+yJ+Vmk3ahs3WBTVyJ8T3XoaSfo9VumDIcKggWGJwgvM3blIMg= 25 | - secure: Bj8MgzUVP0X8MLgK3d9eF48V7x0rPJyrN1IyguzKyJJVC8LV2XZXF+6o/M+zNsVMSsjhgXMkS3RRuaUShxO/OS6gHeG31FWcZqbXfZfgMMyH8a8zDls+r8m2lGEICaZo1OTXR0uiR/VNVt7n2xoBnTmjmRFwkaxAZk4yCjbXYzQ= 26 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Want to contribute to webcomponents.js? Great! 4 | 5 | We are more than happy to accept external contributions to the project in the form of [bug reports](../../issues) and pull requests. 6 | 7 | ## Contributor License Agreement 8 | 9 | Before we can accept patches, there's a quick web form you need to fill out. 10 | 11 | - If you're contributing as an individual (e.g. you own the intellectual property), fill out [this form](http://code.google.com/legal/individual-cla-v1.0.html). 12 | - If you're contributing under a company, fill out [this form](http://code.google.com/legal/corporate-cla-v1.0.html) instead. 13 | 14 | This CLA asserts that contributions are owned by you and that we can license all work under our [license](LICENSE). 15 | 16 | Other projects require a similar agreement: jQuery, Firefox, Apache, Node, and many more. 17 | 18 | [More about CLAs](https://www.google.com/search?q=Contributor%20License%20Agreement) 19 | 20 | ## Initial setup 21 | 22 | 1. Setup Gulp: `sudo npm install -g gulp` 23 | 1. Fork the project on github and pull down your copy. 24 | > replace the {{ username }} with your username and {{ repository }} with the repository name 25 | 26 | git clone git@github.com:{{ username }}/{{ repository }}.git 27 | 28 | 1. Test your change results in a working build. 29 | > in the repo you've made changes to, try generating a build: 30 | 31 | cd $REPO 32 | npm install 33 | gulp 34 | 35 | The builds will be placed into the `dist/` directory if all goes well. 36 | 37 | 1. Commit your code and make a pull request. 38 | 39 | That's it for the one time setup. Now you're ready to make a change. 40 | 41 | ## Submitting a pull request 42 | 43 | We iterate fast! To avoid potential merge conflicts, it's a good idea to pull from the main project before making a change and submitting a pull request. The easiest way to do this is setup a remote called `upstream` and do a pull before working on a change: 44 | 45 | git remote add upstream git://github.com/polymer/webcomponentsjs.git 46 | 47 | Then before making a change, do a pull from the upstream `master` branch: 48 | 49 | git pull upstream master 50 | 51 | To make life easier, add a "pull upstream" alias in your `.gitconfig`: 52 | 53 | [alias] 54 | pu = !"git fetch origin -v; git fetch upstream -v; git merge upstream/master" 55 | 56 | That will pull in changes from your forked repo, the main (upstream) repo, and merge the two. Then it's just a matter of running `git pu` before a change and pushing to your repo: 57 | 58 | git checkout master 59 | git pu 60 | # make change 61 | git commit -a -m 'Awesome things.' 62 | git push 63 | 64 | Lastly, don't forget to submit the pull request. -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Everything in this repo is BSD style license unless otherwise specified. 4 | 5 | Copyright (c) 2015 The Polymer Authors. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following disclaimer 13 | in the documentation and/or other materials provided with the 14 | distribution. 15 | * Neither the name of Google Inc. nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/README.md: -------------------------------------------------------------------------------- 1 | webcomponents.js (v1 spec polyfills) 2 | ================ 3 | 4 | [![Build Status](https://travis-ci.org/webcomponents/webcomponentsjs.svg?branch=master)](https://travis-ci.org/webcomponents/webcomponentsjs) 5 | 6 | > **Note**. For polyfills that work with the older Custom Elements and Shadow DOM v0 specs, see the [v0 branch](https://github.com/webcomponents/webcomponentsjs/tree/v0). 7 | 8 | A suite of polyfills supporting the [Web Components](http://webcomponents.org) specs: 9 | 10 | - **Custom Elements v1**: allows authors to define their own custom tags ([spec](https://w3c.github.io/webcomponents/spec/custom/), [tutorial](https://developers.google.com/web/fundamentals/getting-started/primers/customelements)). 11 | - **HTML Imports**: a way to include and reuse HTML documents via other HTML documents ([spec](https://w3c.github.io/webcomponents/spec/imports/), [tutorial](https://www.html5rocks.com/en/tutorials/webcomponents/imports/)). 12 | - **Shadow DOM v1**: provides encapsulation by hiding DOM subtrees under shadow roots ([spec](https://w3c.github.io/webcomponents/spec/shadow/), [tutorial](https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom)). 13 | 14 | For browsers that need it, there are also some minor polyfills included: 15 | - [`HTMLTemplateElement`](https://github.com/webcomponents/template) 16 | - [`Promise`](https://github.com/stefanpenner/es6-promise) 17 | - `Event`, `CustomEvent`, `MouseEvent` constructors and `Object.assign`, `Array.from` (see [webcomponents-platform](https://github.com/webcomponents/webcomponents-platform)) 18 | 19 | ## How to use 20 | 21 | The polyfills are built (concatenated & minified) into several bundles that target 22 | different browsers and spec readiness: 23 | 24 | - `webcomponents-hi.js` -- HTML Imports (needed by Safari Tech Preview) 25 | - `webcomponents-hi-ce.js` -- HTML Imports and Custom Elements v1 (needed by Safari 10) 26 | - `webcomponents-hi-sd-ce.js` -- HTML Imports, Custom Elements v1 and Shady DOM/CSS (needed by Safari 9, Firefox, Edge) 27 | - `webcomponents-sd-ce.js` -- Custom Elements and Shady DOM/CSS (no HTML Imports) 28 | - `webcomponents-lite.js` -- all of the polyfills: HTML Imports, Custom Elements, Shady DOM/CSS and generic platform polyfills (such as ES6 Promise, Constructable events, etc.) (needed by Internet Explorer 11), and Template (needed by IE 11 and Edge) 29 | 30 | If you are only targeting a specific browser, you can just use the bundle that's 31 | needed by it; alternatively, if your server is capable of serving different assets based on user agent, you can send the polyfill bundle that's necessary for the browser making that request. 32 | 33 | ## `webcomponents-loader.js` 34 | Alternatively, this repo also comes with `webcomponents-loader.js`, a client-side 35 | loader that dynamically loads the minimum polyfill bundle, using feature detection. 36 | Note that because the bundle will be loaded asynchronously, you should wait for the `WebComponentsReady` before you can safely assume that all the polyfills have 37 | loaded and are ready to be used (i.e. if you want to dynamically load other custom 38 | elements, etc.). 39 | 40 | Additionally, you can check if `window.WebComponents` exists to know if the `WebComponentsReady` event will fire, and you can check if `window.WebComponents.ready` is true to check if the `WebComponentsReady` event has already fired. 41 | 42 | Here's an example: 43 | 44 | ```html 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 65 | ``` 66 | 67 | ## `custom-elements-es5-adapter.js` 68 | According to the spec, Custom Elements must be ES6 classes (https://html.spec.whatwg.org/multipage/scripting.html#custom-element-conformance). Since most projects need to support a wide range of browsers that don't necessary support ES6, it may make sense to compile your project to ES5. However, ES5-style custom element classes will **not** work with native Custom Elements because ES5-style classes cannot properly extend ES6 classes, like `HTMLElement`. 69 | 70 | To work around this, load `custom-elements-es5-adapter.js` before declaring new Custom Elements. 71 | 72 | **The adapter must NOT be compiled.** 73 | 74 | ```html 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | ``` 85 | 86 | ## Browser Support 87 | 88 | The polyfills are intended to work in the latest versions of evergreen browsers. See below 89 | for our complete browser support matrix: 90 | 91 | | Polyfill | IE11+ | Chrome* | Firefox* | Safari 9+* | Chrome Android* | Mobile Safari* | 92 | | ---------- |:-----:|:-------:|:--------:|:----------:|:---------------:|:--------------:| 93 | | Custom Elements | ✓ | ✓ | ✓ | ✓ | ✓| ✓ | 94 | | HTML Imports | ✓ | ✓ | ✓ | ✓| ✓| ✓ | 95 | | Shady CSS/DOM | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 96 | 97 | \*Indicates the current version of the browser 98 | 99 | The polyfills may work in older browsers, however require additional polyfills (such as classList, or other [platform](https://github.com/webcomponents/webcomponents-platform) 100 | polyfills) to be used. We cannot guarantee support for browsers outside of our compatibility matrix. 101 | 102 | 103 | ### Manually Building 104 | 105 | If you wish to build the bundles yourself, you'll need `node` and `npm` on your system: 106 | 107 | * install [node.js](http://nodejs.org/) using the instructions on their website 108 | * use `npm` to install [gulp.js](http://gulpjs.com/): `npm install -g gulp` 109 | 110 | Now you are ready to build the polyfills with: 111 | 112 | # install dependencies 113 | npm install 114 | bower install 115 | # build 116 | gulp 117 | 118 | The builds will be placed into the root directory. 119 | 120 | ## Contribute 121 | 122 | See the [contributing guide](CONTRIBUTING.md) 123 | 124 | ## License 125 | 126 | Everything in this repository is BSD style license unless otherwise specified. 127 | 128 | Copyright (c) 2015 The Polymer Authors. All rights reserved. 129 | 130 | ## Helper utilities 131 | 132 | ### `WebComponentsReady` 133 | 134 | Under native HTML Imports, ` 16 | 17 | 18 | 19 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/ce-import-upgrade.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/ce-import.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/ce-upgrade-order.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | Custom Element Upgrade Order 15 | 16 | 17 | 18 | 19 | 20 | 21 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/ce-upgradedocumenttree.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/dev-loader-swizzled.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/dev-loader.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/force-polyfills.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | Force polyfills 15 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/a1-define.html: -------------------------------------------------------------------------------- 1 | 10 | 33 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/a1-import.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/a1-instance.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/a1-reference.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 20 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/csp-import-1.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/csp-import-2.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/csp-script-1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 4 | * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5 | * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6 | * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7 | * Code distributed by Google as part of the polymer project is also 8 | * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9 | */ 10 | 11 | window.externalScriptParsed1 = new Date().getTime(); 12 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/csp-script-2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 4 | * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5 | * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6 | * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7 | * Code distributed by Google as part of the polymer project is also 8 | * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9 | */ 10 | 11 | window.externalScriptParsed2 = new Date().getTime(); 12 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/current-script.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 4 | * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5 | * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6 | * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7 | * Code distributed by Google as part of the polymer project is also 8 | * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9 | */ 10 | 11 | remoteCurrentScriptExecuted = window.remoteCurrentScriptExecuted || 0; 12 | remoteCurrentScriptExecuted++; 13 | assert.ok(document._currentScript); 14 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/element-import-a.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/element-import-b.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/element-import.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/import-file.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/import-upgrade-order.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/script-1.html: -------------------------------------------------------------------------------- 1 | 10 |
me
11 | 16 | 17 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/script-2.html: -------------------------------------------------------------------------------- 1 | 10 |
me2
11 | 15 | 16 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/simple-element-es5.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 55 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/imports/simple-element.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 43 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/integration-es5.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | Integration Test 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Light DOM 23 | 24 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/integration.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | Integration Test 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Light DOM 22 | 23 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/load.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/promise.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | Test Promise Polyfill 14 | 15 | 16 | 17 | 18 | 19 | 44 | 45 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/runner.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | All WebComponents Tests 12 | 13 | 14 | 15 | 16 | 17 | 36 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/smoke.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | plain 20 | 21 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/template-and-CE.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | Template with HTMLImports Test 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/tests/template-and-imports.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | Template with HTMLImports Test 14 | 15 | 16 | 17 | 18 | 21 | 22 | 25 | 26 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/wct.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "suites": ["tests/runner.html"], 3 | "clientOptions": { 4 | "environmentImports": [] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /bower_components/webcomponentsjs/webcomponents-hi-ce.js: -------------------------------------------------------------------------------- 1 | /** 2 | @license @nocompile 3 | Copyright (c) 2018 The Polymer Project Authors. All rights reserved. 4 | This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5 | The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6 | The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7 | Code distributed by Google as part of the polymer project is also 8 | subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9 | */ 10 | (function(){/* 11 | 12 | Copyright (c) 2016 The Polymer Project Authors. All rights reserved. 13 | This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 14 | The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 15 | The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 16 | Code distributed by Google as part of the polymer project is also 17 | subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 18 | */ 19 | 'use strict';(function(a){function b(a,b){if("function"===typeof window.CustomEvent)return new CustomEvent(a,b);var c=document.createEvent("CustomEvent");c.initCustomEvent(a,!!b.bubbles,!!b.cancelable,b.detail);return c}function c(a){if(J)return a.ownerDocument!==document?a.ownerDocument:null;var b=a.__importDoc;if(!b&&a.parentNode){b=a.parentNode;if("function"===typeof b.closest)b=b.closest("link[rel=import]");else for(;!h(b)&&(b=b.parentNode););a.__importDoc=b}return b}function d(a){var b=l(document, 20 | "link[rel=import]:not([import-dependency])"),c=b.length;c?r(b,function(b){return k(b,function(){0===--c&&a()})}):a()}function e(a){function b(){"loading"!==document.readyState&&document.body&&(document.removeEventListener("readystatechange",b),a())}document.addEventListener("readystatechange",b);b()}function f(a){e(function(){return d(function(){return a&&a()})})}function k(a,b){if(a.__loaded)b&&b();else if("script"===a.localName&&!a.src||"style"===a.localName&&!a.firstChild)a.__loaded=!0,b&&b(); 21 | else{var c=function(e){a.removeEventListener(e.type,c);a.__loaded=!0;b&&b()};a.addEventListener("load",c);K&&"style"===a.localName||a.addEventListener("error",c)}}function h(a){return a.nodeType===Node.ELEMENT_NODE&&"link"===a.localName&&"import"===a.rel}function g(){var a=this;this.a={};this.b=0;this.c=new MutationObserver(function(b){return a.K(b)});this.c.observe(document.head,{childList:!0,subtree:!0});this.loadImports(document)}function n(a){r(l(a,"template"),function(a){r(l(a.content,'script:not([type]),script[type="application/javascript"],script[type="text/javascript"]'), 22 | function(a){var b=document.createElement("script");r(a.attributes,function(a){return b.setAttribute(a.name,a.value)});b.textContent=a.textContent;a.parentNode.replaceChild(b,a)});n(a.content)})}function l(a,b){return a.childNodes.length?a.querySelectorAll(b):ya}function r(a,b,c){var e=a?a.length:0,d=c?-1:1;for(c=c?e-1:0;c]*)(rel=['|"]?stylesheet['|"]?[^>]*>)/g,t={I:function(a,b){a.href&&a.setAttribute("href",t.j(a.getAttribute("href"),b));a.src&&a.setAttribute("src",t.j(a.getAttribute("src"),b));if("style"===a.localName){var c=t.C(a.textContent,b,za);a.textContent=t.C(c,b,Aa)}},C:function(a,b,c){return a.replace(c, 24 | function(a,c,e,d){a=e.replace(/["']/g,"");b&&(a=t.j(a,b));return c+"'"+a+"'"+d})},j:function(a,b){if(void 0===t.l){t.l=!1;try{var c=new URL("b","http://a");c.pathname="c%20d";t.l="http://a/c%20d"===c.href}catch(Va){}}if(t.l)return(new URL(a,b)).href;c=t.F;c||(c=document.implementation.createHTMLDocument("temp"),t.F=c,c.w=c.createElement("base"),c.head.appendChild(c.w),c.v=c.createElement("a"));c.w.href=b;c.v.href=a;return c.v.href||a}},Z={async:!0,load:function(a,b,c){if(a)if(a.match(/^data:/)){a= 25 | a.split(",");var e=a[1];e=-1d.status?b(e,a):c(e)};d.send()}else c("error: href must be specified")}},K=/Trident/.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent); 26 | g.prototype.loadImports=function(a){var b=this;r(l(a,"link[rel=import]"),function(a){return b.A(a)})};g.prototype.A=function(a){var b=this,c=a.href;if(void 0!==this.a[c]){var e=this.a[c];e&&e.__loaded&&(a.__import=e,this.g(a))}else this.b++,this.a[c]="pending",Z.load(c,function(a,e){a=b.L(a,e||c);b.a[c]=a;b.b--;b.loadImports(a);b.B()},function(){b.a[c]=null;b.b--;b.B()})};g.prototype.L=function(a,b){if(!a)return document.createDocumentFragment();K&&(a=a.replace(Ba,function(a,b,c){return-1===a.indexOf("type=")? 27 | b+" type=import-disable "+c:a}));var c=document.createElement("template");c.innerHTML=a;if(c.content)a=c.content,n(a);else for(a=document.createDocumentFragment();c.firstChild;)a.appendChild(c.firstChild);if(c=a.querySelector("base"))b=t.j(c.getAttribute("href"),b),c.removeAttribute("href");var e=0;r(l(a,'link[rel=import],link[rel=stylesheet][href][type=import-disable],style:not([type]),link[rel=stylesheet][href]:not([type]),script:not([type]),script[type="application/javascript"],script[type="text/javascript"]'), 28 | function(a){k(a);t.I(a,b);a.setAttribute("import-dependency","");"script"===a.localName&&!a.src&&a.textContent&&(a.setAttribute("src","data:text/javascript;charset=utf-8,"+encodeURIComponent(a.textContent+("\n//# sourceURL="+b+(e?"-"+e:"")+".js\n"))),a.textContent="",e++)});return a};g.prototype.B=function(){var a=this;if(!this.b){this.c.disconnect();this.flatten(document);var b=!1,c=!1,e=function(){c&&b&&(a.loadImports(document),a.b||(a.c.observe(document.head,{childList:!0,subtree:!0}),a.J()))}; 29 | this.N(function(){c=!0;e()});this.M(function(){b=!0;e()})}};g.prototype.flatten=function(a){var b=this;r(l(a,"link[rel=import]"),function(a){var c=b.a[a.href];(a.__import=c)&&c.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&(b.a[a.href]=a,a.readyState="loading",a.__import=a,b.flatten(c),a.appendChild(c))})};g.prototype.M=function(a){function b(d){if(d]*)(rel=['|"]?stylesheet['|"]?[^>]*>)/g,e={v:function(a,b){a.href&&a.setAttribute("href",e.c(a.getAttribute("href"),b));a.src&&a.setAttribute("src",e.c(a.getAttribute("src"),b));if("style"===a.localName){var c=e.o(a.textContent,b,N);a.textContent=e.o(c,b,O)}},o:function(a,b,c){return a.replace(c, 24 | function(a,c,m,g){a=m.replace(/["']/g,"");b&&(a=e.c(a,b));return c+"'"+a+"'"+g})},c:function(a,b){if(void 0===e.f){e.f=!1;try{var c=new URL("b","http://a");c.pathname="c%20d";e.f="http://a/c%20d"===c.href}catch(d){}}if(e.f)return(new URL(a,b)).href;c=e.s;c||(c=document.implementation.createHTMLDocument("temp"),e.s=c,c.i=c.createElement("base"),c.head.appendChild(c.i),c.h=c.createElement("a"));c.i.href=b;c.h.href=a;return c.h.href||a}},F={async:!0,load:function(a,b,c){if(a)if(a.match(/^data:/)){a= 25 | a.split(",");var d=a[1];d=-1f.status?b(d,a):c(d)};f.send()}else c("error: href must be specified")}},x=/Trident/.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent); 26 | k.prototype.loadImports=function(a){var b=this;g(l(a,"link[rel=import]"),function(a){return b.l(a)})};k.prototype.l=function(a){var b=this,c=a.href;if(void 0!==this.a[c]){var d=this.a[c];d&&d.__loaded&&(a.__import=d,this.j(a))}else this.b++,this.a[c]="pending",F.load(c,function(a,d){a=b.B(a,d||c);b.a[c]=a;b.b--;b.loadImports(a);b.m()},function(){b.a[c]=null;b.b--;b.m()})};k.prototype.B=function(a,b){if(!a)return document.createDocumentFragment();x&&(a=a.replace(P,function(a,b,c){return-1===a.indexOf("type=")? 27 | b+" type=import-disable "+c:a}));var c=document.createElement("template");c.innerHTML=a;if(c.content)a=c.content,E(a);else for(a=document.createDocumentFragment();c.firstChild;)a.appendChild(c.firstChild);if(c=a.querySelector("base"))b=e.c(c.getAttribute("href"),b),c.removeAttribute("href");var d=0;g(l(a,'link[rel=import],link[rel=stylesheet][href][type=import-disable],style:not([type]),link[rel=stylesheet][href]:not([type]),script:not([type]),script[type="application/javascript"],script[type="text/javascript"]'), 28 | function(a){t(a);e.v(a,b);a.setAttribute("import-dependency","");"script"===a.localName&&!a.src&&a.textContent&&(a.setAttribute("src","data:text/javascript;charset=utf-8,"+encodeURIComponent(a.textContent+("\n//# sourceURL="+b+(d?"-"+d:"")+".js\n"))),a.textContent="",d++)});return a};k.prototype.m=function(){var a=this;if(!this.b){this.g.disconnect();this.flatten(document);var b=!1,c=!1,d=function(){c&&b&&(a.loadImports(document),a.b||(a.g.observe(document.head,{childList:!0,subtree:!0}),a.w()))}; 29 | this.D(function(){c=!0;d()});this.C(function(){b=!0;d()})}};k.prototype.flatten=function(a){var b=this;g(l(a,"link[rel=import]"),function(a){var c=b.a[a.href];(a.__import=c)&&c.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&(b.a[a.href]=a,a.readyState="loading",a.__import=a,b.flatten(c),a.appendChild(c))})};k.prototype.C=function(a){function b(f){if(f 57 | 58 | var fire = function() { 59 | requestAnimationFrame(function() { 60 | window.WebComponents.ready = true; 61 | document.dispatchEvent(new CustomEvent('WebComponentsReady', {bubbles: true})); 62 | }); 63 | }; 64 | 65 | if (document.readyState !== 'loading') { 66 | fire(); 67 | } else { 68 | document.addEventListener('readystatechange', function wait() { 69 | fire(); 70 | document.removeEventListener('readystatechange', wait); 71 | }); 72 | } 73 | } 74 | })(); 75 | -------------------------------------------------------------------------------- /dist/img-2.es5.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 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; }; }(); 4 | 5 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 6 | 7 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 8 | 9 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 10 | 11 | /** 12 | * Created by Leon Revill on 10/12/2017. 13 | * Blog: blog.revillweb.com 14 | * Twitter: @RevillWeb 15 | * GitHub: github.com/RevillWeb 16 | */ 17 | var Img2 = function (_HTMLElement) { 18 | _inherits(Img2, _HTMLElement); 19 | 20 | function Img2() { 21 | _classCallCheck(this, Img2); 22 | 23 | // Private class variables 24 | var _this = _possibleConstructorReturn(this, (Img2.__proto__ || Object.getPrototypeOf(Img2)).call(this)); 25 | 26 | _this._root = null; 27 | _this._$img = null; 28 | _this._$preview = null; 29 | _this._preview = null; 30 | _this._src = null; 31 | _this._width = null; 32 | _this._height = null; 33 | _this._reset(); 34 | 35 | // Settings 36 | _this._renderOnPreCached = Img2.settings.RENDER_ON_PRECACHED; 37 | 38 | // Bound class methods 39 | _this._precache = _this._precache.bind(_this); 40 | _this._onImgLoad = _this._onImgLoad.bind(_this); 41 | _this._onImgPreCached = _this._onImgPreCached.bind(_this); 42 | 43 | return _this; 44 | } 45 | 46 | _createClass(Img2, [{ 47 | key: "_reset", 48 | 49 | 50 | /** 51 | * Reset all private values 52 | * @private 53 | */ 54 | value: function _reset() { 55 | if (this._loaded === true) this.removeAttribute("loaded"); 56 | this._rendered = false; 57 | this._loading = false; 58 | this._loaded = false; 59 | this._preCaching = false; 60 | this._preCached = false; 61 | } 62 | }, { 63 | key: "connectedCallback", 64 | value: function connectedCallback() { 65 | 66 | if (window.ShadyCSS) ShadyCSS.styleElement(this); 67 | // Override any global settings 68 | this._renderOnPreCached = this.getAttribute("render-on-pre-cached") === "true"; 69 | this._init(); 70 | } 71 | }, { 72 | key: "_init", 73 | value: function _init() { 74 | var _this2 = this; 75 | 76 | // Check to see if we have a src, if not return and do nothing else 77 | this._src = this.getAttribute("src"); 78 | // Grab the initial attribute values 79 | this._preview = this.getAttribute("src-preview"); 80 | this._width = this.getAttribute("width"); 81 | this._height = this.getAttribute("height"); 82 | 83 | if (!this._src || !this._width || !this._height) return; 84 | 85 | // Set the height and width of the element so that we can figure out if it is on the screen or not 86 | this.style.width = this._width + "px"; 87 | this.style.height = this._height + "px"; 88 | 89 | // Figure out if this image is within view 90 | Img2.addIntersectListener(this, function () { 91 | Img2._removePreCacheListener(_this2._precache); 92 | _this2._render(); 93 | _this2._load(); 94 | Img2.removeIntersectListener(_this2); 95 | }); 96 | 97 | // Listen for precache instruction 98 | Img2._addPreCacheListener(this._precache, this._src); 99 | } 100 | 101 | /** 102 | * Method which displays the image once ready to be displayed 103 | * @private 104 | */ 105 | 106 | }, { 107 | key: "_load", 108 | value: function _load() { 109 | if (this._preCached === false) Img2._priorityCount += 1; 110 | this._$img.onload = this._onImgLoad; 111 | this._loading = true; 112 | this._$img.src = this._src; 113 | } 114 | }, { 115 | key: "_onImgLoad", 116 | value: function _onImgLoad() { 117 | this._loading = false; 118 | this._loaded = true; 119 | if (this._$preview !== null) { 120 | this._root.removeChild(this._$preview); 121 | this._$preview = null; 122 | } 123 | this._$img.onload = null; 124 | if (this._preCached === false) Img2._priorityCount -= 1; 125 | this.setAttribute("loaded", ""); 126 | } 127 | }, { 128 | key: "_onImgPreCached", 129 | value: function _onImgPreCached() { 130 | this._preCaching = false; 131 | this._preCached = true; 132 | if (this._renderOnPreCached !== false) { 133 | this._render(); 134 | this._load(); 135 | } 136 | } 137 | }, { 138 | key: "attributeChangedCallback", 139 | value: function attributeChangedCallback(name, oldValue, newValue) { 140 | 141 | // If nothing has changed then just return 142 | if (newValue === oldValue) return; 143 | 144 | switch (name) { 145 | case "src": 146 | // If the src is changed then we need to reset and start again 147 | this._reset(); 148 | this._init(); 149 | break; 150 | case "width": 151 | this._width = newValue; 152 | if (this._$preview !== null) this._$preview.width = this._width; 153 | if (this._$img !== null) this._$img.width = this._width; 154 | this.style.width = this._width + "px"; 155 | break; 156 | case "height": 157 | this._height = newValue; 158 | if (this._$preview !== null) this._$preview.height = this._height; 159 | if (this._$img !== null) this._$img.height = this._height; 160 | this.style.height = this._height + "px"; 161 | break; 162 | case "render-on-pre-cached": 163 | this._renderOnPreCached = !(newValue === "false"); 164 | break; 165 | case "alt": 166 | this._updateAttribute("alt", newValue); 167 | break; 168 | } 169 | } 170 | 171 | /** 172 | * Method used to update an individual attribute on the native image element 173 | * @param {string} name - The name of the attribute to update 174 | * @param {string} value - The new attribute value 175 | * @private 176 | */ 177 | 178 | }, { 179 | key: "_updateAttribute", 180 | value: function _updateAttribute(name, value) { 181 | // If the image element hasn't been rendered yet, just return. 182 | if (this._rendered === false) return; 183 | this._$img.setAttribute(name, value); 184 | } 185 | 186 | /** 187 | * Method which renders the DOM elements and displays any preview image 188 | * @private 189 | */ 190 | 191 | }, { 192 | key: "_render", 193 | value: function _render() { 194 | 195 | if (this._rendered === true) return; 196 | 197 | // Render the Shadow Root if not done already (src change can force this method to be called again) 198 | if (this._root === null) { 199 | // Attach the Shadow Root to the element 200 | this._root = this.attachShadow({ mode: "open" }); 201 | // Create the initial template with styles 202 | var $template = document.createElement("template"); 203 | $template.innerHTML = "\n \n "; 204 | if (window.ShadyCSS) ShadyCSS.prepareTemplate($template, "img-2"); 205 | this._root.appendChild(document.importNode($template.content, true)); 206 | } 207 | 208 | // If a preview image has been specified 209 | if (this._$preview === null && this._preview !== null && this._loaded === false) { 210 | // Create the element 211 | this._$preview = document.createElement("img"); 212 | this._$preview.classList.add("img2-preview"); 213 | this._$preview.src = this._preview; 214 | // Add the specified width and height 215 | this._$preview.width = this._width; 216 | this._$preview.height = this._height; 217 | // Add it to the Shadow Root 218 | this._root.appendChild(this._$preview); 219 | } 220 | 221 | // Render the img element if not done already 222 | if (this._$img === null) { 223 | // Create the actual image element to be used to display the image 224 | this._$img = document.createElement("img"); 225 | this._$img.classList.add("img2-src"); 226 | // add the specified width and height to the image element 227 | this._$img.width = this._width; 228 | this._$img.height = this._height; 229 | var alt = this.getAttribute("alt"); 230 | if (alt !== null) this._$img.setAttribute("alt", alt); 231 | // Add the image to the Shadow Root 232 | this._root.appendChild(this._$img); 233 | } 234 | 235 | // Flag as rendered 236 | this._rendered = true; 237 | } 238 | }, { 239 | key: "_precache", 240 | value: function _precache() { 241 | this._preCaching = true; 242 | Img2._preCache(this._src, this._onImgPreCached); 243 | } 244 | }, { 245 | key: "loaded", 246 | get: function get() { 247 | return this._loaded; 248 | } 249 | }], [{ 250 | key: "_addPreCacheListener", 251 | value: function _addPreCacheListener(cb, url) { 252 | Img2._preCacheListeners.set(cb, url); 253 | } 254 | }, { 255 | key: "_removePreCacheListener", 256 | value: function _removePreCacheListener(cb) { 257 | Img2._preCacheListeners.delete(cb); 258 | } 259 | }, { 260 | key: "_startPreCache", 261 | value: function _startPreCache() { 262 | var _iteratorNormalCompletion = true; 263 | var _didIteratorError = false; 264 | var _iteratorError = undefined; 265 | 266 | try { 267 | for (var _iterator = Img2._preCacheListeners.keys()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 268 | var cb = _step.value; 269 | cb(); 270 | } 271 | } catch (err) { 272 | _didIteratorError = true; 273 | _iteratorError = err; 274 | } finally { 275 | try { 276 | if (!_iteratorNormalCompletion && _iterator.return) { 277 | _iterator.return(); 278 | } 279 | } finally { 280 | if (_didIteratorError) { 281 | throw _iteratorError; 282 | } 283 | } 284 | } 285 | } 286 | 287 | /** 288 | * Methods used to determine when currently visible (priority) elements have finished download to then inform other elements to pre-cache 289 | */ 290 | 291 | }, { 292 | key: "addIntersectListener", 293 | value: function addIntersectListener($element, intersectCallback) { 294 | Img2._intersectListeners.set($element, intersectCallback); 295 | Img2._observer.observe($element); 296 | } 297 | }, { 298 | key: "removeIntersectListener", 299 | value: function removeIntersectListener($element) { 300 | if ($element) Img2._observer.unobserve($element); 301 | } 302 | }, { 303 | key: "_handleIntersect", 304 | value: function _handleIntersect(entries) { 305 | entries.forEach(function (entry) { 306 | if (entry.isIntersecting === true) { 307 | var cb = Img2._intersectListeners.get(entry.target); 308 | if (cb !== undefined) cb(entry); 309 | } 310 | }); 311 | } 312 | }, { 313 | key: "_preCache", 314 | value: function _preCache(url, cb) { 315 | 316 | var slot = Img2._preCacheCallbacks[url]; 317 | if (slot === undefined) { 318 | Img2._preCacheCallbacks[url] = { 319 | cached: false, 320 | cbs: [cb] 321 | }; 322 | var location = url.indexOf("http") > -1 ? url : window.location.href + url; 323 | Img2._worker.postMessage({ location: location, url: url }); 324 | } else { 325 | if (slot.cached === true) { 326 | cb(); 327 | } else { 328 | slot.cbs.push(cb); 329 | } 330 | } 331 | } 332 | }, { 333 | key: "observedAttributes", 334 | get: function get() { 335 | return ["src", "width", "height", "alt"]; 336 | } 337 | }, { 338 | key: "_priorityCount", 339 | get: function get() { 340 | return Img2.__priorityCount; 341 | }, 342 | set: function set(value) { 343 | Img2.__priorityCount = value; 344 | if (Img2.__priorityCount < 1) { 345 | // Inform components that they can start to pre-cache their images 346 | // Debounce in case the user scrolls because then there will be more priority images 347 | if (Img2._startPreCacheDebounce !== null) { 348 | clearTimeout(Img2._startPreCacheDebounce); 349 | Img2._startPreCacheDebounce = null; 350 | } 351 | Img2._startPreCacheDebounce = setTimeout(function () { 352 | if (Img2.__priorityCount < 1) Img2._startPreCache(); 353 | }, 500); 354 | } 355 | } 356 | 357 | /** 358 | * Methods used to determine when this element is in the visible viewport 359 | */ 360 | 361 | }]); 362 | 363 | return Img2; 364 | }(HTMLElement); 365 | 366 | /** 367 | * Methods used to pre-cache images using a WebWorker 368 | */ 369 | 370 | Img2._preCacheListeners = new Map(); 371 | Img2.__priorityCount = 0; 372 | Img2._startPreCacheDebounce = null; 373 | Img2._intersectListeners = new Map(); 374 | Img2._observer = new IntersectionObserver(Img2._handleIntersect, { 375 | root: null, 376 | rootMargin: "0px", 377 | threshold: 0 378 | }); 379 | Img2._preCacheCallbacks = {}; 380 | Img2._worker = new Worker(window.URL.createObjectURL(new Blob(["self.onmessage=" + function (e) { 381 | var xhr = new XMLHttpRequest(); 382 | function onload() { 383 | self.postMessage(e.data.url); 384 | } 385 | xhr.responseType = "blob"; 386 | xhr.onload = xhr.onerror = onload; 387 | xhr.open("GET", e.data.location, true); 388 | xhr.send(); 389 | }.toString() + ";"], { type: "text/javascript" }))); 390 | 391 | Img2._worker.onmessage = function (e) { 392 | var slot = Img2._preCacheCallbacks[e.data]; 393 | if (slot !== undefined) { 394 | slot.cached = true; 395 | slot.cbs = slot.cbs.filter(function (cb) { 396 | // Call the callback 397 | cb(); 398 | // Remove the callback 399 | return false; 400 | }); 401 | } 402 | }; 403 | 404 | /** Img2 Settings **/ 405 | Img2.settings = { 406 | "RENDER_ON_PRECACHED": false // Set this to false to save memory but can cause jank during scrolling 407 | }; 408 | 409 | window.customElements.define("img-2", Img2); 410 | -------------------------------------------------------------------------------- /dist/img-2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Leon Revill on 10/12/2017. 3 | * Blog: blog.revillweb.com 4 | * Twitter: @RevillWeb 5 | * GitHub: github.com/RevillWeb 6 | */ 7 | class Img2 extends HTMLElement { 8 | 9 | constructor() { 10 | super(); 11 | 12 | // Private class variables 13 | this._root = null; 14 | this._$img = null; 15 | this._$preview = null; 16 | this._preview = null; 17 | this._src = null; 18 | this._width = null; 19 | this._height = null; 20 | this._reset(); 21 | 22 | // Settings 23 | this._renderOnPreCached = Img2.settings.RENDER_ON_PRECACHED; 24 | 25 | // Bound class methods 26 | this._precache = this._precache.bind(this); 27 | this._onImgLoad = this._onImgLoad.bind(this); 28 | this._onImgPreCached = this._onImgPreCached.bind(this); 29 | } 30 | 31 | get loaded() { 32 | return this._loaded; 33 | } 34 | 35 | /** 36 | * Reset all private values 37 | * @private 38 | */ 39 | _reset() { 40 | if (this._loaded === true) this.removeAttribute("loaded"); 41 | this._rendered = false; 42 | this._loading = false; 43 | this._loaded = false; 44 | this._preCaching = false; 45 | this._preCached = false; 46 | } 47 | 48 | connectedCallback() { 49 | 50 | if (window.ShadyCSS) ShadyCSS.styleElement(this); 51 | // Override any global settings 52 | this._renderOnPreCached = this.getAttribute("render-on-pre-cached") === "true"; 53 | this._init(); 54 | } 55 | 56 | _init() { 57 | 58 | // Check to see if we have a src, if not return and do nothing else 59 | this._src = this.getAttribute("src"); 60 | // Grab the initial attribute values 61 | this._preview = this.getAttribute("src-preview"); 62 | this._width = this.getAttribute("width"); 63 | this._height = this.getAttribute("height"); 64 | 65 | if (!this._src || !this._width || !this._height) return; 66 | 67 | // Set the height and width of the element so that we can figure out if it is on the screen or not 68 | this.style.width = `${ this._width }px`; 69 | this.style.height = `${ this._height }px`; 70 | 71 | // Figure out if this image is within view 72 | Img2.addIntersectListener(this, () => { 73 | Img2._removePreCacheListener(this._precache); 74 | this._render(); 75 | this._load(); 76 | Img2.removeIntersectListener(this); 77 | }); 78 | 79 | // Listen for precache instruction 80 | Img2._addPreCacheListener(this._precache, this._src); 81 | } 82 | 83 | /** 84 | * Method which displays the image once ready to be displayed 85 | * @private 86 | */ 87 | _load() { 88 | if (this._preCached === false) Img2._priorityCount += 1; 89 | this._$img.onload = this._onImgLoad; 90 | this._loading = true; 91 | this._$img.src = this._src; 92 | } 93 | 94 | _onImgLoad() { 95 | this._loading = false; 96 | this._loaded = true; 97 | if (this._$preview !== null) { 98 | this._root.removeChild(this._$preview); 99 | this._$preview = null; 100 | } 101 | this._$img.onload = null; 102 | if (this._preCached === false) Img2._priorityCount -= 1; 103 | this.setAttribute("loaded", ""); 104 | } 105 | 106 | _onImgPreCached() { 107 | this._preCaching = false; 108 | this._preCached = true; 109 | if (this._renderOnPreCached !== false) { 110 | this._render(); 111 | this._load(); 112 | } 113 | } 114 | 115 | static get observedAttributes() { 116 | return ["src", "width", "height", "alt"]; 117 | } 118 | attributeChangedCallback(name, oldValue, newValue) { 119 | 120 | // If nothing has changed then just return 121 | if (newValue === oldValue) return; 122 | 123 | switch (name) { 124 | case "src": 125 | // If the src is changed then we need to reset and start again 126 | this._reset(); 127 | this._init(); 128 | break; 129 | case "width": 130 | this._width = newValue; 131 | if (this._$preview !== null) this._$preview.width = this._width; 132 | if (this._$img !== null) this._$img.width = this._width; 133 | this.style.width = `${ this._width }px`; 134 | break; 135 | case "height": 136 | this._height = newValue; 137 | if (this._$preview !== null) this._$preview.height = this._height; 138 | if (this._$img !== null) this._$img.height = this._height; 139 | this.style.height = `${ this._height }px`; 140 | break; 141 | case "render-on-pre-cached": 142 | this._renderOnPreCached = !(newValue === "false"); 143 | break; 144 | case "alt": 145 | this._updateAttribute("alt", newValue); 146 | break; 147 | } 148 | } 149 | 150 | /** 151 | * Method used to update an individual attribute on the native image element 152 | * @param {string} name - The name of the attribute to update 153 | * @param {string} value - The new attribute value 154 | * @private 155 | */ 156 | _updateAttribute(name, value) { 157 | // If the image element hasn't been rendered yet, just return. 158 | if (this._rendered === false) return; 159 | this._$img.setAttribute(name, value); 160 | } 161 | 162 | /** 163 | * Method which renders the DOM elements and displays any preview image 164 | * @private 165 | */ 166 | _render() { 167 | 168 | if (this._rendered === true) return; 169 | 170 | // Render the Shadow Root if not done already (src change can force this method to be called again) 171 | if (this._root === null) { 172 | // Attach the Shadow Root to the element 173 | this._root = this.attachShadow({ mode: "open" }); 174 | // Create the initial template with styles 175 | let $template = document.createElement("template"); 176 | $template.innerHTML = ` 177 | 204 | `; 205 | if (window.ShadyCSS) ShadyCSS.prepareTemplate($template, "img-2"); 206 | this._root.appendChild(document.importNode($template.content, true)); 207 | } 208 | 209 | // If a preview image has been specified 210 | if (this._$preview === null && this._preview !== null && this._loaded === false) { 211 | // Create the element 212 | this._$preview = document.createElement("img"); 213 | this._$preview.classList.add("img2-preview"); 214 | this._$preview.src = this._preview; 215 | // Add the specified width and height 216 | this._$preview.width = this._width; 217 | this._$preview.height = this._height; 218 | // Add it to the Shadow Root 219 | this._root.appendChild(this._$preview); 220 | } 221 | 222 | // Render the img element if not done already 223 | if (this._$img === null) { 224 | // Create the actual image element to be used to display the image 225 | this._$img = document.createElement("img"); 226 | this._$img.classList.add("img2-src"); 227 | // add the specified width and height to the image element 228 | this._$img.width = this._width; 229 | this._$img.height = this._height; 230 | const alt = this.getAttribute("alt"); 231 | if (alt !== null) this._$img.setAttribute("alt", alt); 232 | // Add the image to the Shadow Root 233 | this._root.appendChild(this._$img); 234 | } 235 | 236 | // Flag as rendered 237 | this._rendered = true; 238 | } 239 | 240 | _precache() { 241 | this._preCaching = true; 242 | Img2._preCache(this._src, this._onImgPreCached); 243 | } 244 | 245 | static _addPreCacheListener(cb, url) { 246 | Img2._preCacheListeners.set(cb, url); 247 | } 248 | 249 | static _removePreCacheListener(cb) { 250 | Img2._preCacheListeners.delete(cb); 251 | } 252 | 253 | static _startPreCache() { 254 | for (let cb of Img2._preCacheListeners.keys()) cb(); 255 | } 256 | 257 | /** 258 | * Methods used to determine when currently visible (priority) elements have finished download to then inform other elements to pre-cache 259 | */ 260 | 261 | static get _priorityCount() { 262 | return Img2.__priorityCount; 263 | } 264 | static set _priorityCount(value) { 265 | Img2.__priorityCount = value; 266 | if (Img2.__priorityCount < 1) { 267 | // Inform components that they can start to pre-cache their images 268 | // Debounce in case the user scrolls because then there will be more priority images 269 | if (Img2._startPreCacheDebounce !== null) { 270 | clearTimeout(Img2._startPreCacheDebounce); 271 | Img2._startPreCacheDebounce = null; 272 | } 273 | Img2._startPreCacheDebounce = setTimeout(function () { 274 | if (Img2.__priorityCount < 1) Img2._startPreCache(); 275 | }, 500); 276 | } 277 | } 278 | 279 | /** 280 | * Methods used to determine when this element is in the visible viewport 281 | */ 282 | 283 | 284 | static addIntersectListener($element, intersectCallback) { 285 | Img2._intersectListeners.set($element, intersectCallback); 286 | Img2._observer.observe($element); 287 | } 288 | 289 | static removeIntersectListener($element) { 290 | if ($element) Img2._observer.unobserve($element); 291 | } 292 | 293 | static _handleIntersect(entries) { 294 | entries.forEach(entry => { 295 | if (entry.isIntersecting === true) { 296 | const cb = Img2._intersectListeners.get(entry.target); 297 | if (cb !== undefined) cb(entry); 298 | } 299 | }); 300 | } 301 | 302 | static _preCache(url, cb) { 303 | 304 | let slot = Img2._preCacheCallbacks[url]; 305 | if (slot === undefined) { 306 | Img2._preCacheCallbacks[url] = { 307 | cached: false, 308 | cbs: [cb] 309 | }; 310 | const location = url.indexOf("http") > -1 ? url : window.location.href + url; 311 | Img2._worker.postMessage({ location: location, url: url }); 312 | } else { 313 | if (slot.cached === true) { 314 | cb(); 315 | } else { 316 | slot.cbs.push(cb); 317 | } 318 | } 319 | } 320 | } 321 | 322 | /** 323 | * Methods used to pre-cache images using a WebWorker 324 | */ 325 | 326 | Img2._preCacheListeners = new Map(); 327 | Img2.__priorityCount = 0; 328 | Img2._startPreCacheDebounce = null; 329 | Img2._intersectListeners = new Map(); 330 | Img2._observer = new IntersectionObserver(Img2._handleIntersect, { 331 | root: null, 332 | rootMargin: "0px", 333 | threshold: 0 334 | }); 335 | Img2._preCacheCallbacks = {}; 336 | Img2._worker = new Worker(window.URL.createObjectURL(new Blob([`self.onmessage=${ function (e) { 337 | const xhr = new XMLHttpRequest(); 338 | function onload() { 339 | self.postMessage(e.data.url); 340 | } 341 | xhr.responseType = "blob"; 342 | xhr.onload = xhr.onerror = onload; 343 | xhr.open("GET", e.data.location, true); 344 | xhr.send(); 345 | }.toString() };`], { type: "text/javascript" }))); 346 | 347 | Img2._worker.onmessage = function (e) { 348 | const slot = Img2._preCacheCallbacks[e.data]; 349 | if (slot !== undefined) { 350 | slot.cached = true; 351 | slot.cbs = slot.cbs.filter(cb => { 352 | // Call the callback 353 | cb(); 354 | // Remove the callback 355 | return false; 356 | }); 357 | } 358 | }; 359 | 360 | /** Img2 Settings **/ 361 | Img2.settings = { 362 | "RENDER_ON_PRECACHED": false // Set this to false to save memory but can cause jank during scrolling 363 | }; 364 | 365 | window.customElements.define("img-2", Img2); 366 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "img-2", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ansi-regex": { 8 | "version": "2.1.1", 9 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 10 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 11 | "dev": true 12 | }, 13 | "ansi-styles": { 14 | "version": "2.2.1", 15 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 16 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 17 | "dev": true 18 | }, 19 | "async": { 20 | "version": "1.5.2", 21 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 22 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", 23 | "dev": true 24 | }, 25 | "babel-code-frame": { 26 | "version": "6.26.0", 27 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", 28 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", 29 | "dev": true, 30 | "requires": { 31 | "chalk": "1.1.3", 32 | "esutils": "2.0.2", 33 | "js-tokens": "3.0.2" 34 | } 35 | }, 36 | "babel-core": { 37 | "version": "6.26.0", 38 | "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", 39 | "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", 40 | "dev": true, 41 | "requires": { 42 | "babel-code-frame": "6.26.0", 43 | "babel-generator": "6.26.0", 44 | "babel-helpers": "6.24.1", 45 | "babel-messages": "6.23.0", 46 | "babel-register": "6.26.0", 47 | "babel-runtime": "6.26.0", 48 | "babel-template": "6.26.0", 49 | "babel-traverse": "6.26.0", 50 | "babel-types": "6.26.0", 51 | "babylon": "6.18.0", 52 | "convert-source-map": "1.5.1", 53 | "debug": "2.6.9", 54 | "json5": "0.5.1", 55 | "lodash": "4.17.4", 56 | "minimatch": "3.0.4", 57 | "path-is-absolute": "1.0.1", 58 | "private": "0.1.8", 59 | "slash": "1.0.0", 60 | "source-map": "0.5.7" 61 | } 62 | }, 63 | "babel-generator": { 64 | "version": "6.26.0", 65 | "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", 66 | "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", 67 | "dev": true, 68 | "requires": { 69 | "babel-messages": "6.23.0", 70 | "babel-runtime": "6.26.0", 71 | "babel-types": "6.26.0", 72 | "detect-indent": "4.0.0", 73 | "jsesc": "1.3.0", 74 | "lodash": "4.17.4", 75 | "source-map": "0.5.7", 76 | "trim-right": "1.0.1" 77 | } 78 | }, 79 | "babel-helper-call-delegate": { 80 | "version": "6.24.1", 81 | "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", 82 | "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", 83 | "dev": true, 84 | "requires": { 85 | "babel-helper-hoist-variables": "6.24.1", 86 | "babel-runtime": "6.26.0", 87 | "babel-traverse": "6.26.0", 88 | "babel-types": "6.26.0" 89 | } 90 | }, 91 | "babel-helper-define-map": { 92 | "version": "6.26.0", 93 | "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", 94 | "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", 95 | "dev": true, 96 | "requires": { 97 | "babel-helper-function-name": "6.24.1", 98 | "babel-runtime": "6.26.0", 99 | "babel-types": "6.26.0", 100 | "lodash": "4.17.4" 101 | } 102 | }, 103 | "babel-helper-function-name": { 104 | "version": "6.24.1", 105 | "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", 106 | "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", 107 | "dev": true, 108 | "requires": { 109 | "babel-helper-get-function-arity": "6.24.1", 110 | "babel-runtime": "6.26.0", 111 | "babel-template": "6.26.0", 112 | "babel-traverse": "6.26.0", 113 | "babel-types": "6.26.0" 114 | } 115 | }, 116 | "babel-helper-get-function-arity": { 117 | "version": "6.24.1", 118 | "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", 119 | "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", 120 | "dev": true, 121 | "requires": { 122 | "babel-runtime": "6.26.0", 123 | "babel-types": "6.26.0" 124 | } 125 | }, 126 | "babel-helper-hoist-variables": { 127 | "version": "6.24.1", 128 | "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", 129 | "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", 130 | "dev": true, 131 | "requires": { 132 | "babel-runtime": "6.26.0", 133 | "babel-types": "6.26.0" 134 | } 135 | }, 136 | "babel-helper-optimise-call-expression": { 137 | "version": "6.24.1", 138 | "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", 139 | "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", 140 | "dev": true, 141 | "requires": { 142 | "babel-runtime": "6.26.0", 143 | "babel-types": "6.26.0" 144 | } 145 | }, 146 | "babel-helper-regex": { 147 | "version": "6.26.0", 148 | "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", 149 | "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", 150 | "dev": true, 151 | "requires": { 152 | "babel-runtime": "6.26.0", 153 | "babel-types": "6.26.0", 154 | "lodash": "4.17.4" 155 | } 156 | }, 157 | "babel-helper-replace-supers": { 158 | "version": "6.24.1", 159 | "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", 160 | "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", 161 | "dev": true, 162 | "requires": { 163 | "babel-helper-optimise-call-expression": "6.24.1", 164 | "babel-messages": "6.23.0", 165 | "babel-runtime": "6.26.0", 166 | "babel-template": "6.26.0", 167 | "babel-traverse": "6.26.0", 168 | "babel-types": "6.26.0" 169 | } 170 | }, 171 | "babel-helpers": { 172 | "version": "6.24.1", 173 | "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", 174 | "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", 175 | "dev": true, 176 | "requires": { 177 | "babel-runtime": "6.26.0", 178 | "babel-template": "6.26.0" 179 | } 180 | }, 181 | "babel-messages": { 182 | "version": "6.23.0", 183 | "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", 184 | "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", 185 | "dev": true, 186 | "requires": { 187 | "babel-runtime": "6.26.0" 188 | } 189 | }, 190 | "babel-plugin-check-es2015-constants": { 191 | "version": "6.22.0", 192 | "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", 193 | "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", 194 | "dev": true, 195 | "requires": { 196 | "babel-runtime": "6.26.0" 197 | } 198 | }, 199 | "babel-plugin-syntax-class-properties": { 200 | "version": "6.13.0", 201 | "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", 202 | "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", 203 | "dev": true 204 | }, 205 | "babel-plugin-transform-class-properties": { 206 | "version": "6.24.1", 207 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", 208 | "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", 209 | "dev": true, 210 | "requires": { 211 | "babel-helper-function-name": "6.24.1", 212 | "babel-plugin-syntax-class-properties": "6.13.0", 213 | "babel-runtime": "6.26.0", 214 | "babel-template": "6.26.0" 215 | } 216 | }, 217 | "babel-plugin-transform-es2015-arrow-functions": { 218 | "version": "6.22.0", 219 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", 220 | "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", 221 | "dev": true, 222 | "requires": { 223 | "babel-runtime": "6.26.0" 224 | } 225 | }, 226 | "babel-plugin-transform-es2015-block-scoped-functions": { 227 | "version": "6.22.0", 228 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", 229 | "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", 230 | "dev": true, 231 | "requires": { 232 | "babel-runtime": "6.26.0" 233 | } 234 | }, 235 | "babel-plugin-transform-es2015-block-scoping": { 236 | "version": "6.26.0", 237 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", 238 | "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", 239 | "dev": true, 240 | "requires": { 241 | "babel-runtime": "6.26.0", 242 | "babel-template": "6.26.0", 243 | "babel-traverse": "6.26.0", 244 | "babel-types": "6.26.0", 245 | "lodash": "4.17.4" 246 | } 247 | }, 248 | "babel-plugin-transform-es2015-classes": { 249 | "version": "6.24.1", 250 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", 251 | "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", 252 | "dev": true, 253 | "requires": { 254 | "babel-helper-define-map": "6.26.0", 255 | "babel-helper-function-name": "6.24.1", 256 | "babel-helper-optimise-call-expression": "6.24.1", 257 | "babel-helper-replace-supers": "6.24.1", 258 | "babel-messages": "6.23.0", 259 | "babel-runtime": "6.26.0", 260 | "babel-template": "6.26.0", 261 | "babel-traverse": "6.26.0", 262 | "babel-types": "6.26.0" 263 | } 264 | }, 265 | "babel-plugin-transform-es2015-computed-properties": { 266 | "version": "6.24.1", 267 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", 268 | "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", 269 | "dev": true, 270 | "requires": { 271 | "babel-runtime": "6.26.0", 272 | "babel-template": "6.26.0" 273 | } 274 | }, 275 | "babel-plugin-transform-es2015-destructuring": { 276 | "version": "6.23.0", 277 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", 278 | "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", 279 | "dev": true, 280 | "requires": { 281 | "babel-runtime": "6.26.0" 282 | } 283 | }, 284 | "babel-plugin-transform-es2015-duplicate-keys": { 285 | "version": "6.24.1", 286 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", 287 | "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", 288 | "dev": true, 289 | "requires": { 290 | "babel-runtime": "6.26.0", 291 | "babel-types": "6.26.0" 292 | } 293 | }, 294 | "babel-plugin-transform-es2015-for-of": { 295 | "version": "6.23.0", 296 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", 297 | "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", 298 | "dev": true, 299 | "requires": { 300 | "babel-runtime": "6.26.0" 301 | } 302 | }, 303 | "babel-plugin-transform-es2015-function-name": { 304 | "version": "6.24.1", 305 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", 306 | "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", 307 | "dev": true, 308 | "requires": { 309 | "babel-helper-function-name": "6.24.1", 310 | "babel-runtime": "6.26.0", 311 | "babel-types": "6.26.0" 312 | } 313 | }, 314 | "babel-plugin-transform-es2015-literals": { 315 | "version": "6.22.0", 316 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", 317 | "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", 318 | "dev": true, 319 | "requires": { 320 | "babel-runtime": "6.26.0" 321 | } 322 | }, 323 | "babel-plugin-transform-es2015-modules-amd": { 324 | "version": "6.24.1", 325 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", 326 | "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", 327 | "dev": true, 328 | "requires": { 329 | "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", 330 | "babel-runtime": "6.26.0", 331 | "babel-template": "6.26.0" 332 | } 333 | }, 334 | "babel-plugin-transform-es2015-modules-commonjs": { 335 | "version": "6.26.0", 336 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", 337 | "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", 338 | "dev": true, 339 | "requires": { 340 | "babel-plugin-transform-strict-mode": "6.24.1", 341 | "babel-runtime": "6.26.0", 342 | "babel-template": "6.26.0", 343 | "babel-types": "6.26.0" 344 | } 345 | }, 346 | "babel-plugin-transform-es2015-modules-strip": { 347 | "version": "0.1.1", 348 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-strip/-/babel-plugin-transform-es2015-modules-strip-0.1.1.tgz", 349 | "integrity": "sha1-c5PwccNWod+2rAMHfgwGy1ejEl8=", 350 | "dev": true 351 | }, 352 | "babel-plugin-transform-es2015-modules-systemjs": { 353 | "version": "6.24.1", 354 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", 355 | "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", 356 | "dev": true, 357 | "requires": { 358 | "babel-helper-hoist-variables": "6.24.1", 359 | "babel-runtime": "6.26.0", 360 | "babel-template": "6.26.0" 361 | } 362 | }, 363 | "babel-plugin-transform-es2015-modules-umd": { 364 | "version": "6.24.1", 365 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", 366 | "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", 367 | "dev": true, 368 | "requires": { 369 | "babel-plugin-transform-es2015-modules-amd": "6.24.1", 370 | "babel-runtime": "6.26.0", 371 | "babel-template": "6.26.0" 372 | } 373 | }, 374 | "babel-plugin-transform-es2015-object-super": { 375 | "version": "6.24.1", 376 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", 377 | "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", 378 | "dev": true, 379 | "requires": { 380 | "babel-helper-replace-supers": "6.24.1", 381 | "babel-runtime": "6.26.0" 382 | } 383 | }, 384 | "babel-plugin-transform-es2015-parameters": { 385 | "version": "6.24.1", 386 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", 387 | "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", 388 | "dev": true, 389 | "requires": { 390 | "babel-helper-call-delegate": "6.24.1", 391 | "babel-helper-get-function-arity": "6.24.1", 392 | "babel-runtime": "6.26.0", 393 | "babel-template": "6.26.0", 394 | "babel-traverse": "6.26.0", 395 | "babel-types": "6.26.0" 396 | } 397 | }, 398 | "babel-plugin-transform-es2015-shorthand-properties": { 399 | "version": "6.24.1", 400 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", 401 | "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", 402 | "dev": true, 403 | "requires": { 404 | "babel-runtime": "6.26.0", 405 | "babel-types": "6.26.0" 406 | } 407 | }, 408 | "babel-plugin-transform-es2015-spread": { 409 | "version": "6.22.0", 410 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", 411 | "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", 412 | "dev": true, 413 | "requires": { 414 | "babel-runtime": "6.26.0" 415 | } 416 | }, 417 | "babel-plugin-transform-es2015-sticky-regex": { 418 | "version": "6.24.1", 419 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", 420 | "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", 421 | "dev": true, 422 | "requires": { 423 | "babel-helper-regex": "6.26.0", 424 | "babel-runtime": "6.26.0", 425 | "babel-types": "6.26.0" 426 | } 427 | }, 428 | "babel-plugin-transform-es2015-template-literals": { 429 | "version": "6.22.0", 430 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", 431 | "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", 432 | "dev": true, 433 | "requires": { 434 | "babel-runtime": "6.26.0" 435 | } 436 | }, 437 | "babel-plugin-transform-es2015-typeof-symbol": { 438 | "version": "6.23.0", 439 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", 440 | "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", 441 | "dev": true, 442 | "requires": { 443 | "babel-runtime": "6.26.0" 444 | } 445 | }, 446 | "babel-plugin-transform-es2015-unicode-regex": { 447 | "version": "6.24.1", 448 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", 449 | "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", 450 | "dev": true, 451 | "requires": { 452 | "babel-helper-regex": "6.26.0", 453 | "babel-runtime": "6.26.0", 454 | "regexpu-core": "2.0.0" 455 | } 456 | }, 457 | "babel-plugin-transform-regenerator": { 458 | "version": "6.26.0", 459 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", 460 | "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", 461 | "dev": true, 462 | "requires": { 463 | "regenerator-transform": "0.10.1" 464 | } 465 | }, 466 | "babel-plugin-transform-strict-mode": { 467 | "version": "6.24.1", 468 | "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", 469 | "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", 470 | "dev": true, 471 | "requires": { 472 | "babel-runtime": "6.26.0", 473 | "babel-types": "6.26.0" 474 | } 475 | }, 476 | "babel-preset-es2015": { 477 | "version": "6.24.1", 478 | "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", 479 | "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", 480 | "dev": true, 481 | "requires": { 482 | "babel-plugin-check-es2015-constants": "6.22.0", 483 | "babel-plugin-transform-es2015-arrow-functions": "6.22.0", 484 | "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", 485 | "babel-plugin-transform-es2015-block-scoping": "6.26.0", 486 | "babel-plugin-transform-es2015-classes": "6.24.1", 487 | "babel-plugin-transform-es2015-computed-properties": "6.24.1", 488 | "babel-plugin-transform-es2015-destructuring": "6.23.0", 489 | "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", 490 | "babel-plugin-transform-es2015-for-of": "6.23.0", 491 | "babel-plugin-transform-es2015-function-name": "6.24.1", 492 | "babel-plugin-transform-es2015-literals": "6.22.0", 493 | "babel-plugin-transform-es2015-modules-amd": "6.24.1", 494 | "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", 495 | "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", 496 | "babel-plugin-transform-es2015-modules-umd": "6.24.1", 497 | "babel-plugin-transform-es2015-object-super": "6.24.1", 498 | "babel-plugin-transform-es2015-parameters": "6.24.1", 499 | "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", 500 | "babel-plugin-transform-es2015-spread": "6.22.0", 501 | "babel-plugin-transform-es2015-sticky-regex": "6.24.1", 502 | "babel-plugin-transform-es2015-template-literals": "6.22.0", 503 | "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", 504 | "babel-plugin-transform-es2015-unicode-regex": "6.24.1", 505 | "babel-plugin-transform-regenerator": "6.26.0" 506 | } 507 | }, 508 | "babel-register": { 509 | "version": "6.26.0", 510 | "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", 511 | "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", 512 | "dev": true, 513 | "requires": { 514 | "babel-core": "6.26.0", 515 | "babel-runtime": "6.26.0", 516 | "core-js": "2.5.2", 517 | "home-or-tmp": "2.0.0", 518 | "lodash": "4.17.4", 519 | "mkdirp": "0.5.1", 520 | "source-map-support": "0.4.18" 521 | } 522 | }, 523 | "babel-runtime": { 524 | "version": "6.26.0", 525 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 526 | "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", 527 | "dev": true, 528 | "requires": { 529 | "core-js": "2.5.2", 530 | "regenerator-runtime": "0.11.1" 531 | } 532 | }, 533 | "babel-template": { 534 | "version": "6.26.0", 535 | "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", 536 | "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", 537 | "dev": true, 538 | "requires": { 539 | "babel-runtime": "6.26.0", 540 | "babel-traverse": "6.26.0", 541 | "babel-types": "6.26.0", 542 | "babylon": "6.18.0", 543 | "lodash": "4.17.4" 544 | } 545 | }, 546 | "babel-traverse": { 547 | "version": "6.26.0", 548 | "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", 549 | "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", 550 | "dev": true, 551 | "requires": { 552 | "babel-code-frame": "6.26.0", 553 | "babel-messages": "6.23.0", 554 | "babel-runtime": "6.26.0", 555 | "babel-types": "6.26.0", 556 | "babylon": "6.18.0", 557 | "debug": "2.6.9", 558 | "globals": "9.18.0", 559 | "invariant": "2.2.2", 560 | "lodash": "4.17.4" 561 | } 562 | }, 563 | "babel-types": { 564 | "version": "6.26.0", 565 | "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", 566 | "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", 567 | "dev": true, 568 | "requires": { 569 | "babel-runtime": "6.26.0", 570 | "esutils": "2.0.2", 571 | "lodash": "4.17.4", 572 | "to-fast-properties": "1.0.3" 573 | } 574 | }, 575 | "babylon": { 576 | "version": "6.18.0", 577 | "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", 578 | "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", 579 | "dev": true 580 | }, 581 | "balanced-match": { 582 | "version": "1.0.0", 583 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 584 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 585 | "dev": true 586 | }, 587 | "brace-expansion": { 588 | "version": "1.1.8", 589 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 590 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 591 | "dev": true, 592 | "requires": { 593 | "balanced-match": "1.0.0", 594 | "concat-map": "0.0.1" 595 | } 596 | }, 597 | "chalk": { 598 | "version": "1.1.3", 599 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 600 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 601 | "dev": true, 602 | "requires": { 603 | "ansi-styles": "2.2.1", 604 | "escape-string-regexp": "1.0.5", 605 | "has-ansi": "2.0.0", 606 | "strip-ansi": "3.0.1", 607 | "supports-color": "2.0.0" 608 | } 609 | }, 610 | "colors": { 611 | "version": "1.0.3", 612 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", 613 | "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", 614 | "dev": true 615 | }, 616 | "concat-map": { 617 | "version": "0.0.1", 618 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 619 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 620 | "dev": true 621 | }, 622 | "convert-source-map": { 623 | "version": "1.5.1", 624 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", 625 | "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", 626 | "dev": true 627 | }, 628 | "core-js": { 629 | "version": "2.5.2", 630 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.2.tgz", 631 | "integrity": "sha1-vEZIZW59ydyA19PHu8Fy2W50TmM=", 632 | "dev": true 633 | }, 634 | "corser": { 635 | "version": "2.0.1", 636 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 637 | "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", 638 | "dev": true 639 | }, 640 | "debug": { 641 | "version": "2.6.9", 642 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 643 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 644 | "dev": true, 645 | "requires": { 646 | "ms": "2.0.0" 647 | } 648 | }, 649 | "detect-indent": { 650 | "version": "4.0.0", 651 | "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", 652 | "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", 653 | "dev": true, 654 | "requires": { 655 | "repeating": "2.0.1" 656 | } 657 | }, 658 | "ecstatic": { 659 | "version": "3.1.1", 660 | "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.1.1.tgz", 661 | "integrity": "sha512-D9UcjcxDMMqjaQxC0mSsFh/IjJSdiZVPnHrhjHuKXlhLByk5QGGPX1GUIDIjRzhTq4UDCPYwWblw79VBEh3r1w==", 662 | "dev": true, 663 | "requires": { 664 | "he": "1.1.1", 665 | "mime": "1.6.0", 666 | "minimist": "1.2.0", 667 | "url-join": "2.0.5" 668 | }, 669 | "dependencies": { 670 | "minimist": { 671 | "version": "1.2.0", 672 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 673 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 674 | "dev": true 675 | } 676 | } 677 | }, 678 | "escape-string-regexp": { 679 | "version": "1.0.5", 680 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 681 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 682 | "dev": true 683 | }, 684 | "esutils": { 685 | "version": "2.0.2", 686 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 687 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 688 | "dev": true 689 | }, 690 | "eventemitter3": { 691 | "version": "1.2.0", 692 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", 693 | "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", 694 | "dev": true 695 | }, 696 | "globals": { 697 | "version": "9.18.0", 698 | "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", 699 | "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", 700 | "dev": true 701 | }, 702 | "has-ansi": { 703 | "version": "2.0.0", 704 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 705 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 706 | "dev": true, 707 | "requires": { 708 | "ansi-regex": "2.1.1" 709 | } 710 | }, 711 | "he": { 712 | "version": "1.1.1", 713 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", 714 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", 715 | "dev": true 716 | }, 717 | "home-or-tmp": { 718 | "version": "2.0.0", 719 | "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", 720 | "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", 721 | "dev": true, 722 | "requires": { 723 | "os-homedir": "1.0.2", 724 | "os-tmpdir": "1.0.2" 725 | } 726 | }, 727 | "http-proxy": { 728 | "version": "1.16.2", 729 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", 730 | "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", 731 | "dev": true, 732 | "requires": { 733 | "eventemitter3": "1.2.0", 734 | "requires-port": "1.0.0" 735 | } 736 | }, 737 | "http-server": { 738 | "version": "0.11.1", 739 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz", 740 | "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==", 741 | "dev": true, 742 | "requires": { 743 | "colors": "1.0.3", 744 | "corser": "2.0.1", 745 | "ecstatic": "3.1.1", 746 | "http-proxy": "1.16.2", 747 | "opener": "1.4.3", 748 | "optimist": "0.6.1", 749 | "portfinder": "1.0.13", 750 | "union": "0.4.6" 751 | } 752 | }, 753 | "invariant": { 754 | "version": "2.2.2", 755 | "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", 756 | "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", 757 | "dev": true, 758 | "requires": { 759 | "loose-envify": "1.3.1" 760 | } 761 | }, 762 | "is-finite": { 763 | "version": "1.0.2", 764 | "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", 765 | "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", 766 | "dev": true, 767 | "requires": { 768 | "number-is-nan": "1.0.1" 769 | } 770 | }, 771 | "js-tokens": { 772 | "version": "3.0.2", 773 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 774 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 775 | "dev": true 776 | }, 777 | "jsesc": { 778 | "version": "1.3.0", 779 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", 780 | "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", 781 | "dev": true 782 | }, 783 | "json5": { 784 | "version": "0.5.1", 785 | "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", 786 | "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", 787 | "dev": true 788 | }, 789 | "lodash": { 790 | "version": "4.17.4", 791 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 792 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", 793 | "dev": true 794 | }, 795 | "loose-envify": { 796 | "version": "1.3.1", 797 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", 798 | "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", 799 | "dev": true, 800 | "requires": { 801 | "js-tokens": "3.0.2" 802 | } 803 | }, 804 | "mime": { 805 | "version": "1.6.0", 806 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 807 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 808 | "dev": true 809 | }, 810 | "minimatch": { 811 | "version": "3.0.4", 812 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 813 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 814 | "dev": true, 815 | "requires": { 816 | "brace-expansion": "1.1.8" 817 | } 818 | }, 819 | "minimist": { 820 | "version": "0.0.8", 821 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 822 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 823 | "dev": true 824 | }, 825 | "mkdirp": { 826 | "version": "0.5.1", 827 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 828 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 829 | "dev": true, 830 | "requires": { 831 | "minimist": "0.0.8" 832 | } 833 | }, 834 | "ms": { 835 | "version": "2.0.0", 836 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 837 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 838 | "dev": true 839 | }, 840 | "number-is-nan": { 841 | "version": "1.0.1", 842 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 843 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 844 | "dev": true 845 | }, 846 | "opener": { 847 | "version": "1.4.3", 848 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", 849 | "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", 850 | "dev": true 851 | }, 852 | "optimist": { 853 | "version": "0.6.1", 854 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 855 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 856 | "dev": true, 857 | "requires": { 858 | "minimist": "0.0.8", 859 | "wordwrap": "0.0.3" 860 | } 861 | }, 862 | "os-homedir": { 863 | "version": "1.0.2", 864 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 865 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", 866 | "dev": true 867 | }, 868 | "os-tmpdir": { 869 | "version": "1.0.2", 870 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 871 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 872 | "dev": true 873 | }, 874 | "path-is-absolute": { 875 | "version": "1.0.1", 876 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 877 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 878 | "dev": true 879 | }, 880 | "portfinder": { 881 | "version": "1.0.13", 882 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", 883 | "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", 884 | "dev": true, 885 | "requires": { 886 | "async": "1.5.2", 887 | "debug": "2.6.9", 888 | "mkdirp": "0.5.1" 889 | } 890 | }, 891 | "private": { 892 | "version": "0.1.8", 893 | "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", 894 | "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", 895 | "dev": true 896 | }, 897 | "qs": { 898 | "version": "2.3.3", 899 | "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", 900 | "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", 901 | "dev": true 902 | }, 903 | "regenerate": { 904 | "version": "1.3.3", 905 | "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", 906 | "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", 907 | "dev": true 908 | }, 909 | "regenerator-runtime": { 910 | "version": "0.11.1", 911 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", 912 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", 913 | "dev": true 914 | }, 915 | "regenerator-transform": { 916 | "version": "0.10.1", 917 | "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", 918 | "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", 919 | "dev": true, 920 | "requires": { 921 | "babel-runtime": "6.26.0", 922 | "babel-types": "6.26.0", 923 | "private": "0.1.8" 924 | } 925 | }, 926 | "regexpu-core": { 927 | "version": "2.0.0", 928 | "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", 929 | "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", 930 | "dev": true, 931 | "requires": { 932 | "regenerate": "1.3.3", 933 | "regjsgen": "0.2.0", 934 | "regjsparser": "0.1.5" 935 | } 936 | }, 937 | "regjsgen": { 938 | "version": "0.2.0", 939 | "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", 940 | "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", 941 | "dev": true 942 | }, 943 | "regjsparser": { 944 | "version": "0.1.5", 945 | "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", 946 | "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", 947 | "dev": true, 948 | "requires": { 949 | "jsesc": "0.5.0" 950 | }, 951 | "dependencies": { 952 | "jsesc": { 953 | "version": "0.5.0", 954 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", 955 | "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", 956 | "dev": true 957 | } 958 | } 959 | }, 960 | "repeating": { 961 | "version": "2.0.1", 962 | "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", 963 | "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", 964 | "dev": true, 965 | "requires": { 966 | "is-finite": "1.0.2" 967 | } 968 | }, 969 | "requires-port": { 970 | "version": "1.0.0", 971 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 972 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", 973 | "dev": true 974 | }, 975 | "slash": { 976 | "version": "1.0.0", 977 | "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", 978 | "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", 979 | "dev": true 980 | }, 981 | "source-map": { 982 | "version": "0.5.7", 983 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 984 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 985 | "dev": true 986 | }, 987 | "source-map-support": { 988 | "version": "0.4.18", 989 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", 990 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", 991 | "dev": true, 992 | "requires": { 993 | "source-map": "0.5.7" 994 | } 995 | }, 996 | "strip-ansi": { 997 | "version": "3.0.1", 998 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 999 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1000 | "dev": true, 1001 | "requires": { 1002 | "ansi-regex": "2.1.1" 1003 | } 1004 | }, 1005 | "supports-color": { 1006 | "version": "2.0.0", 1007 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1008 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 1009 | "dev": true 1010 | }, 1011 | "to-fast-properties": { 1012 | "version": "1.0.3", 1013 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", 1014 | "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", 1015 | "dev": true 1016 | }, 1017 | "trim-right": { 1018 | "version": "1.0.1", 1019 | "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", 1020 | "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", 1021 | "dev": true 1022 | }, 1023 | "union": { 1024 | "version": "0.4.6", 1025 | "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", 1026 | "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", 1027 | "dev": true, 1028 | "requires": { 1029 | "qs": "2.3.3" 1030 | } 1031 | }, 1032 | "url-join": { 1033 | "version": "2.0.5", 1034 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", 1035 | "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", 1036 | "dev": true 1037 | }, 1038 | "wordwrap": { 1039 | "version": "0.0.3", 1040 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 1041 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", 1042 | "dev": true 1043 | } 1044 | } 1045 | } 1046 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "img-2", 3 | "version": "0.0.4", 4 | "repository": "https://github.com/RevillWeb/img-2.git", 5 | "description": "Replace elements with to automatically pre-cache images and improve page performance.", 6 | "main": "dist/img-2.js", 7 | "scripts": { 8 | "watch": "babel --plugins=transform-class-properties,transform-es2015-modules-strip src/img-2.js --out-file dist/img-2.js --watch", 9 | "build": "babel --plugins=transform-class-properties,transform-es2015-modules-strip src/img-2.js --out-file dist/img-2.js && babel --plugins=transform-class-properties --presets=es2015 src/img-2.js --out-file dist/img-2.es5.js", 10 | "serve": "http-server -p 3232 ." 11 | }, 12 | "keywords": [ 13 | "pre-cache", 14 | "pre-load" 15 | ], 16 | "author": "Leon Revill (@revillweb)", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "babel-core": "^6.26.0", 20 | "babel-plugin-transform-class-properties": "^6.24.1", 21 | "babel-plugin-transform-es2015-modules-strip": "^0.1.1", 22 | "babel-preset-es2015": "^6.24.1", 23 | "http-server": "^0.11.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/img-2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Leon Revill on 10/12/2017. 3 | * Blog: blog.revillweb.com 4 | * Twitter: @RevillWeb 5 | * GitHub: github.com/RevillWeb 6 | */ 7 | class Img2 extends HTMLElement { 8 | 9 | constructor() { 10 | super(); 11 | 12 | // Private class variables 13 | this._root = null; 14 | this._$img = null; 15 | this._$preview = null; 16 | this._preview = null; 17 | this._src = null; 18 | this._width = null; 19 | this._height = null; 20 | this._reset(); 21 | 22 | // Settings 23 | this._renderOnPreCached = Img2.settings.RENDER_ON_PRECACHED; 24 | 25 | // Bound class methods 26 | this._precache = this._precache.bind(this); 27 | this._onImgLoad = this._onImgLoad.bind(this); 28 | this._onImgPreCached = this._onImgPreCached.bind(this); 29 | 30 | } 31 | 32 | get loaded() { 33 | return this._loaded; 34 | } 35 | 36 | /** 37 | * Reset all private values 38 | * @private 39 | */ 40 | _reset() { 41 | if (this._loaded === true) this.removeAttribute("loaded"); 42 | this._inited = false; 43 | this._rendered = false; 44 | this._loading = false; 45 | this._loaded = false; 46 | this._preCaching = false; 47 | this._preCached = false; 48 | } 49 | 50 | connectedCallback() { 51 | 52 | if (window.ShadyCSS) ShadyCSS.styleElement(this); 53 | // Override any global settings 54 | this._renderOnPreCached = (this.getAttribute("render-on-pre-cached") === "true"); 55 | this._init(); 56 | 57 | } 58 | 59 | _init() { 60 | 61 | // Check to see if we have a src, if not return and do nothing else 62 | this._src = this.getAttribute("src"); 63 | // Grab the initial attribute values 64 | this._preview = this.getAttribute("src-preview"); 65 | this._width = this.getAttribute("width"); 66 | this._height = this.getAttribute("height"); 67 | 68 | if (!this._src || !this._width || !this._height) return; 69 | 70 | // Set the height and width of the element so that we can figure out if it is on the screen or not 71 | this.style.width = `${this._width}px`; 72 | this.style.height = `${this._height}px`; 73 | 74 | // Figure out if this image is within view 75 | Img2.addIntersectListener(this, () => { 76 | Img2._removePreCacheListener(this._precache); 77 | this._render(); 78 | this._load(); 79 | Img2.removeIntersectListener(this); 80 | }); 81 | 82 | // Listen for precache instruction 83 | Img2._addPreCacheListener(this._precache, this._src); 84 | this._inited = true; 85 | } 86 | 87 | /** 88 | * Method which displays the image once ready to be displayed 89 | * @private 90 | */ 91 | _load() { 92 | if (this._preCached === false) Img2._priorityCount += 1; 93 | this._$img.onload = this._onImgLoad; 94 | this._loading = true; 95 | this._$img.src = this._src; 96 | } 97 | 98 | _onImgLoad() { 99 | this._loading = false; 100 | this._loaded = true; 101 | if (this._$preview !== null) { 102 | this._root.removeChild(this._$preview); 103 | this._$preview = null; 104 | } 105 | this._$img.onload = null; 106 | if (this._preCached === false) Img2._priorityCount -= 1; 107 | this.setAttribute("loaded", ""); 108 | } 109 | 110 | _onImgPreCached() { 111 | this._preCaching = false; 112 | this._preCached = true; 113 | if (this._renderOnPreCached !== false) { 114 | this._render(); 115 | this._load(); 116 | } 117 | } 118 | 119 | static get observedAttributes() { 120 | return ["src", "width", "height", "alt"]; 121 | } 122 | attributeChangedCallback(name, oldValue, newValue) { 123 | 124 | // If nothing has changed then just return 125 | if (newValue === oldValue) return; 126 | 127 | switch (name) { 128 | case "src": 129 | // If the src is changed then we need to reset and start again 130 | this._reset(); 131 | this._init(); 132 | break; 133 | case "width": 134 | this._width = newValue; 135 | if (this._$preview !== null) this._$preview.width = this._width; 136 | if (this._$img !== null) this._$img.width = this._width; 137 | this.style.width = `${this._width}px`; 138 | if (!this._inited) this._init(); 139 | break; 140 | case "height": 141 | this._height = newValue; 142 | if (this._$preview !== null) this._$preview.height = this._height; 143 | if (this._$img !== null) this._$img.height = this._height; 144 | this.style.height = `${this._height}px`; 145 | if (!this._inited) this._init(); 146 | break; 147 | case "render-on-pre-cached": 148 | this._renderOnPreCached = !(newValue === "false"); 149 | break; 150 | case "alt": 151 | this._updateAttribute("alt", newValue); 152 | break; 153 | } 154 | } 155 | 156 | /** 157 | * Method used to update an individual attribute on the native image element 158 | * @param {string} name - The name of the attribute to update 159 | * @param {string} value - The new attribute value 160 | * @private 161 | */ 162 | _updateAttribute(name, value) { 163 | // If the image element hasn't been rendered yet, just return. 164 | if (this._rendered === false) return; 165 | this._$img.setAttribute(name, value); 166 | } 167 | 168 | /** 169 | * Method which renders the DOM elements and displays any preview image 170 | * @private 171 | */ 172 | _render() { 173 | 174 | if (this._rendered === true) return; 175 | 176 | // Render the Shadow Root if not done already (src change can force this method to be called again) 177 | if (this._root === null) { 178 | // Attach the Shadow Root to the element 179 | this._root = this.attachShadow({mode: "open"}); 180 | // Create the initial template with styles 181 | let $template = document.createElement("template"); 182 | $template.innerHTML = ` 183 | 210 | `; 211 | if (window.ShadyCSS) ShadyCSS.prepareTemplate($template, "img-2"); 212 | this._root.appendChild(document.importNode($template.content, true)); 213 | } 214 | 215 | // If a preview image has been specified 216 | if (this._$preview === null && this._preview !== null && this._loaded === false) { 217 | // Create the element 218 | this._$preview = document.createElement("img"); 219 | this._$preview.classList.add("img2-preview"); 220 | this._$preview.src = this._preview; 221 | // Add the specified width and height 222 | this._$preview.width = this._width; 223 | this._$preview.height = this._height; 224 | // Add it to the Shadow Root 225 | this._root.appendChild(this._$preview); 226 | } 227 | 228 | // Render the img element if not done already 229 | if (this._$img === null) { 230 | // Create the actual image element to be used to display the image 231 | this._$img = document.createElement("img"); 232 | this._$img.classList.add("img2-src"); 233 | // add the specified width and height to the image element 234 | this._$img.width = this._width; 235 | this._$img.height = this._height; 236 | const alt = this.getAttribute("alt"); 237 | if (alt !== null) this._$img.setAttribute("alt", alt); 238 | // Add the image to the Shadow Root 239 | this._root.appendChild(this._$img); 240 | } 241 | 242 | // Flag as rendered 243 | this._rendered = true; 244 | 245 | } 246 | 247 | _precache() { 248 | this._preCaching = true; 249 | Img2._preCache(this._src, this._onImgPreCached); 250 | } 251 | 252 | static _preCacheListeners = new Map(); 253 | static _addPreCacheListener(cb, url) { 254 | Img2._preCacheListeners.set(cb, url); 255 | } 256 | 257 | static _removePreCacheListener(cb) { 258 | Img2._preCacheListeners.delete(cb); 259 | } 260 | 261 | static _startPreCache() { 262 | for (let cb of Img2._preCacheListeners.keys()) cb(); 263 | } 264 | 265 | /** 266 | * Methods used to determine when currently visible (priority) elements have finished download to then inform other elements to pre-cache 267 | */ 268 | 269 | static __priorityCount = 0; 270 | static _startPreCacheDebounce = null; 271 | static get _priorityCount() { 272 | return Img2.__priorityCount; 273 | } 274 | static set _priorityCount(value) { 275 | Img2.__priorityCount = value; 276 | if (Img2.__priorityCount < 1) { 277 | // Inform components that they can start to pre-cache their images 278 | // Debounce in case the user scrolls because then there will be more priority images 279 | if (Img2._startPreCacheDebounce !== null) { 280 | clearTimeout(Img2._startPreCacheDebounce); 281 | Img2._startPreCacheDebounce = null; 282 | } 283 | Img2._startPreCacheDebounce = setTimeout(function(){ 284 | if (Img2.__priorityCount < 1) Img2._startPreCache(); 285 | }, 500); 286 | } 287 | } 288 | 289 | /** 290 | * Methods used to determine when this element is in the visible viewport 291 | */ 292 | static _intersectListeners = new Map(); 293 | static _observer = new IntersectionObserver(Img2._handleIntersect, { 294 | root: null, 295 | rootMargin: "0px", 296 | threshold: 0 297 | }); 298 | 299 | static addIntersectListener($element, intersectCallback) { 300 | Img2._intersectListeners.set($element, intersectCallback); 301 | Img2._observer.observe($element); 302 | } 303 | 304 | static removeIntersectListener($element) { 305 | if ($element) Img2._observer.unobserve($element); 306 | } 307 | 308 | static _handleIntersect(entries) { 309 | entries.forEach(entry => { 310 | if (entry.isIntersecting === true) { 311 | const cb = Img2._intersectListeners.get(entry.target); 312 | if (cb !== undefined) cb(entry); 313 | } 314 | }); 315 | } 316 | 317 | static _preCacheCallbacks = {}; 318 | static _preCache(url, cb) { 319 | 320 | let slot = Img2._preCacheCallbacks[url]; 321 | if (slot === undefined) { 322 | Img2._preCacheCallbacks[url] = { 323 | cached: false, 324 | cbs: [cb] 325 | }; 326 | const absolute = url.indexOf("http") === 0 || url.indexOf("/") === 0; 327 | const location = absolute ? url : window.location.href + url; 328 | Img2._worker.postMessage({ location: location, url: url }); 329 | } else { 330 | if (slot.cached === true) { 331 | cb(); 332 | } else { 333 | slot.cbs.push(cb); 334 | } 335 | } 336 | } 337 | } 338 | 339 | /** 340 | * Methods used to pre-cache images using a WebWorker 341 | */ 342 | 343 | Img2._worker = new Worker(window.URL.createObjectURL( 344 | new Blob([`self.onmessage=${function (e) { 345 | const xhr = new XMLHttpRequest(); 346 | function onload() { 347 | self.postMessage(e.data.url); 348 | } 349 | xhr.responseType = "blob"; 350 | xhr.onload = xhr.onerror = onload; 351 | xhr.open("GET", e.data.location, true); 352 | xhr.send(); 353 | }.toString()};`], { type: "text/javascript"}) 354 | )); 355 | 356 | Img2._worker.onmessage = function (e) { 357 | const slot = Img2._preCacheCallbacks[e.data]; 358 | if (slot !== undefined) { 359 | slot.cached = true; 360 | slot.cbs = slot.cbs.filter(cb => { 361 | // Call the callback 362 | cb(); 363 | // Remove the callback 364 | return false; 365 | }); 366 | } 367 | }; 368 | 369 | /** Img2 Settings **/ 370 | Img2.settings = { 371 | "RENDER_ON_PRECACHED": false // Set this to false to save memory but can cause jank during scrolling 372 | }; 373 | 374 | window.customElements.define("img-2", Img2); 375 | --------------------------------------------------------------------------------