/** * Modules in this bundle * @license * * smartphoto: * license: MIT (http://opensource.org/licenses/MIT) * author: appleple * homepage: http://developer.a-blogcms.jp * version: 0.5.9 * * a-template: * license: MIT (http://opensource.org/licenses/MIT) * author: steelydylan * maintainers: steelydylan * version: 0.2.0 * * delegate: * license: MIT (http://opensource.org/licenses/MIT) * maintainers: zenorocha * homepage: https://github.com/zenorocha/delegate#readme * version: 3.1.2 * * morphdom: * license: MIT (http://opensource.org/licenses/MIT) * author: Patrick Steele-Idem * maintainers: mlrawlings , pnidem * homepage: https://github.com/patrick-steele-idem/morphdom#readme * version: 2.3.2 * * This header is generated by licensify (https://github.com/twada/licensify) */ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.smartPhoto = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o>> 0; var thisArg = arguments[1]; var value = void 0; for (var i = 0; i < length; i++) { value = list[i]; if (predicate.call(thisArg, value, i, list)) { return value; } } return undefined; }; } if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function (s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i = matches.length; while (--i >= 0 && matches.item(i) !== this) {} return i > -1; }; } var selector = function selector(_selector) { return document.querySelector(_selector); }; var getObjectById = function getObjectById(id) { for (var i = 0, n = objs.length; i < n; i++) { var obj = objs[i]; var templates = obj.templates; for (var t = 0, m = templates.length; t < m; t++) { if (templates[t] == id) { return obj; } } } return null; }; var findAncestor = function findAncestor(element, selector) { if (typeof element.closest === 'function') { return element.closest(selector) || null; } while (element) { if (element.matches(selector)) { return element; } element = element.parentElement; } return null; }; var on = function on(element, query, e, fn) { var events = e.split(' '); events.forEach(function (event) { delegate(element, query, event, fn); }); }; if (typeof document !== "undefined") { //data binding on(document, '[data-bind]', 'input change click', function (e) { var target = e.delegateTarget; var data = target.getAttribute('data-bind'); var attr = target.getAttribute('href'); var id = findAncestor(target, '[data-id]').getAttribute('data-id'); var value = target.value; if (attr) { value = value.replace('#', ''); } if (id) { var obj = getObjectById(id); if (target.getAttribute('type') === 'radio') {} else if (target.getAttribute('type') === 'checkbox') { (function () { var arr = []; var items = document.querySelectorAll('[data-bind="' + data + '"]'); [].forEach.call(items, function (item) { if (item.checked) { arr.push(item.value); } }); })(); } else { obj.updateDataByString(data, value); } } }); //action on(document, dataAction, eventType, function (e) { var target = e.delegateTarget; if (e.type === "click" && target.tagName === 'select') { return; } if (e.type === "input" && target.getAttribute("type") === "button") { return; } var events = eventType.split(" "); var action = "action"; events.forEach(function (event) { if (target.getAttribute("data-action-" + event)) { if (e.type === event) { action += "-" + event; } } }); var string = target.getAttribute('data-' + action); if (!string) { return; } var method = string.replace(/\(.*?\);?/, ""); var parameter = string.replace(/(.*?)\((.*?)\);?/, "$2"); var pts = parameter.split(","); //寮曘亶鏁 var id = findAncestor(target, '[data-id]').getAttribute('data-id'); if (!id) { return; } var obj = getObjectById(id); obj.e = e; if (obj.method && obj.method[method]) { obj.method[method].apply(obj, pts); } else if (obj[method]) { obj[method].apply(obj, pts); } }); } var aTemplate = function () { function aTemplate(opt) { _classCallCheck(this, aTemplate); this.atemplate = []; objs.push(this); for (var i in opt) { this[i] = opt[i]; } if (!this.data) { this.data = {}; } if (!this.templates) { this.templates = []; } var templates = this.templates; var length = templates.length; for (var _i = 0, n = length; _i < n; _i++) { var template = this.templates[_i]; var html = selector('#' + template).innerHTML; this.atemplate.push({ id: template, html: html }); } this.setId(); } _createClass(aTemplate, [{ key: 'addTemplate', value: function addTemplate(id, html) { this.atemplate.push({ id: id, html: html }); this.templates.push(id); } }, { key: 'loadHtml', value: function loadHtml() { var templates = this.templates; var promises = []; templates.forEach(function (template) { var d = new $.Deferred(); promises.push(d); var src = selector('#' + template).getAttribute('src'); $.ajax({ url: src, type: 'GET', dataType: 'text' }).success(function (data) { selector('#' + template).innerHTML = data; d.resolve(); }); }); return $.when.apply($, promises); } }, { key: 'getData', value: function getData() { return JSON.parse(JSON.stringify(this.data)); } }, { key: 'saveData', value: function saveData(key) { var data = JSON.stringify(this.data); localStorage.setItem(key, data); } }, { key: 'setData', value: function setData(val) { for (var i in val) { if (typeof val[i] !== "function") { this.data[i] = val[i]; } } } }, { key: 'loadData', value: function loadData(key) { var data = JSON.parse(localStorage.getItem(key)); if (data) { for (var i in data) { if (typeof data[i] !== "function") { this.data[i] = data[i]; } } } } }, { key: 'getRand', value: function getRand(a, b) { return ~~(Math.random() * (b - a + 1)) + a; } }, { key: 'getRandText', value: function getRandText(limit) { var ret = ""; var strings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var length = strings.length; for (var i = 0; i < limit; i++) { ret += strings.charAt(Math.floor(this.getRand(0, length))); } return ret; } }, { key: 'setId', value: function setId() { var text = void 0; var ids = aTemplate.ids; var flag = false; while (1) { text = this.getRandText(10); for (var i = 0, n = aTemplate.ids; i < n; i++) { if (aTemplate.ids[i] === text) { flag = true; } } if (flag === false) { break; } } this.data.aTemplate_id = text; } }, { key: 'getDataFromObj', value: function getDataFromObj(s, o) { s = s.replace(/\[([a-zA-Z0-9._-]+)\]/g, '.$1'); // convert indexes to properties s = s.replace(/^\./, ''); // strip leading dot var a = s.split('.'); while (a.length) { var n = a.shift(); if (n in o) { o = o[n]; } else { return; } } return o; } }, { key: 'getDataByString', value: function getDataByString(s) { var o = this.data; return this.getDataFromObj(s, o); } }, { key: 'updateDataByString', value: function updateDataByString(path, newValue) { var object = this.data; var stack = path.split('.'); while (stack.length > 1) { object = object[stack.shift()]; } object[stack.shift()] = newValue; } }, { key: 'removeDataByString', value: function removeDataByString(path) { var object = this.data; var stack = path.split('.'); while (stack.length > 1) { object = object[stack.shift()]; } var shift = stack.shift(); if (shift.match(/^\d+$/)) { object.splice(Number(shift), 1); } else { delete object[shift]; } } }, { key: 'resolveBlock', value: function resolveBlock(html, item, i) { var that = this; var touchs = html.match(//g); var touchnots = html.match(//g); var exists = html.match(//g); var empties = html.match(//g); /*銈裤儍銉併儢銉儍銈В姹?/ if (touchs) { for (var k = 0, n = touchs.length; k < n; k++) { var start = touchs[k]; start = start.replace(/([a-zA-Z0-9._-]+):touch#([a-zA-Z0-9._-]+)/, "($1):touch#($2)"); var end = start.replace(/BEGIN/, "END"); var reg = new RegExp(start + "(([\\n\\r\\t]|.)*?)" + end, "g"); html = html.replace(reg, function (m, key2, val, next) { var itemkey = typeof item[key2] === "function" ? item[key2].apply(that) : that.getDataFromObj(key2, item); if (itemkey == val) { return next; } else { return ""; } }); } } /*銈裤儍銉併儙銉冦儓銉栥儹銉冦偗瑙f焙*/ if (touchnots) { for (var _k = 0, _n = touchnots.length; _k < _n; _k++) { var _start = touchnots[_k]; _start = _start.replace(/([a-zA-Z0-9._-]+):touchnot#([a-zA-Z0-9._-]+)/, "($1):touchnot#($2)"); var _end = _start.replace(/BEGIN/, "END"); var _reg = new RegExp(_start + "(([\\n\\r\\t]|.)*?)" + _end, "g"); html = html.replace(_reg, function (m, key2, val, next) { var itemkey = typeof item[key2] === "function" ? item[key2].apply(that) : that.getDataFromObj(key2, item); if (itemkey != val) { return next; } else { return ""; } }); } } /*exist銉栥儹銉冦偗銈掕В姹?/ if (exists) { for (var _k2 = 0, _n2 = exists.length; _k2 < _n2; _k2++) { var _start2 = exists[_k2]; _start2 = _start2.replace(/([a-zA-Z0-9._-]+):exist/, "($1):exist"); var _end2 = _start2.replace(/BEGIN/, "END"); var _reg2 = new RegExp(_start2 + "(([\\n\\r\\t]|.)*?)" + _end2, "g"); html = html.replace(_reg2, function (m, key2, next) { var itemkey = typeof item[key2] === "function" ? item[key2].apply(that) : that.getDataFromObj(key2, item); if (itemkey || itemkey === 0) { return next; } else { return ""; } }); } } /*empty銉栥儹銉冦偗銈掕В姹?/ if (empties) { for (var _k3 = 0, _n3 = empties.length; _k3 < _n3; _k3++) { var _start3 = empties[_k3]; _start3 = _start3.replace(/([a-zA-Z0-9._-]+):empty/, "($1):empty"); var _end3 = _start3.replace(/BEGIN/, "END"); var empty = new RegExp(_start3 + "(([\\n\\r\\t]|.)*?)" + _end3, "g"); html = html.replace(empty, function (m, key2, next) { var itemkey = typeof item[key2] === "function" ? item[key2].apply(that) : that.getDataFromObj(key2, item); if (!itemkey && itemkey !== 0) { return next; } else { return ""; } }); } } /*澶夋暟瑙f焙*/ html = html.replace(/{([a-zA-Z0-9._-]+)}(\[([a-zA-Z0-9._-]+)\])*/g, function (n, key3, key4, converter) { var data = void 0; if (key3 == "i") { data = i; } else { if (item[key3] || item[key3] === 0) { if (typeof item[key3] === "function") { data = item[key3].apply(that); } else { data = item[key3]; } } else { if (converter && that.convert && that.convert[converter]) { return that.convert[converter].call(that, ""); } else { return ""; } } } if (converter && that.convert && that.convert[converter]) { return that.convert[converter].call(that, data); } else { return data; } }); return html; } /*绲跺銉戙偣褰㈠紡銇鏁般倰瑙f焙*/ }, { key: 'resolveAbsBlock', value: function resolveAbsBlock(html) { var that = this; html = html.replace(/{(.*?)}/g, function (n, key3) { var data = that.getDataByString(key3); if (typeof data !== "undefined") { if (typeof data === "function") { return data.apply(that); } else { return data; } } else { return n; } }); return html; } }, { key: 'resolveInclude', value: function resolveInclude(html) { var include = //g; html = html.replace(include, function (m, key) { return selector('#' + key).innerHTML; }); return html; } }, { key: 'resolveWith', value: function resolveWith(html) { var width = /(([\n\r\t]|.)*?)/g; html = html.replace(width, function (m, key, val) { m = m.replace(/data\-bind=['"](.*?)['"]/g, "data-bind='" + key + ".$1'"); return m; }); return html; } }, { key: 'resolveLoop', value: function resolveLoop(html) { var loop = /(([\n\r\t]|.)*?)/g; var that = this; /*銉兗銉楁枃瑙f焙*/ html = html.replace(loop, function (m, key, val) { var keyItem = that.getDataByString(key); var keys = []; if (typeof keyItem === "function") { keys = keyItem.apply(that); } else { keys = keyItem; } var ret = ""; if (keys instanceof Array) { for (var i = 0, n = keys.length; i < n; i++) { ret += that.resolveBlock(val, keys[i], i); } } /*銈ㄣ偣銈便兗銉楀墛闄?/ ret = ret.replace(/\\([^\\])/g, "$1"); return ret; }); return html; } }, { key: 'removeData', value: function removeData(arr) { var data = this.data; for (var i in data) { for (var t = 0, n = arr.length; t < n; t++) { if (i === arr[t]) { delete data[i]; } } } return this; } }, { key: 'hasLoop', value: function hasLoop(txt) { var loop = /(([\n\r\t]|.)*?)/g; if (txt.match(loop)) { return true; } else { return false; } } }, { key: 'getHtml', value: function getHtml(selector, row) { var template = this.atemplate.find(function (item) { return item.id === selector; }); var html = ""; if (template && template.html) { html = template.html; } if (row) { html = selector; } if (!html) { return ""; } var data = this.data; /*銈ゃ兂銈儷銉笺儔瑙f焙*/ html = this.resolveInclude(html); /*with瑙f焙*/ html = this.resolveWith(html); /*銉兗銉楄В姹?/ while (this.hasLoop(html)) { html = this.resolveLoop(html); } /*澶夋暟瑙f焙*/ html = this.resolveBlock(html, data); /*銈ㄣ偣銈便兗銉楀墛闄?/ html = html.replace(/\\([^\\])/g, "$1"); /*绲跺銉戙偣銇ф寚瀹氥仌銈屻仧澶夋暟銈掕В姹?/ html = this.resolveAbsBlock(html); /*绌鸿鍓婇櫎*/ return html.replace(/^([\t ])*\n/gm, ""); } }, { key: 'update', value: function update(txt, part) { var html = this.getHtml(); var templates = this.templates; var renderWay = txt || "html"; if (this.beforeUpdated) { this.beforeUpdated(); } for (var i = 0, n = templates.length; i < n; i++) { var tem = templates[i]; var query = "#" + tem; var _html = this.getHtml(tem); var target = selector('[data-id=\'' + tem + '\']'); if (!part || part == tem) { if (!target) { selector(query).insertAdjacentHTML('afterend', '
'); if (renderWay === 'text') { selector('[data-id=\'' + tem + '\']').innerText = _html; } else { selector('[data-id=\'' + tem + '\']').innerHTML = _html; } } else { if (renderWay === 'text') { target.innerText = _html; } else { morphdom(target, '
' + _html + '
'); } } if (part) { break; } } } this.updateBindingData(part); if (this.onUpdated) { this.onUpdated(part); } return this; } }, { key: 'updateBindingData', value: function updateBindingData(part) { var _this = this; var templates = this.templates; for (var i = 0, n = templates.length; i < n; i++) { var temp = templates[i]; if (!part || part == temp) { var template = selector('[data-id=\'' + temp + '\']'); var binds = template.querySelectorAll('[data-bind]'); [].forEach.call(binds, function (item) { var data = _this.getDataByString(item.getAttribute("data-bind")); if (item.getAttribute("type") === "checkbox" || item.getAttribute("type") === "radio") { if (data == item.value) { item.checked = true; } } else { item.value = data; } }); if (part) { break; } } } return this; } }, { key: 'applyMethod', value: function applyMethod(method) { var args = [].splice.call(arguments, 0); args.shift(); return this.method[method].apply(this, args); } }, { key: 'getComputedProp', value: function getComputedProp(prop) { return this.data[prop].apply(this); } }, { key: 'remove', value: function remove(path) { var object = this.data; var stack = path.split('.'); while (stack.length > 1) { object = object[stack.shift()]; } var shift = stack.shift(); if (shift.match(/^\d+$/)) { object.splice(Number(shift), 1); } else { delete object[shift]; } return this; } }]); return aTemplate; }(); module.exports = aTemplate; },{"delegate":3,"morphdom":4}],2:[function(require,module,exports){ var DOCUMENT_NODE_TYPE = 9; /** * A polyfill for Element.matches() */ if (typeof Element !== 'undefined' && !Element.prototype.matches) { var proto = Element.prototype; proto.matches = proto.matchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector || proto.oMatchesSelector || proto.webkitMatchesSelector; } /** * Finds the closest parent that matches a selector. * * @param {Element} element * @param {String} selector * @return {Function} */ function closest (element, selector) { while (element && element.nodeType !== DOCUMENT_NODE_TYPE) { if (element.matches(selector)) return element; element = element.parentNode; } } module.exports = closest; },{}],3:[function(require,module,exports){ var closest = require('./closest'); /** * Delegates event to a selector. * * @param {Element} element * @param {String} selector * @param {String} type * @param {Function} callback * @param {Boolean} useCapture * @return {Object} */ function delegate(element, selector, type, callback, useCapture) { var listenerFn = listener.apply(this, arguments); element.addEventListener(type, listenerFn, useCapture); return { destroy: function() { element.removeEventListener(type, listenerFn, useCapture); } } } /** * Finds closest match and invokes callback. * * @param {Element} element * @param {String} selector * @param {String} type * @param {Function} callback * @return {Function} */ function listener(element, selector, type, callback) { return function(e) { e.delegateTarget = closest(e.target, selector); if (e.delegateTarget) { callback.call(element, e); } } } module.exports = delegate; },{"./closest":2}],4:[function(require,module,exports){ 'use strict'; var range; // Create a range object for efficently rendering strings to elements. var NS_XHTML = 'http://www.w3.org/1999/xhtml'; var doc = typeof document === 'undefined' ? undefined : document; var testEl = doc ? doc.body || doc.createElement('div') : {}; // Fixes // (IE7+ support) <=IE7 does not support el.hasAttribute(name) var actualHasAttributeNS; if (testEl.hasAttributeNS) { actualHasAttributeNS = function(el, namespaceURI, name) { return el.hasAttributeNS(namespaceURI, name); }; } else if (testEl.hasAttribute) { actualHasAttributeNS = function(el, namespaceURI, name) { return el.hasAttribute(name); }; } else { actualHasAttributeNS = function(el, namespaceURI, name) { return el.getAttributeNode(namespaceURI, name) != null; }; } var hasAttributeNS = actualHasAttributeNS; function toElement(str) { if (!range && doc.createRange) { range = doc.createRange(); range.selectNode(doc.body); } var fragment; if (range && range.createContextualFragment) { fragment = range.createContextualFragment(str); } else { fragment = doc.createElement('body'); fragment.innerHTML = str; } return fragment.childNodes[0]; } /** * Returns true if two node's names are the same. * * NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same * nodeName and different namespace URIs. * * @param {Element} a * @param {Element} b The target element * @return {boolean} */ function compareNodeNames(fromEl, toEl) { var fromNodeName = fromEl.nodeName; var toNodeName = toEl.nodeName; if (fromNodeName === toNodeName) { return true; } if (toEl.actualize && fromNodeName.charCodeAt(0) < 91 && /* from tag name is upper case */ toNodeName.charCodeAt(0) > 90 /* target tag name is lower case */) { // If the target element is a virtual DOM node then we may need to normalize the tag name // before comparing. Normal HTML elements that are in the "http://www.w3.org/1999/xhtml" // are converted to upper case return fromNodeName === toNodeName.toUpperCase(); } else { return false; } } /** * Create an element, optionally with a known namespace URI. * * @param {string} name the element name, e.g. 'div' or 'svg' * @param {string} [namespaceURI] the element's namespace URI, i.e. the value of * its `xmlns` attribute or its inferred namespace. * * @return {Element} */ function createElementNS(name, namespaceURI) { return !namespaceURI || namespaceURI === NS_XHTML ? doc.createElement(name) : doc.createElementNS(namespaceURI, name); } /** * Copies the children of one DOM element to another DOM element */ function moveChildren(fromEl, toEl) { var curChild = fromEl.firstChild; while (curChild) { var nextChild = curChild.nextSibling; toEl.appendChild(curChild); curChild = nextChild; } return toEl; } function morphAttrs(fromNode, toNode) { var attrs = toNode.attributes; var i; var attr; var attrName; var attrNamespaceURI; var attrValue; var fromValue; for (i = attrs.length - 1; i >= 0; --i) { attr = attrs[i]; attrName = attr.name; attrNamespaceURI = attr.namespaceURI; attrValue = attr.value; if (attrNamespaceURI) { attrName = attr.localName || attrName; fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName); if (fromValue !== attrValue) { fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue); } } else { fromValue = fromNode.getAttribute(attrName); if (fromValue !== attrValue) { fromNode.setAttribute(attrName, attrValue); } } } // Remove any extra attributes found on the original DOM element that // weren't found on the target element. attrs = fromNode.attributes; for (i = attrs.length - 1; i >= 0; --i) { attr = attrs[i]; if (attr.specified !== false) { attrName = attr.name; attrNamespaceURI = attr.namespaceURI; if (attrNamespaceURI) { attrName = attr.localName || attrName; if (!hasAttributeNS(toNode, attrNamespaceURI, attrName)) { fromNode.removeAttributeNS(attrNamespaceURI, attrName); } } else { if (!hasAttributeNS(toNode, null, attrName)) { fromNode.removeAttribute(attrName); } } } } } function syncBooleanAttrProp(fromEl, toEl, name) { if (fromEl[name] !== toEl[name]) { fromEl[name] = toEl[name]; if (fromEl[name]) { fromEl.setAttribute(name, ''); } else { fromEl.removeAttribute(name, ''); } } } var specialElHandlers = { /** * Needed for IE. Apparently IE doesn't think that "selected" is an * attribute when reading over the attributes using selectEl.attributes */ OPTION: function(fromEl, toEl) { syncBooleanAttrProp(fromEl, toEl, 'selected'); }, /** * The "value" attribute is special for the element since it sets * the initial value. Changing the "value" attribute without changing the * "value" property will have no effect since it is only used to the set the * initial value. Similar for the "checked" attribute, and "disabled". */ INPUT: function(fromEl, toEl) { syncBooleanAttrProp(fromEl, toEl, 'checked'); syncBooleanAttrProp(fromEl, toEl, 'disabled'); if (fromEl.value !== toEl.value) { fromEl.value = toEl.value; } if (!hasAttributeNS(toEl, null, 'value')) { fromEl.removeAttribute('value'); } }, TEXTAREA: function(fromEl, toEl) { var newValue = toEl.value; if (fromEl.value !== newValue) { fromEl.value = newValue; } var firstChild = fromEl.firstChild; if (firstChild) { // Needed for IE. Apparently IE sets the placeholder as the // node value and vise versa. This ignores an empty update. var oldValue = firstChild.nodeValue; if (oldValue == newValue || (!newValue && oldValue == fromEl.placeholder)) { return; } firstChild.nodeValue = newValue; } }, SELECT: function(fromEl, toEl) { if (!hasAttributeNS(toEl, null, 'multiple')) { var selectedIndex = -1; var i = 0; var curChild = toEl.firstChild; while(curChild) { var nodeName = curChild.nodeName; if (nodeName && nodeName.toUpperCase() === 'OPTION') { if (hasAttributeNS(curChild, null, 'selected')) { selectedIndex = i; break; } i++; } curChild = curChild.nextSibling; } fromEl.selectedIndex = i; } } }; var ELEMENT_NODE = 1; var TEXT_NODE = 3; var COMMENT_NODE = 8; function noop() {} function defaultGetNodeKey(node) { return node.id; } function morphdomFactory(morphAttrs) { return function morphdom(fromNode, toNode, options) { if (!options) { options = {}; } if (typeof toNode === 'string') { if (fromNode.nodeName === '#document' || fromNode.nodeName === 'HTML') { var toNodeHtml = toNode; toNode = doc.createElement('html'); toNode.innerHTML = toNodeHtml; } else { toNode = toElement(toNode); } } var getNodeKey = options.getNodeKey || defaultGetNodeKey; var onBeforeNodeAdded = options.onBeforeNodeAdded || noop; var onNodeAdded = options.onNodeAdded || noop; var onBeforeElUpdated = options.onBeforeElUpdated || noop; var onElUpdated = options.onElUpdated || noop; var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop; var onNodeDiscarded = options.onNodeDiscarded || noop; var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop; var childrenOnly = options.childrenOnly === true; // This object is used as a lookup to quickly find all keyed elements in the original DOM tree. var fromNodesLookup = {}; var keyedRemovalList; function addKeyedRemoval(key) { if (keyedRemovalList) { keyedRemovalList.push(key); } else { keyedRemovalList = [key]; } } function walkDiscardedChildNodes(node, skipKeyedNodes) { if (node.nodeType === ELEMENT_NODE) { var curChild = node.firstChild; while (curChild) { var key = undefined; if (skipKeyedNodes && (key = getNodeKey(curChild))) { // If we are skipping keyed nodes then we add the key // to a list so that it can be handled at the very end. addKeyedRemoval(key); } else { // Only report the node as discarded if it is not keyed. We do this because // at the end we loop through all keyed elements that were unmatched // and then discard them in one final pass. onNodeDiscarded(curChild); if (curChild.firstChild) { walkDiscardedChildNodes(curChild, skipKeyedNodes); } } curChild = curChild.nextSibling; } } } /** * Removes a DOM node out of the original DOM * * @param {Node} node The node to remove * @param {Node} parentNode The nodes parent * @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded. * @return {undefined} */ function removeNode(node, parentNode, skipKeyedNodes) { if (onBeforeNodeDiscarded(node) === false) { return; } if (parentNode) { parentNode.removeChild(node); } onNodeDiscarded(node); walkDiscardedChildNodes(node, skipKeyedNodes); } // // TreeWalker implementation is no faster, but keeping this around in case this changes in the future // function indexTree(root) { // var treeWalker = document.createTreeWalker( // root, // NodeFilter.SHOW_ELEMENT); // // var el; // while((el = treeWalker.nextNode())) { // var key = getNodeKey(el); // if (key) { // fromNodesLookup[key] = el; // } // } // } // // NodeIterator implementation is no faster, but keeping this around in case this changes in the future // // function indexTree(node) { // var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT); // var el; // while((el = nodeIterator.nextNode())) { // var key = getNodeKey(el); // if (key) { // fromNodesLookup[key] = el; // } // } // } function indexTree(node) { if (node.nodeType === ELEMENT_NODE) { var curChild = node.firstChild; while (curChild) { var key = getNodeKey(curChild); if (key) { fromNodesLookup[key] = curChild; } // Walk recursively indexTree(curChild); curChild = curChild.nextSibling; } } } indexTree(fromNode); function handleNodeAdded(el) { onNodeAdded(el); var curChild = el.firstChild; while (curChild) { var nextSibling = curChild.nextSibling; var key = getNodeKey(curChild); if (key) { var unmatchedFromEl = fromNodesLookup[key]; if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) { curChild.parentNode.replaceChild(unmatchedFromEl, curChild); morphEl(unmatchedFromEl, curChild); } } handleNodeAdded(curChild); curChild = nextSibling; } } function morphEl(fromEl, toEl, childrenOnly) { var toElKey = getNodeKey(toEl); var curFromNodeKey; if (toElKey) { // If an element with an ID is being morphed then it is will be in the final // DOM so clear it out of the saved elements collection delete fromNodesLookup[toElKey]; } if (toNode.isSameNode && toNode.isSameNode(fromNode)) { return; } if (!childrenOnly) { if (onBeforeElUpdated(fromEl, toEl) === false) { return; } morphAttrs(fromEl, toEl); onElUpdated(fromEl); if (onBeforeElChildrenUpdated(fromEl, toEl) === false) { return; } } if (fromEl.nodeName !== 'TEXTAREA') { var curToNodeChild = toEl.firstChild; var curFromNodeChild = fromEl.firstChild; var curToNodeKey; var fromNextSibling; var toNextSibling; var matchingFromEl; outer: while (curToNodeChild) { toNextSibling = curToNodeChild.nextSibling; curToNodeKey = getNodeKey(curToNodeChild); while (curFromNodeChild) { fromNextSibling = curFromNodeChild.nextSibling; if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) { curToNodeChild = toNextSibling; curFromNodeChild = fromNextSibling; continue outer; } curFromNodeKey = getNodeKey(curFromNodeChild); var curFromNodeType = curFromNodeChild.nodeType; var isCompatible = undefined; if (curFromNodeType === curToNodeChild.nodeType) { if (curFromNodeType === ELEMENT_NODE) { // Both nodes being compared are Element nodes if (curToNodeKey) { // The target node has a key so we want to match it up with the correct element // in the original DOM tree if (curToNodeKey !== curFromNodeKey) { // The current element in the original DOM tree does not have a matching key so // let's check our lookup to see if there is a matching element in the original // DOM tree if ((matchingFromEl = fromNodesLookup[curToNodeKey])) { if (curFromNodeChild.nextSibling === matchingFromEl) { // Special case for single element removals. To avoid removing the original // DOM node out of the tree (since that can break CSS transitions, etc.), // we will instead discard the current node and wait until the next // iteration to properly match up the keyed target element with its matching // element in the original tree isCompatible = false; } else { // We found a matching keyed element somewhere in the original DOM tree. // Let's moving the original DOM node into the current position and morph // it. // NOTE: We use insertBefore instead of replaceChild because we want to go through // the `removeNode()` function for the node that is being discarded so that // all lifecycle hooks are correctly invoked fromEl.insertBefore(matchingFromEl, curFromNodeChild); fromNextSibling = curFromNodeChild.nextSibling; if (curFromNodeKey) { // Since the node is keyed it might be matched up later so we defer // the actual removal to later addKeyedRemoval(curFromNodeKey); } else { // NOTE: we skip nested keyed nodes from being removed since there is // still a chance they will be matched up later removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); } curFromNodeChild = matchingFromEl; } } else { // The nodes are not compatible since the "to" node has a key and there // is no matching keyed node in the source tree isCompatible = false; } } } else if (curFromNodeKey) { // The original has a key isCompatible = false; } isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild); if (isCompatible) { // We found compatible DOM elements so transform // the current "from" node to match the current // target DOM node. morphEl(curFromNodeChild, curToNodeChild); } } else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) { // Both nodes being compared are Text or Comment nodes isCompatible = true; // Simply update nodeValue on the original node to // change the text value curFromNodeChild.nodeValue = curToNodeChild.nodeValue; } } if (isCompatible) { // Advance both the "to" child and the "from" child since we found a match curToNodeChild = toNextSibling; curFromNodeChild = fromNextSibling; continue outer; } // No compatible match so remove the old node from the DOM and continue trying to find a // match in the original DOM. However, we only do this if the from node is not keyed // since it is possible that a keyed node might match up with a node somewhere else in the // target tree and we don't want to discard it just yet since it still might find a // home in the final DOM tree. After everything is done we will remove any keyed nodes // that didn't find a home if (curFromNodeKey) { // Since the node is keyed it might be matched up later so we defer // the actual removal to later addKeyedRemoval(curFromNodeKey); } else { // NOTE: we skip nested keyed nodes from being removed since there is // still a chance they will be matched up later removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); } curFromNodeChild = fromNextSibling; } // If we got this far then we did not find a candidate match for // our "to node" and we exhausted all of the children "from" // nodes. Therefore, we will just append the current "to" node // to the end if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) { fromEl.appendChild(matchingFromEl); morphEl(matchingFromEl, curToNodeChild); } else { var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild); if (onBeforeNodeAddedResult !== false) { if (onBeforeNodeAddedResult) { curToNodeChild = onBeforeNodeAddedResult; } if (curToNodeChild.actualize) { curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc); } fromEl.appendChild(curToNodeChild); handleNodeAdded(curToNodeChild); } } curToNodeChild = toNextSibling; curFromNodeChild = fromNextSibling; } // We have processed all of the "to nodes". If curFromNodeChild is // non-null then we still have some from nodes left over that need // to be removed while (curFromNodeChild) { fromNextSibling = curFromNodeChild.nextSibling; if ((curFromNodeKey = getNodeKey(curFromNodeChild))) { // Since the node is keyed it might be matched up later so we defer // the actual removal to later addKeyedRemoval(curFromNodeKey); } else { // NOTE: we skip nested keyed nodes from being removed since there is // still a chance they will be matched up later removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); } curFromNodeChild = fromNextSibling; } } var specialElHandler = specialElHandlers[fromEl.nodeName]; if (specialElHandler) { specialElHandler(fromEl, toEl); } } // END: morphEl(...) var morphedNode = fromNode; var morphedNodeType = morphedNode.nodeType; var toNodeType = toNode.nodeType; if (!childrenOnly) { // Handle the case where we are given two DOM nodes that are not // compatible (e.g.
--> or
--> TEXT) if (morphedNodeType === ELEMENT_NODE) { if (toNodeType === ELEMENT_NODE) { if (!compareNodeNames(fromNode, toNode)) { onNodeDiscarded(fromNode); morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI)); } } else { // Going from an element node to a text node morphedNode = toNode; } } else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { // Text or comment node if (toNodeType === morphedNodeType) { morphedNode.nodeValue = toNode.nodeValue; return morphedNode; } else { // Text node to something else morphedNode = toNode; } } } if (morphedNode === toNode) { // The "to node" was not compatible with the "from node" so we had to // toss out the "from node" and use the "to node" onNodeDiscarded(fromNode); } else { morphEl(morphedNode, toNode, childrenOnly); // We now need to loop over any keyed nodes that might need to be // removed. We only do the removal if we know that the keyed node // never found a match. When a keyed node is matched up we remove // it out of fromNodesLookup and we use fromNodesLookup to determine // if a keyed node has been matched up or not if (keyedRemovalList) { for (var i=0, len=keyedRemovalList.length; i
'); [].forEach.call(_this.elements, function (element) { _this.addNewItem(element); }); var currentItem = _this._getCurrentItemByHash(); if (currentItem) { util.triggerEvent(currentItem.element, 'click'); } _this.update(); _this._getEachImageSize().then(function () { _this._fireEvent('loadall'); }); setInterval(function () { _this._doAnim(); }, _this.data.forceInterval); if (!_this.data.isSmartPhone) { window.addEventListener('resize', function () { _this._resetTranslate(); _this._setPosByCurrentIndex(); _this._setSizeByScreen(); _this.update(); }); window.addEventListener('keydown', function (e) { var code = e.keyCode || e.which; if (_this.data.hide === true) { return; } if (code === 37) { _this.gotoSlide(_this.data.prev); } else if (code === 39) { _this.gotoSlide(_this.data.next); } else if (code === 27) { _this.hidePhoto(); } }); return _possibleConstructorReturn(_this); } window.addEventListener('orientationchange', function () { _this._resetTranslate(); _this._setPosByCurrentIndex(); _this._setHashByCurrentIndex(); _this._setSizeByScreen(); _this.update(); }); if (!_this.data.useOrientationApi) { return _possibleConstructorReturn(_this); } window.addEventListener('deviceorientation', function (e) { var orientation = window.orientation; if (!e || !e.gamma || _this.data.appearEffect) { return; } if (!_this.isBeingZoomed && !_this.photoSwipable && !_this.data.elastic && _this.data.scale) { if (orientation === 0) { _this._calcGravity(e.gamma, e.beta); } else if (orientation === 90) { _this._calcGravity(e.beta, e.gamma); } else if (orientation === -90) { _this._calcGravity(-e.beta, -e.gamma); } else if (orientation === 180) { _this._calcGravity(-e.gamma, -e.beta); } } }); return _this; } _createClass(smartPhoto, [{ key: 'on', value: function on(event, fn) { var _this2 = this; var photo = this._getElementByClass(this.data.classNames.smartPhoto); photo.addEventListener(event, function (e) { fn.call(_this2, e); }); } }, { key: 'increment', value: function increment(item) { return item + 1; } }, { key: 'virtualPos', value: function virtualPos(pos) { pos = parseInt(pos, 10); var item = this._getSelectedItem(); return pos / item.scale / this.data.scaleSize; } }, { key: 'groupItems', value: function groupItems() { return this.data.group[this.data.currentGroup]; } }, { key: '_getEachImageSize', value: function _getEachImageSize() { var arr = []; var group = this.data.group; var loadItems = function loadItems(item) { var promise = new Promise(function (resolve, reject) { var img = new Image(); img.onload = function () { item.width = img.width; item.height = img.height; item.loaded = true; resolve(); }; img.onerror = function () { reject(); }; img.src = item.src; }); arr.push(promise); }; Object.keys(group).forEach(function (key) { group[key].forEach(loadItems); }); return Promise.all(arr); } }, { key: '_resetTranslate', value: function _resetTranslate() { var _this3 = this; var items = this.groupItems(); items.forEach(function (item, index) { item.translateX = _this3._getWindowWidth() * index; }); } }, { key: 'addNewItem', value: function addNewItem(element) { var _this4 = this; var groupId = element.getAttribute('data-group') || 'nogroup'; var group = this.data.group; if (groupId === 'nogroup') { element.setAttribute('data-group', 'nogroup'); } if (!group[groupId]) { group[groupId] = []; } var index = group[groupId].length; var item = { src: element.getAttribute('href'), caption: element.getAttribute('data-caption'), groupId: groupId, translateX: this._getWindowWidth() * index, index: index, translateY: 0, width: 50, height: 50, id: element.getAttribute('data-id') || index, loaded: false, processed: false, element: element }; group[groupId].push(item); this.data.currentGroup = groupId; var id = element.getAttribute('data-id'); if (!id) { element.setAttribute('data-id', index); } element.setAttribute('data-index', index); element.addEventListener('click', function (event) { event.preventDefault(); _this4.data.currentGroup = element.getAttribute('data-group'); _this4.data.currentIndex = parseInt(element.getAttribute('data-index'), 10); _this4._setHashByCurrentIndex(); var currentItem = _this4._getSelectedItem(); if (currentItem.loaded) { _this4._initPhoto(); _this4.addAppearEffect(element); _this4.clicked = true; _this4.update(); _this4._fireEvent('open'); } else { _this4._loadItem(currentItem).then(function () { _this4._initPhoto(); _this4.addAppearEffect(element); _this4.clicked = true; _this4.update(); _this4._fireEvent('open'); }); } }); } }, { key: '_initPhoto', value: function _initPhoto() { this.data.total = this.groupItems().length; this.data.hide = false; this.data.photoPosX = 0; this.data.photoPosY = 0; this._setPosByCurrentIndex(); this._setSizeByScreen(); this.setArrow(); if (this.data.resizeStyle === 'fill' && this.data.isSmartPhone) { this.data.scale = true; this.data.hideUi = true; this.data.scaleSize = this._getScaleBoarder(); } } }, { key: 'onUpdated', value: function onUpdated() { var _this5 = this; if (this.data.appearEffect && this.data.appearEffect.once) { this.data.appearEffect.once = false; this.execEffect().then(function () { _this5.data.appearEffect = null; _this5.data.appear = true; _this5.update(); }); } if (this.clicked) { this.clicked = false; var classNames = this.data.classNames; var caption = this._getElementByClass(classNames.smartPhotoCaption); caption.focus(); } } }, { key: 'execEffect', value: function execEffect() { var _this6 = this; return new Promise(function (resolve) { var appearEffect = _this6.data.appearEffect; var classNames = _this6.data.classNames; var effect = _this6._getElementByClass(classNames.smartPhotoImgClone); var handler = function handler() { effect.removeEventListener('transitionend', handler, true); resolve(); }; effect.addEventListener('transitionend', handler, true); setTimeout(function () { effect.style.transform = 'translate(' + appearEffect.afterX + 'px, ' + appearEffect.afterY + 'px) scale(' + appearEffect.scale + ')'; }, 10); }); } }, { key: 'addAppearEffect', value: function addAppearEffect(element) { var img = element.querySelector('img'); var pos = util.getViewPos(img); var appear = {}; var scale = 1; appear.width = img.offsetWidth; appear.height = img.offsetHeight; appear.top = pos.top; appear.left = pos.left; appear.once = true; appear.img = img.getAttribute('src'); var windowX = this._getWindowWidth(); var windowY = this._getWindowHeight(); var screenY = windowY - this.data.headerHeight - this.data.footerHeight; if (this.data.resizeStyle === 'fill' && this.data.isSmartPhone) { if (img.offsetWidth > img.offsetHeight) { scale = windowY / img.offsetHeight; } else { scale = windowX / img.offsetWidth; } } else { scale = screenY / img.offsetHeight; if (scale * img.offsetWidth > windowX) { scale = windowX / img.offsetWidth; } } var x = (scale - 1) / 2 * img.offsetWidth + (windowX - img.offsetWidth * scale) / 2; var y = (scale - 1) / 2 * img.offsetHeight + (windowY - img.offsetHeight * scale) / 2; appear.afterX = x; appear.afterY = y; appear.scale = scale; this.data.appearEffect = appear; } }, { key: 'hidePhoto', value: function hidePhoto() { var _this7 = this; this.data.hide = true; this.data.appear = false; this.data.appearEffect = null; this.data.hideUi = false; this.data.scale = false; this.data.scaleSize = 1; var scrollX = window.scrollX; var scrollY = window.scrollY; if (location.hash) { this._setHash(''); } window.scroll(scrollX, scrollY); this._doHideEffect().then(function () { _this7.update(); _this7._fireEvent('close'); }); } }, { key: '_doHideEffect', value: function _doHideEffect() { var _this8 = this; return new Promise(function (resolve) { var classNames = _this8.data.classNames; var photo = _this8._getElementByClass(classNames.smartPhoto); var img = _this8._getElementByQuery('.current .' + classNames.smartPhotoImg); var height = _this8._getWindowHeight(); var handler = function handler() { photo.removeEventListener('transitionend', handler, true); resolve(); }; photo.style.opacity = 0; img.style.transform = 'translateY(' + height + 'px)'; photo.addEventListener('transitionend', handler, true); }); } }, { key: '_getElementByClass', value: function _getElementByClass(className) { return document.querySelector('[data-id="' + this.id + '"] .' + className); } }, { key: '_getElementByQuery', value: function _getElementByQuery(query) { return document.querySelector('[data-id="' + this.id + '"] ' + query); } }, { key: '_getTouchPos', value: function _getTouchPos() { var x = 0; var y = 0; var e = typeof event === 'undefined' ? this.e : event; if (this._isTouched(e)) { x = e.touches[0].pageX; y = e.touches[0].pageY; } else if (e.pageX) { x = e.pageX; y = e.pageY; } return { x: x, y: y }; } }, { key: '_getGesturePos', value: function _getGesturePos(e) { var touches = e.touches; return [{ x: touches[0].pageX, y: touches[0].pageY }, { x: touches[1].pageX, y: touches[1].pageY }]; } }, { key: '_setPosByCurrentIndex', value: function _setPosByCurrentIndex() { var _this9 = this; var items = this.groupItems(); var moveX = -1 * items[this.data.currentIndex].translateX; this.pos.x = moveX; setTimeout(function () { _this9.data.translateX = moveX; _this9.data.translateY = 0; _this9._listUpdate(); }, 1); } }, { key: '_setHashByCurrentIndex', value: function _setHashByCurrentIndex() { var scrollX = window.scrollX; var scrollY = window.scrollY; var items = this.groupItems(); var id = items[this.data.currentIndex].id; var group = this.data.currentGroup; var hash = 'group=' + group + '&photo=' + id; this._setHash(hash); window.scroll(scrollX, scrollY); } }, { key: '_setHash', value: function _setHash(hash) { if (!(window.history && window.history.pushState)) { return; } if (hash) { window.history.replaceState(null, null, location.pathname + '#' + hash); } else { window.history.replaceState(null, null, '' + location.pathname); } } }, { key: '_getCurrentItemByHash', value: function _getCurrentItemByHash() { var group = this.data.group; var hash = location.hash.substr(1); var hashObj = util.parseQuery(hash); var currentItem = null; var getCurrentItem = function getCurrentItem(item) { if (hashObj.group === item.groupId && hashObj.photo === item.id) { currentItem = item; } }; Object.keys(group).forEach(function (key) { group[key].forEach(getCurrentItem); }); return currentItem; } }, { key: '_loadItem', value: function _loadItem(item) { return new Promise(function (resolve) { var img = new Image(); img.onload = function () { item.width = img.width; item.height = img.height; item.loaded = true; resolve(); }; img.onerror = function () { resolve(); }; img.src = item.src; }); } }, { key: '_setSizeByScreen', value: function _setSizeByScreen() { var windowX = this._getWindowWidth(); var windowY = this._getWindowHeight(); var headerHeight = this.data.headerHeight; var footerHeight = this.data.footerHeight; var screenY = windowY - (headerHeight + footerHeight); var items = this.groupItems(); items.forEach(function (item) { if (!item.loaded) { return; } item.processed = true; item.scale = screenY / item.height; item.x = (item.scale - 1) / 2 * item.width + (windowX - item.width * item.scale) / 2; item.y = (item.scale - 1) / 2 * item.height + (windowY - item.height * item.scale) / 2; if (item.width * item.scale > windowX) { item.scale = windowX / item.width; item.x = (item.scale - 1) / 2 * item.width; } }); } }, { key: '_slideList', value: function _slideList() { var _this10 = this; this.data.scaleSize = 1; this.isBeingZoomed = false; this.data.hideUi = false; this.data.scale = false; this.data.photoPosX = 0; this.data.photoPosY = 0; this.data.onMoveClass = true; this._setPosByCurrentIndex(); this._setHashByCurrentIndex(); this._setSizeByScreen(); setTimeout(function () { _this10.data.onMoveClass = false; _this10.setArrow(); _this10.update(); if (_this10.data.oldIndex !== _this10.data.currentIndex) { _this10._fireEvent('change'); } _this10.data.oldIndex = _this10.data.currentIndex; }, 200); } }, { key: 'gotoSlide', value: function gotoSlide(index) { if (this.e && this.e.preventDefault) { this.e.preventDefault(); } this.data.currentIndex = parseInt(index, 10); if (!this.data.currentIndex) { this.data.currentIndex = 0; } this._slideList(); } }, { key: 'setArrow', value: function setArrow() { var items = this.groupItems(); var length = items.length; var next = this.data.currentIndex + 1; var prev = this.data.currentIndex - 1; this.data.showNextArrow = false; this.data.showPrevArrow = false; if (next !== length) { this.data.next = next; this.data.showNextArrow = true; } if (prev !== -1) { this.data.prev = prev; this.data.showPrevArrow = true; } } }, { key: 'beforeDrag', value: function beforeDrag() { if (this._isGestured(this.e)) { this.beforeGesture(); return; } this.isBeingZoomed = false; if (this.data.scale) { this.beforePhotoDrag(); return; } var pos = this._getTouchPos(); this.isSwipable = true; this.dragStart = true; this.firstPos = pos; this.oldPos = pos; } }, { key: 'afterDrag', value: function afterDrag() { var items = this.groupItems(); var date = new Date(); var tapSecond = date.getTime(); var offset = this.tapSecond - tapSecond; var swipeWidth = 0; var swipeHeight = 0; this.isSwipable = false; this.onListMove = false; if (this.oldPos) { swipeWidth = this.oldPos.x - this.firstPos.x; swipeHeight = this.oldPos.y - this.firstPos.y; } if (this.isBeingZoomed) { this.afterGesture(); return; } if (this.data.scale) { this.afterPhotoDrag(); return; } else if (!util.isSmartPhone() && swipeWidth === 0 && swipeHeight === 0) { this.zoomPhoto(); return; } if (Math.abs(offset) <= 500 && swipeWidth === 0 && swipeHeight === 0) { this.e.preventDefault(); this.zoomPhoto(); return; } this.tapSecond = tapSecond; this._fireEvent('swipeend'); if (this.moveDir === 'horizontal') { if (swipeWidth >= this.data.swipeOffset && this.data.currentIndex !== 0) { this.data.currentIndex -= 1; } else if (swipeWidth <= -this.data.swipeOffset && this.data.currentIndex !== items.length - 1) { this.data.currentIndex += 1; } this._slideList(); } if (this.moveDir === 'vertical') { if (swipeHeight >= this.data.swipeOffset) { this.hidePhoto(); } else { this.data.translateY = 0; this._slideList(); } } } }, { key: 'onDrag', value: function onDrag() { this.e.preventDefault(); if (this._isGestured(this.e) && this.onListMove === false) { this.onGesture(); return; } if (this.isBeingZoomed) { return; } if (this.data.scale) { this.onPhotoDrag(); return; } if (!this.isSwipable) { return; } var pos = this._getTouchPos(); var x = pos.x - this.oldPos.x; var y = pos.y - this.firstPos.y; if (this.dragStart) { this._fireEvent('swipestart'); this.dragStart = false; if (Math.abs(x) > Math.abs(y)) { this.moveDir = 'horizontal'; } else { this.moveDir = 'vertical'; } } if (this.moveDir === 'horizontal') { this.pos.x += x; this.data.translateX = this.pos.x; } else { this.data.translateY = y; } this.onListMove = true; this.oldPos = pos; this._listUpdate(); } }, { key: 'zoomPhoto', value: function zoomPhoto() { var _this11 = this; this.data.hideUi = true; this.data.scaleSize = this._getScaleBoarder(); this.data.photoPosX = 0; this.data.photoPosY = 0; this._photoUpdate(); setTimeout(function () { _this11.data.scale = true; _this11._photoUpdate(); _this11._fireEvent('zoomin'); }, 300); } }, { key: 'zoomOutPhoto', value: function zoomOutPhoto() { this.data.scaleSize = 1; this.isBeingZoomed = false; this.data.hideUi = false; this.data.scale = false; this.data.photoPosX = 0; this.data.photoPosY = 0; this._photoUpdate(); this._fireEvent('zoomout'); } }, { key: 'beforePhotoDrag', value: function beforePhotoDrag() { var pos = this._getTouchPos(); this.photoSwipable = true; if (!this.data.photoPosX) { this.data.photoPosX = 0; } if (!this.data.photoPosY) { this.data.photoPosY = 0; } this.oldPhotoPos = pos; this.firstPhotoPos = pos; } }, { key: 'onPhotoDrag', value: function onPhotoDrag() { if (!this.photoSwipable) { return; } this.e.preventDefault(); var pos = this._getTouchPos(); var x = pos.x - this.oldPhotoPos.x; var y = pos.y - this.oldPhotoPos.y; var moveX = this._round(this.data.scaleSize * x, 6); var moveY = this._round(this.data.scaleSize * y, 6); if (typeof moveX === 'number') { this.data.photoPosX += moveX; this.photoVX = moveX; } if (typeof moveY === 'number') { this.data.photoPosY += moveY; this.photoVY = moveY; } this.oldPhotoPos = pos; this._photoUpdate(); } }, { key: 'afterPhotoDrag', value: function afterPhotoDrag() { if (this.oldPhotoPos.x === this.firstPhotoPos.x && this.photoSwipable) { this.photoSwipable = false; this.zoomOutPhoto(); } else { this.photoSwipable = false; var item = this._getSelectedItem(); var bound = this._makeBound(item); var offset = this.data.swipeOffset * this.data.scaleSize; var flagX = 0; var flagY = 0; if (this.data.photoPosX > bound.maxX) { flagX = -1; } else if (this.data.photoPosX < bound.minX) { flagX = 1; } if (this.data.photoPosY > bound.maxY) { flagY = -1; } else if (this.data.photoPosY < bound.minY) { flagY = 1; } if (this.data.photoPosX - bound.maxX > offset && this.data.currentIndex !== 0) { this.gotoSlide(this.data.prev); return; } if (bound.minX - this.data.photoPosX > offset && this.data.currentIndex + 1 !== this.data.total) { this.gotoSlide(this.data.next); return; } // todo // if(this.data.photoPosY - bound.maxY > offset) { // this.hidePhoto(); // return; // } if (flagX === 0 && flagY === 0) { this.vx = this.photoVX / 5; this.vy = this.photoVY / 5; } else { this._registerElasticForce(flagX, flagY); } } } }, { key: 'beforeGesture', value: function beforeGesture() { this._fireEvent('gesturestart'); var pos = this._getGesturePos(this.e); var distance = this._getDistance(pos[0], pos[1]); this.isBeingZoomed = true; this.oldDistance = distance; this.data.scale = true; this.e.preventDefault(); } }, { key: 'onGesture', value: function onGesture() { var pos = this._getGesturePos(this.e); var distance = this._getDistance(pos[0], pos[1]); var size = (distance - this.oldDistance) / 100; var oldScaleSize = this.data.scaleSize; var posX = this.data.photoPosX; var posY = this.data.photoPosY; this.isBeingZoomed = true; this.data.scaleSize += this._round(size, 6); if (this.data.scaleSize < 0.2) { this.data.scaleSize = 0.2; } // todo if (this.data.scaleSize < oldScaleSize) { this.data.photoPosX = (1 + this.data.scaleSize - oldScaleSize) * posX; this.data.photoPosY = (1 + this.data.scaleSize - oldScaleSize) * posY; } if (this.data.scaleSize < 1 || this.data.scaleSize > this._getScaleBoarder()) { this.data.hideUi = true; } else { this.data.hideUi = false; } this.oldDistance = distance; this.e.preventDefault(); this._photoUpdate(); } }, { key: 'afterGesture', value: function afterGesture() { if (this.data.scaleSize > this._getScaleBoarder()) { return; } this.data.photoPosX = 0; this.data.photoPosY = 0; this.data.scale = false; this.data.scaleSize = 1; this.data.hideUi = false; this._fireEvent('gestureend'); this._photoUpdate(); } }, { key: '_getForceAndTheta', value: function _getForceAndTheta(vx, vy) { return { force: Math.sqrt(vx * vx + vy * vy), theta: Math.atan2(vy, vx) }; } }, { key: '_getScaleBoarder', value: function _getScaleBoarder() { var item = this._getSelectedItem(); var windowWidth = this._getWindowWidth(); var windowHeight = this._getWindowHeight(); if (!util.isSmartPhone()) { return 1 / item.scale; } if (item.width > item.height) { return windowHeight / (item.height * item.scale); } return windowWidth / (item.width * item.scale); } }, { key: '_makeBound', value: function _makeBound(item) { var width = item.width * item.scale * this.data.scaleSize; var height = item.height * item.scale * this.data.scaleSize; var minX = void 0; var minY = void 0; var maxX = void 0; var maxY = void 0; var windowWidth = this._getWindowWidth(); var windowHeight = this._getWindowHeight(); if (windowWidth > width) { maxX = (windowWidth - width) / 2; minX = -1 * maxX; } else { maxX = (width - windowWidth) / 2; minX = -1 * maxX; } if (windowHeight > height) { maxY = (windowHeight - height) / 2; minY = -1 * maxY; } else { maxY = (height - windowHeight) / 2; minY = -1 * maxY; } return { minX: this._round(minX, 6) * this.data.scaleSize, minY: this._round(minY, 6) * this.data.scaleSize, maxX: this._round(maxX, 6) * this.data.scaleSize, maxY: this._round(maxY, 6) * this.data.scaleSize }; } }, { key: '_registerElasticForce', value: function _registerElasticForce(x, y) { var _this12 = this; var item = this._getSelectedItem(); var bound = this._makeBound(item); this.data.elastic = true; if (x === 1) { this.data.photoPosX = bound.minX; } else if (x === -1) { this.data.photoPosX = bound.maxX; } if (y === 1) { this.data.photoPosY = bound.minY; } else if (y === -1) { this.data.photoPosY = bound.maxY; } this._photoUpdate(); setTimeout(function () { _this12.data.elastic = false; _this12._photoUpdate(); }, 300); } }, { key: '_getSelectedItem', value: function _getSelectedItem() { var data = this.data; var index = data.currentIndex; return data.group[data.currentGroup][index]; } }, { key: '_getUniqId', value: function _getUniqId() { return (Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase(); } }, { key: '_getDistance', value: function _getDistance(point1, point2) { var x = point1.x - point2.x; var y = point1.y - point2.y; return Math.sqrt(x * x + y * y); } }, { key: '_round', value: function _round(val, precision) { var digit = Math.pow(10, precision); val *= digit; val = Math.round(val); val /= digit; return val; } }, { key: '_isTouched', value: function _isTouched(e) { if (e && e.touches) { return true; } return false; } }, { key: '_isGestured', value: function _isGestured(e) { if (e && e.touches && e.touches.length > 1) { return true; } return false; } }, { key: '_isSmartPhone', value: function _isSmartPhone() { var agent = navigator.userAgent; if (agent.indexOf('iPhone') > 0 || agent.indexOf('iPad') > 0 || agent.indexOf('ipod') > 0 || agent.indexOf('Android') > 0) { return true; } return false; } }, { key: '_calcGravity', value: function _calcGravity(gamma, beta) { if (gamma > 5 || gamma < -5) { this.vx += gamma * 0.05; } if (this.data.verticalGravity === false) { return; } if (beta > 5 || beta < -5) { this.vy += beta * 0.05; } } }, { key: '_photoUpdate', value: function _photoUpdate() { var classNames = this.data.classNames; var current = this._getElementByQuery('.current'); var img = current.querySelector('.' + classNames.smartPhotoImg); var nav = this._getElementByQuery('.' + classNames.smartPhotoNav); var arrows = this._getElementByQuery('.' + classNames.smartPhotoArrows); var photoPosX = this.virtualPos(this.data.photoPosX); var photoPosY = this.virtualPos(this.data.photoPosY); var scaleSize = this.data.scaleSize; var transform = 'translate(' + photoPosX + 'px,' + photoPosY + 'px) scale(' + scaleSize + ')'; img.style.transform = transform; if (this.data.scale) { util.addClass(img, classNames.smartPhotoImgOnMove); } else { util.removeClass(img, classNames.smartPhotoImgOnMove); } if (this.data.elastic) { util.addClass(img, classNames.smartPhotoImgElasticMove); } else { util.removeClass(img, classNames.smartPhotoImgElasticMove); } if (this.data.hideUi) { if (nav) { nav.setAttribute('aria-hidden', 'true'); } if (arrows) { arrows.setAttribute('aria-hidden', 'true'); } } else { if (nav) { nav.setAttribute('aria-hidden', 'false'); } if (arrows) { arrows.setAttribute('aria-hidden', 'false'); } } } }, { key: '_getWindowWidth', value: function _getWindowWidth() { return document.documentElement.clientWidth; } }, { key: '_getWindowHeight', value: function _getWindowHeight() { return window.innerHeight; } }, { key: '_listUpdate', value: function _listUpdate() { var classNames = this.data.classNames; var list = this._getElementByQuery('.' + classNames.smartPhotoList); var transform = 'translate(' + this.data.translateX + 'px,' + this.data.translateY + 'px)'; list.style.transform = transform; // $list if (this.data.onMoveClass) { util.addClass(list, classNames.smartPhotoListOnMove); } else { util.removeClass(list, classNames.smartPhotoListOnMove); } } }, { key: '_fireEvent', value: function _fireEvent(eventName) { var photo = this._getElementByClass(this.data.classNames.smartPhoto); util.triggerEvent(photo, eventName); } }, { key: '_doAnim', value: function _doAnim() { if (this.isBeingZoomed || this.isSwipable || this.photoSwipable || this.data.elastic || !this.data.scale) { return; } this.data.photoPosX += this.vx; this.data.photoPosY += this.vy; var item = this._getSelectedItem(); var bound = this._makeBound(item); if (this.data.photoPosX < bound.minX) { this.data.photoPosX = bound.minX; this.vx *= -0.2; } else if (this.data.photoPosX > bound.maxX) { this.data.photoPosX = bound.maxX; this.vx *= -0.2; } if (this.data.photoPosY < bound.minY) { this.data.photoPosY = bound.minY; this.vy *= -0.2; } else if (this.data.photoPosY > bound.maxY) { this.data.photoPosY = bound.maxY; this.vy *= -0.2; } var power = this._getForceAndTheta(this.vx, this.vy); var force = power.force; var theta = power.theta; force -= this.data.registance; if (Math.abs(force) < 0.5) { return; } this.vx = Math.cos(theta) * force; this.vy = Math.sin(theta) * force; this._photoUpdate(); } }]); return smartPhoto; }(_aTemplate3.default); module.exports = smartPhoto; },{"../lib/util":7,"a-template":1}],6:[function(require,module,exports){ 'use strict'; module.exports = require('./core/'); },{"./core/":5}],7:[function(require,module,exports){ 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; module.exports.isSmartPhone = function () { var agent = navigator.userAgent; if (agent.indexOf('iPhone') > 0 || agent.indexOf('iPad') > 0 || agent.indexOf('ipod') > 0 || agent.indexOf('Android') > 0) { return true; } else { return false; } }; function deepExtend(out) { out = out || {}; for (var i = 1; i < arguments.length; i++) { var obj = arguments[i]; if (!obj) { continue; } for (var key in obj) { if (obj.hasOwnProperty(key)) { if (_typeof(obj[key]) === 'object') out[key] = deepExtend(out[key], obj[key]);else out[key] = obj[key]; } } } return out; }; module.exports.extend = deepExtend; module.exports.triggerEvent = function (el, eventName, options) { var event = void 0; if (window.CustomEvent) { event = new CustomEvent(eventName, { cancelable: true }); } else { event = document.createEvent('CustomEvent'); event.initCustomEvent(eventName, false, false, options); } el.dispatchEvent(event); }; module.exports.parseQuery = function (query) { var s = query.split('&'), data = {}, i = 0, iz = s.length, param, key, value; for (; i < iz; i++) { param = s[i].split('='); if (param[0] !== void 0) { key = param[0]; value = param[1] !== void 0 ? param.slice(1).join('=') : key; data[key] = decodeURIComponent(value); } } return data; }; module.exports.getViewPos = function (element) { return { left: element.getBoundingClientRect().left, top: element.getBoundingClientRect().top }; }; module.exports.removeElement = function (element) { if (element && element.parentNode) { element.parentNode.removeChild(element); } }; module.exports.append = function (element, string) { var parser = new DOMParser(); var doc = parser.parseFromString(string, 'text/html'); element.appendChild(doc.querySelector('body').childNodes[0]); }; module.exports.addClass = function (element, className) { if (element.classList) { element.classList.add(className); } else { element.className += ' ' + className; } }; module.exports.removeClass = function (element, className) { if (element.classList) { element.classList.remove(className); } else { element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); } }; },{}]},{},[6])(6) });