diff --git a/.gitignore b/.gitignore
index fc86718..5891b27 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@ report
.DS_Store
node_modules
Ply.js
+Ply.es6
Ply.ui.js
diff --git a/Gruntfile.js b/Gruntfile.js
index 581c31f..2acee23 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -6,19 +6,20 @@ module.exports = function (grunt){
es6transpiler: {
core: {
- src: 'src/Ply.es6',
+ src: 'Ply.es6',
dest: 'Ply.js'
- },
- ui: {
- src: 'src/Ply.ui.es6',
- dest: 'Ply.ui.js'
}
},
+ export: {
+ src: "src/Ply.es6",
+ dst: "Ply.es6"
+ },
+
watch: {
scripts: {
files: 'src/*.es6',
- tasks: ['es6transpiler'],
+ tasks: ['es'],
options: { interrupt: true }
}
},
@@ -46,20 +47,52 @@ module.exports = function (grunt){
},
dist: {
files: {
- '<%= pkg.exportName %>.min.js': ['Ply.js', 'Ply.ui.js']
+ '<%= pkg.exportName %>.min.js': ['Ply.js']
}
}
}
});
+
+ grunt.registerTask('export', 'Export es6 to js', function () {
+ function file(rel, name) {
+ return rel.split('/').slice(0, -1).concat(name).join('/') + '.es6';
+ }
+
+ function parse(src, pad) {
+ grunt.log.writeln((pad || '') + 'Parse file:', src);
+
+ return grunt.file.read(src)
+ .replace(/module\.exports\s*=\s*([\s\S]+);/, '$1')
+ .replace(/require\('(.*?)'\);?/g, function (_, name) {
+ return parse(file(src, name), ' ');
+ })
+ .replace(/\/+\s+&import\s+"(.*?)".*?\n/g, function (_, name) {
+ return parse(file(src, name), ' ');
+ })
+ .trim()
+ ;
+ }
+
+ var config = grunt.config(this.name);
+ var content = parse(config.src).replace(/;;;[^\n]+/g, '');
+
+ grunt.log.writeln(new Array(50).join('-'));
+ grunt.log.oklns('Write file:', config.dst);
+
+ grunt.file.write(config.dst, content);
+ });
+
+
+
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-qunit-istanbul');
grunt.loadNpmTasks('grunt-es6-transpiler');
grunt.loadNpmTasks('grunt-contrib-uglify');
- grunt.registerTask('es', ['es6transpiler']);
+ grunt.registerTask('es', ['export', 'es6transpiler']);
grunt.registerTask('build', ['es', 'qunit']);
grunt.registerTask('min', ['uglify']);
grunt.registerTask('default', ['build', 'min']);
diff --git a/Ply.min.js b/Ply.min.js
index 6bc68fa..b190bcb 100644
--- a/Ply.min.js
+++ b/Ply.min.js
@@ -1,2 +1,464 @@
/*! Ply 0.3.0 - MIT | git://github.com/rubaxa/Ply.git */
-!function(a){window.Ply=a(window)}(function(a,b){"use strict";function c(a){return"function"==typeof a}function d(a){if(G)return new G(a);var b=F.Deferred();return a(b.resolve,b.reject),b}function e(a){return G?G.all(a):F.when.apply(F,a)}function f(a){return d(function(b){return b(a)})}function g(a){return a&&a.then?a:f(a)}function h(a,b){if(a)for(var c in a)a.hasOwnProperty(c)&&b(a[c],c,a)}function i(a){var b={};return h(a,function(a,d){b[d]=c(a)?a:a instanceof Object?i(a):a}),b}function j(a){for(var b=Array.prototype.slice,c=b.call(arguments,1),d=0,e=c.length;e>d;d++)h(c[d],function(b,c){a[c]=b});return a}function k(a,b){try{return(b||D).querySelector(a)}catch(c){return F(a,b)[0]}}function l(a,b){return a.getElementsByTagName(b)}function m(a,b){try{a&&b&&a.appendChild(b)}catch(c){}}function n(a){a&&a.parentNode&&a.parentNode.removeChild(a)}function o(a,b,c){var d=c.handle=c.handle||function(b){b.target||(b.target=b.srcElement||D),3===b.target.nodeType&&(b.target=b.target.parentNode),b.preventDefault||(b.preventDefault=function(){b.returnValue=!1}),b.stopPropagation||(b.stopPropagation=function(){b.cancelBubble=!0}),c.call(a,b)};a.addEventListener?a.addEventListener(b,d,!1):a.attachEvent("on"+b,d)}function p(a,b,c){var d=c.handle;d&&(a.removeEventListener?a.removeEventListener(b,d,!1):a.detachEvent("on"+b,d))}function q(a,b,c){if(a&&a.style&&b)if(b instanceof Object)for(var d in b)q(a,d,b[d]);else{if(void 0===c)return D.defaultView&&D.defaultView.getComputedStyle?c=D.defaultView.getComputedStyle(a,""):a.currentStyle&&(c=a.currentStyle),void 0===b?c:c[b];K[b]?K[b](a.style,c):a.style[I[b]||b]=c}}function r(a){if(null==a&&(a="div"),a.appendChild)return a;if(a.skip)return D.createDocumentFragment();"string"==typeof a&&(a={tag:a});var b,c=a.children,d=H.exec(a.tag||"");return delete a.children,a.tag=d[1]||"div",a.id=a.id||(d[2]||"").substr(1),d=(d[3]||"").split("."),d[0]=a.className||"",a.className=d.join(" "),b=D.createElement(a.tag),delete a.tag,h(a,function(c,d){if(c)if("css"===d)q(b,a.css);else if("text"===d)null!=c&&m(b,D.createTextNode(c));else if("html"===d)null!=c&&(b.innerHTML=c);else if("ply"===d)b.setAttribute(O,c);else if(d in b)try{b[d]=c}catch(e){b.setAttribute(d,c)}else/^data-/.test(d)&&b.setAttribute(d,c)}),c&&c.appendChild?m(b,c):h(c,function(a,c){a&&("string"==typeof a?a={text:a}:"object"!=typeof a&&(a={}),"string"==typeof c&&(a.tag=a.tag||c),m(b,r(a)))}),b}function s(a){for(var b,c,d=l(a,"input"),e=0,f=d.length;f>e;e++)if(b=d[e],"submit"===b.type)!c&&(c=b);else if(!/hidden|check|radio/.test(b.type)&&""==b.value){c=b;break}c||(c=l(a,"button")[0]);try{c.focus()}catch(g){}}function t(a){return u(!0),d(function(b){for(var c,d=l(a,"img"),e=d.length,f=e,g=function(){if(--f<=0){for(e=d.length;e--;)c=d[e],p(c,"load",g),p(c,"error",g);u(!1),b()}};e--;)c=d[e],c.complete?f--:(o(c,"load",g),o(c,"error",g));!f&&g()})}function u(a){var b=u.get();clearTimeout(u.pid),u.pid=a?E(function(){m(D.body,b)},100):E(function(){n(b)},100)}function v(a,b){return r({css:{padding:"20px 20px 40px",display:"inline-block",position:"relative",textAlign:"left",whiteSpace:"normal",verticalAlign:"middle",transform:"translate3d(0, 0, 0)"},children:b.baseHtml?[{ply:":layer",tag:".ply-layer",className:b.mod,css:j({overflow:"hidden",position:"relative",backfaceVisibility:"hidden"},b.layer),children:[b.flags.closeBtn&&{ply:":close",tag:".ply-x",text:z.lang.cross},{tag:".ply-inside",children:a}]}]:a})}function w(a){return r({ply:":overlay",tag:".ply-overlay",css:{top:0,left:0,right:0,bottom:0,position:"fixed"},children:[{tag:"div",css:j({width:"100%",height:"100%"},a)}]})}function x(a,b,c){a.wrapEl=r({tag:"form",css:{whiteSpace:"nowrap",zIndex:b.zIndex}}),c||(a.overlayEl=w(b.overlay),a.overlayBoxEl=a.overlayEl.firstChild,m(a.wrapEl,a.overlayEl));var d=r();q(d,{height:"100%",display:"inline-block",verticalAlign:"middle"}),m(a.wrapEl,d);var e=b.el;return a.el=e&&e.cloneNode?e.cloneNode(!0):r({html:e||""}),a.layerEl=v(a.el,b),a.contentEl=y(a.layerEl),a.context=new A(a.layerEl),m(a.wrapEl,a.layerEl),a.bodyEl=b.body&&k(b.body)||D.body,a.wrapEl.tabIndex=-1,q(a.wrapEl,{top:0,left:0,right:0,bottom:0,position:"fixed",textAlign:"center",overflow:"auto",outline:0}),a}function y(a){return a.firstChild.lastChild.firstChild}function z(a,b){b=a instanceof Object?a:b||{},b.el=b.el||a;var c=this;c.cid="c"+B++,P.zIndex++,c.options=b=j({},P,b),b.flags=j({},P.flags,b.flags),x(c,b),c.setEffect(b.effect),c.fx=function(a){return!(c.fx.queue=c.fx.queue.then(a,a).then(function(){return c}))},c.fx.queue=f(),c.on("click",":overlay",function(){c.hasFlag("closeByOverlay")&&c.closeBy("overlay")}),c.on("click",":close",function(a,b){a.preventDefault(),c.closeBy("BUTTON"===b.nodeName?"cancel":"x")}),c.options.init(this)}function A(a){this.el=a}var B=1,C=function(){},D=a.document,E=a.setTimeout,F=a.jQuery||a.Zepto||a.ender||a.$,G=b||a.Promise,H=/^(\w+)?(#\w+)?((?:\.[\w_-]+)*)/i,I=function(){var a={},b=r().style,c="opacity transition transform perspective transformStyle transformOrigin backfaceVisibility".split(" "),d=["Webkit","Moz","O","MS"];return h(c,function(c,e){if(a[c]=c in b&&c,!a[c])for(e=0;4>e;e++){var f=d[e]+c.charAt(0).toUpperCase()+c.substr(1);if(a[c]=f in b&&f)break}}),a}(),J={esc:27},K={},L=[],M=L.push,N=L.splice,O="data-ply";I.opacity||(K.opacity=function(a,b){a.zoom=1,a.filter="alpha(opacity="+100*b+")"}),u.get=function(){return u.el||(u.el=r({tag:".ply-loading",children:{".ply-loading-spinner":!0}}))};var P={zIndex:1e4,layer:{},overlay:{opacity:.6,backgroundColor:"rgb(0, 0, 0)"},flags:{closeBtn:!0,bodyScroll:!1,closeByEsc:!0,closeByOverlay:!0,hideLayerInStack:!0,visibleOverlayInStack:!1},baseHtml:!0,init:C,open:C,close:C,destroy:C,callback:C};return z.fn=z.prototype={constructor:z,_activate:function(){if(!this.hasFlag("bodyScroll")){var a=this.bodyEl,b=r({css:{overflow:"auto",visibility:"hidden",height:"5px"},children:[{tag:"div",css:{height:"100px"}}]});this.__overflow=q(a,"overflow"),this.__paddingRight=q(a,"paddingRight"),m(a,b),q(a,{overflow:"hidden",paddingRight:b.offsetWidth-b.firstChild.offsetWidth+"px"}),n(b)}o(this.wrapEl,"submit",this._getHandleEvent("submit"))},_deactivate:function(){this.hasFlag("bodyScroll")||q(this.bodyEl,{overflow:this.__overflow,paddingRight:this.__paddingRight}),p(this.layerEl,"submit",this._getHandleEvent("submit"))},_getHandleEvent:function(a){var b=this,c=b.__handleEvent||(b.__handleEvent={});return c[a]||(c[a]=function(c){b._handleEvent(a,c)}),c[a]},_handleEvent:function(a,b){b.preventDefault(),this.closeBy(a)},applyEffect:function(a,b,c){return a=this[a]||a,a.nodeType||(c=b,b=a,a=this.layerEl),c=z.effects.get(c||this.effects),z.effects.apply.call(c,a,b)},closeBy:function(a){var b=this,c={by:a,state:"submit"===a,layer:this,data:this.context.toJSON(),context:this.context},d=this.options.callback(c);g(d).then(function(a){a!==!1&&(b.result=c,b.close())})},on:function(a,b,c){var d=this;return c||(c=b,b=":layer"),c["_"+b]=function(a){var e=a.target;do if(1===e.nodeType&&e.getAttribute(O)===b)return c.call(d,a,e);while(e!==d.wrapEl&&(e=e.parentNode))},o(d.wrapEl,a,c["_"+b]),d},off:function(a,b,c){return c||(c=b,b="layer"),p(this.wrapEl,a,c["_"+b]||C),this},hasFlag:function(a){return!!this.options.flags[a]},setEffect:function(a){return this.effects=z.effects.get(a),this},_toggleState:function(a,b){var c=this,d=a?"open":"close",f=z.stack.last;return c.visible!=a&&(c.visible=a,c[a?"_activate":"_deactivate"](),z.stack[a?"add":"remove"](c),c.fx(function(){return t(c.wrapEl).then(function(){var g=z.stack.length===(a?1:0),h=f&&f.hasFlag("hideLayerInStack"),i=g||c.hasFlag("visibleOverlayInStack");return a?(!i&&n(c.overlayBoxEl),m(c.bodyEl,c.wrapEl),c.wrapEl.focus(),s(c.layerEl),h&&f.applyEffect("close.layer",b).then(function(){n(f.layerEl)})):(f=z.stack.last)&&(m(f.wrapEl,f.layerEl),f.hasFlag("hideLayerInStack")&&f.applyEffect("open.layer",b).then(function(){s(f.el)})),e([c.applyEffect(d+".layer",b),i&&c.applyEffect("overlayEl",d+".overlay",b)]).then(function(){a||(n(c.wrapEl),m(c.overlayEl,c.overlayBoxEl)),c.options[d](c)})})})),c.fx.queue},open:function(a){return this.result=null,this._toggleState(!0,a)},close:function(a){return this._toggleState(!1,a)},_swap:function(a,b,c,d,f){var g=this;return g.visible?g.fx(function(){return t(b).then(function(){return d(),e([g.applyEffect(a,"close.layer",c),g.applyEffect(b,"open.layer",c)]).then(function(){n(a),f(),g.wrapEl.focus(),s(b)})})}):f(),g.fx.queue},swap:function(a,b){a=j({},this.options,a);var c=this,d=x({},a,!0),e=b||a.effect?z.effects.get(b||a.effect):c.effects,f=c.layerEl,g=d.layerEl;return c._swap(f,g,e,function(){m(c.bodyEl,c.wrapEl),m(c.bodyEl,d.wrapEl)},function(){n(d.wrapEl),m(c.wrapEl,g),c.el=d.el,c.layerEl=g,c.contentEl=y(g),c.context.el=g})},innerSwap:function(a,b){a=j({},this.options,a);var c=this,d=x({},a,!0),e=b||a.effect?z.effects.get(b||a.effect):c.effects,f=k(".ply-inside",d.layerEl),g=k(".ply-inside",c.layerEl);return c._swap(g,f,e,function(){q(g,{width:g.offsetWidth+"px",position:"absolute"}),m(g.parentNode,f)},C)},destroy:function(){n(this.wrapEl),this._deactivate(),z.stack.remove(this),this.visible=!1,this.options.destroy(this)}},z.stack={_idx:{},last:null,length:0,_pop:function(a){var b=z.stack.last;a.keyCode===J.esc&&b.hasFlag("closeByEsc")&&b.closeBy("esc")},add:function(a){var b=M.call(this,a);this.last=a,this._idx[a.cid]=b-1,1===b&&o(D,"keyup",this._pop)},remove:function(a){var b=this._idx[a.cid];b>=0&&(N.call(this,b,1),delete this._idx[a.cid],this.last=this[this.length-1],this.last||p(D,"keyup",this._pop))}},z.effects={defaults:{duration:300,open:{layer:null,overlay:null},close:{layer:null,overlay:null}},setup:function(a){this.defaults=this.get(a)},get:function(a){function b(a){var b=/^([\w_-]+)(?::(\d+%?))?(\[[^\]]+\])?/.exec(a)||[];return{name:b[1]||a,duration:b[2]||null,args:JSON.parse(b[3]||"null")||{}}}function c(c,d,e){var f=b(d),g=c[f.name]||e||{},h=f.duration||g.duration||c.duration||a.duration;return"string"==typeof g&&(g=b(g),delete g.args),/%/.test(g.duration)&&(g.duration=parseInt(g.duration,10)/100*h),g.duration=0|(g.duration||h),g}var d=i(this.defaults);if("string"==typeof a){var e=b(a);a=i(this[e.name]||{open:{},close:{}}),a.duration=e.duration||a.duration,a.open.args=e.args[0],a.close.args=e.args[1]}else if(a instanceof Array){var f=b(a[0]),g=b(a[1]),h=this[f.name],j=this[g.name];a={open:i(h&&h.open||{layer:a[0],overlay:a[0]}),close:i(j&&j.close||{layer:a[1],overlay:a[1]})},a.open.args=f.args[0],a.close.args=g.args[0]}else a instanceof Object||(a={});a.duration=0|(a.duration||d.duration);for(var k in{open:0,close:0}){var l=a[k]||d[k]||{};"string"==typeof l&&(l={layer:l}),l.layer=c(l,"layer",d[k].layer),l.overlay=c(l,"overlay",d[k].overlay),void 0===l.args&&delete l.args,a[k]=l}return a},apply:function(a,b){b=b.split(".");var e,g,j=this[b[0]],k=a.firstChild,l=[a.getAttribute("style"),k&&k.getAttribute("style")];return I.transition&&j&&(g=j[b[1]])&&(e=z.effects[g.name])&&(e.to||e.from)?(e=i(e),q(a,"transition","none"),q(k,"transition","none"),h(e.to,function(b,c,d){"&"===b&&(d[c]=q(a,c))}),c(e.from)?e.from(a,j.args):e.from&&q(a,e.from),d(function(b){e.width=a.offsetWidth,q(a,"transition","all "+g.duration+"ms"),q(k,"transition","all "+g.duration+"ms"),c(e.to)?e.to(a,j.args):q(a,e.to),E(b,g.duration)}).then(function(){a.setAttribute("style",l[0]),k&&k.setAttribute("style",l[1])})):f()},fade:{open:{layer:"fade-in:80%",overlay:"fade-in:100%"},close:{layer:"fade-out:60%",overlay:"fade-out:60%"}},scale:{open:{layer:"scale-in",overlay:"fade-in"},close:{layer:"scale-out",overlay:"fade-out"}},fall:{open:{layer:"fall-in",overlay:"fade-in"},close:{layer:"fall-out",overlay:"fade-out"}},slide:{open:{layer:"slide-in",overlay:"fade-in"},close:{layer:"slide-out",overlay:"fade-out"}},"3d-flip":{open:{layer:"3d-flip-in",overlay:"fade-in"},close:{layer:"3d-flip-out",overlay:"fade-out"}},"3d-sign":{open:{layer:"3d-sign-in",overlay:"fade-in"},close:{layer:"3d-sign-out",overlay:"fade-out"}},inner:{open:{layer:"inner-in"},close:{layer:"inner-out"}},"fade-in":{from:{opacity:0},to:{opacity:"&"}},"fade-out":{to:{opacity:0}},"slide-in":{from:{opacity:0,transform:"translateY(20%)"},to:{opacity:"&",transform:"translateY(0)"}},"slide-out":{to:{opacity:0,transform:"translateY(20%)"}},"fall-in":{from:{opacity:0,transform:"scale(1.3)"},to:{opacity:"&",transform:"scale(1)"}},"fall-out":{to:{opacity:0,transform:"scale(1.3)"}},"scale-in":{from:{opacity:0,transform:"scale(0.7)"},to:{opacity:"&",transform:"scale(1)"}},"scale-out":{to:{opacity:0,transform:"scale(0.7)"}},rotate3d:function(a,b,c,d,e){q(a,{perspective:"1300px"}),q(a.firstChild,{opacity:b,transform:"rotate"+c+"("+d+"deg)",transformStyle:"preserve-3d",transformOrigin:e?"50% 0":"50%"})},"3d-sign-in":{from:function(a){z.effects.rotate3d(a,0,"X",-60,"50% 0")},to:function(a){q(a.firstChild,{opacity:1,transform:"rotateX(0)"})}},"3d-sign-out":{from:function(a){z.effects.rotate3d(a,1,"X",0,"50% 0")},to:function(a){q(a.firstChild,{opacity:0,transform:"rotateX(-60deg)"})}},"3d-flip-in":{from:function(a,b){z.effects.rotate3d(a,0,"Y",b||-70)},to:function(a){q(a.firstChild,{opacity:1,transform:"rotateY(0)"})}},"3d-flip-out":{from:function(a){z.effects.rotate3d(a,1,"Y",0)},to:function(a,b){q(a.firstChild,{opacity:0,transform:"rotateY("+(b||70)+"deg)"})}},"inner-in":{from:function(a){q(a,"transform","translateX(100%)")},to:function(a){q(a,"transform","translateX(0%)")}},"inner-out":{from:function(a){q(a,"transform","translateX(0%)")},to:function(a){q(a,"transform","translateX(-100%)")}}},A.fn=A.prototype={constructor:A,getEl:function(a){return this.el?k("["+O+'-name="'+a+'"]',this.el):void 0},val:function(a,b){var c="string"==typeof a?this.getEl(a):a;return c&&null==c.value&&(c=l(c,"input")[0]||l(c,"textarea")[0]||l(c,"select")[0]),c&&null!=b&&(c.value=b),c&&c.value||""},toJSON:function(){for(var a,b=this.el.querySelectorAll("["+O+"-name]"),c={},d=b.length;d--;)a=b[d],c[a.getAttribute(O+"-name")]=this.val(a);return c}},z.lang={ok:"OK",cancel:"Cancel",cross:"✖"},z.css=q,z.cssHooks=K,z.keys=J,z.noop=C,z.each=h,z.extend=j,z.promise=d,z.support=I,z.defaults=P,z.attrName=O,z.Context=A,z.dom={build:r,append:m,remove:n,addEvent:o,removeEvent:p},z}),function(a){a(Ply)}(function(a){"use strict";function b(a,c,d){var f,g=b[a];return g||(a=a.split(/\s+/).slice(0,-1).join(" "),g=c&&(b[a+" [name="+c.name+"]"]||b[a+" [type="+c.type+"]"])||b[a+" *"]||b[":default"]),f=j(g(c,d)),c&&c.name&&f.setAttribute(e+"-name",c.name),f.className+=" ply-ui",f}function c(a,d){c["_"+a]=d,c[a]=function(a,c){return i(function(b,e){d(a,c,b,e)}).then(function(a){return a.appendChild||(a=b(":root",a)),a})}}function d(a,b,c,d){return b.mod=a,b.effect=b.effect||"slide",b.flags=h({closeBtn:!1},b.flags),{header:c.title,content:c.form?{"dialog-form":{children:c.form}}:{el:c.text||c},ctrls:{ok:c.ok||d.ok,cancel:c.cancel===!1?null:c.cancel||d.cancel}}}var e=a.attrName,f=a.noop,g=a.each,h=a.extend,i=a.promise,j=a.dom.build,k=a.dom.append,l=a.lang,m=function(a,b){return null==a?{skip:!0}:("string"==typeof a&&(a={text:a}),"object"==typeof a&&(a.name=a.name||b),a)};b.factory=function(a,c,d){b[a.replace(/^\s+|\s+$/g,"").replace(/\s+/g," ")]=function(e,f){var i=document.createDocumentFragment();if(null!=e||":root"===a){e=d?e:m(e),g(d?e:e.children,function(c,d){var e=((f||a)+" "+d).replace(/^:\w+\s+/,""),g=b(e,m(c,d),e);k(i,g)}),d||delete e.children;var j=c(e,i);return j.appendChild||h(j,e),j}return i}},b.factory(":default",function(a,b){return a.children=b,a}),b.factory(":root",function(a){return{tag:".ply-form",className:a.mod,children:[b(":header",a.header),b(":content",a.content),a.ctrls&&b(":default",{tag:"div.ply-footer",children:a.ctrls})]}}),b.factory(":header",function(a,b){return{tag:".ply-header",text:a.text,children:b}}),b.factory(":content",function(a,b){return{tag:".ply-content",children:b}},!0),b.factory("ok",function(a){return{ply:":ok",tag:"button.ply-ctrl.ply-ok",text:a===!0?l.ok:a}}),b.factory("cancel",function(a){return{ply:":close",tag:"button.ply-ctrl.ply-cancel",type:"reset",text:a===!0?l.cancel:a}}),c.use=function(a,b,d,e,f){c["_"+a](b,d,e,f)},c("default",function(a,b,c){c(b||{})}),c("alert",function(a,b,c){c(d("alert",a,b,{ok:!0}))}),c("confirm",function(a,b,c){c(d("confirm",a,b,{ok:!0,cancel:!0}))}),c("prompt",function(a,b,c){c(d("prompt",a,b,{ok:!0,cancel:!0}))}),b.factory("dialog-form *",function(a){return{tag:"input.ply-input",type:a.type||"text",name:a.name,value:a.value,required:!0,placeholder:a.hint||a.text}}),a.create=function(b,d,e){e||(e=d,d={});var f=c[b]||c["default"];return f(d,e).then(function(b){return new a(h(d,{el:b}))})},a.open=function(b,c,d){return a.create(b,c,d).then(function(a){return a.open()})},a.dialog=function(b,c,d){return b instanceof Object?(c=c||{},i(function(d,e){var i,j,k,l=c.initState,m=b,n={},o=function(a,b){(c.progress||f)(h({name:i.$name,index:i.$index,length:q,stack:m,current:i,layer:b},a),n)},p=function(b,c,d){var e=JSON.parse(JSON.stringify(b.data));i=b,k=!0,(b.prepare||f)(e,n),a.create(b.ui||"alert",b.options||{},e).then(function(a){var e;j?e=j[/^inner/.test(c)?"innerSwap":"swap"](a,c):(j=a,e=j.open()),e.then(function(){n[b.$name].el=j.layerEl,k=!1}),d(j)})},q=0;g(m,function(b,c){l=l||c,b.effects=b.effects||{},b.$name=c,b.$index=q++,n[c]=new a.Context}),m.$length=q,p(m[l],null,function(a){o({},a),j.options.callback=function(a){if(k)return!1;var b=a.state||"next"===i.back,c=m[i[b?"next":"back"]];return c?(p(c,i[b?"nextEffect":"backEffect"],function(b){o(a,b)}),!1):void(a.state?d:e)(a,n)}})})):(d||(d=c||{},c={}),a.open(b,c,d).then(function(a){return i(function(b){a.options.close=function(){b(a.result)}})}))},a.ui=b,a.factory=c});
\ No newline at end of file
+!function (a) {
+ window.Ply = a(window)
+}(function (a, b) {
+ "use strict";
+ function c(a) {
+ return"function" == typeof a
+ }
+
+ function d(a) {
+ if (O)return new O(a);
+ var b = P.Deferred();
+ return a(b.resolve, b.reject), b
+ }
+
+ function e(a) {
+ return O ? O.all(a) : P.when.apply(P, a)
+ }
+
+ function f(a) {
+ return d(function (b) {
+ return b(a)
+ })
+ }
+
+ function g(a) {
+ return a && a.then ? a : f(a)
+ }
+
+ function h(a, b) {
+ if (a)for (var c in a)a.hasOwnProperty(c) && b(a[c], c, a)
+ }
+
+ function i(a) {
+ var b = {};
+ return h(a, function (a, d) {
+ b[d] = c(a) ? a : a instanceof Object ? i(a) : a
+ }), b
+ }
+
+ function j(a) {
+ for (var b = Array.prototype.slice, c = b.call(arguments, 1), d = 0, e = c.length; e > d; d++)h(c[d], function (b, c) {
+ a[c] = b
+ });
+ return a
+ }
+
+ function k(a, b) {
+ try {
+ return(b || H).querySelector(a)
+ } catch (c) {
+ return P(a, b)[0]
+ }
+ }
+
+ function l(a, b) {
+ return a.getElementsByTagName(b)
+ }
+
+ function m(a, b) {
+ try {
+ a && b && a.appendChild(b)
+ } catch (c) {
+ }
+ }
+
+ function n(a) {
+ a && a.parentNode && a.parentNode.removeChild(a)
+ }
+
+ function o(a, b, c) {
+ var d = c.handle = c.handle || function (b) {
+ b.target || (b.target = b.srcElement || H), 3 === b.target.nodeType && (b.target = b.target.parentNode), b.preventDefault || (b.preventDefault = function () {
+ b.returnValue = !1
+ }), b.stopPropagation || (b.stopPropagation = function () {
+ b.cancelBubble = !0
+ }), c.call(a, b)
+ };
+ a.addEventListener ? a.addEventListener(b, d, !1) : a.attachEvent("on" + b, d)
+ }
+
+ function p(a, b, c) {
+ var d = c.handle;
+ d && (a.removeEventListener ? a.removeEventListener(b, d, !1) : a.detachEvent("on" + b, d))
+ }
+
+ function q(a) {
+ if (null == a && (a = "div"), a.appendChild)return a;
+ if (a.skip)return H.createDocumentFragment();
+ "string" == typeof a && (a = {tag: a});
+ var b, c = a.children, d = Q.exec(a.tag || "");
+ return delete a.children, a.tag = d[1] || "div", a.id = a.id || (d[2] || "").substr(1), d = (d[3] || "").split("."), d[0] = a.className || "", a.className = d.join(" "), b = H.createElement(a.tag), delete a.tag, h(a, function (c, d) {
+ if (c)if ("css" === d)t(b, a.css); else if ("text" === d)null != c && m(b, H.createTextNode(c)); else if ("html" === d)null != c && (b.innerHTML = c); else if ("ply" === d)b.setAttribute(M, c); else if (d in b)try {
+ b[d] = c
+ } catch (e) {
+ b.setAttribute(d, c)
+ } else/^data-/.test(d) && b.setAttribute(d, c)
+ }), c && c.appendChild ? m(b, c) : h(c, function (a, c) {
+ a && ("string" == typeof a ? a = {text: a} : "object" != typeof a && (a = {}), "string" == typeof c && (a.tag = a.tag || c), m(b, q(a)))
+ }), b
+ }
+
+ function r(a) {
+ for (var b, c, d = l(a, "input"), e = 0, f = d.length; f > e; e++)if (b = d[e], "submit" === b.type)!c && (c = b); else if (!/hidden|check|radio/.test(b.type) && "" == b.value) {
+ c = b;
+ break
+ }
+ c || (c = l(a, "button")[0]);
+ try {
+ c.focus()
+ } catch (g) {
+ }
+ }
+
+ function s(a) {
+ return u(!0), d(function (b) {
+ for (var c, d = l(a, "img"), e = d.length, f = e, g = function () {
+ if (--f <= 0) {
+ for (e = d.length; e--;)c = d[e], p(c, "load", g), p(c, "error", g);
+ u(!1), b()
+ }
+ }; e--;)c = d[e], c.complete ? f-- : (o(c, "load", g), o(c, "error", g));
+ !f && g()
+ })
+ }
+
+ function t(a, b, c) {
+ if (a && a.style && b)if (b instanceof Object)for (var d in b)t(a, d, b[d]); else {
+ if (void 0 === c)return H.defaultView && H.defaultView.getComputedStyle ? c = H.defaultView.getComputedStyle(a, "") : a.currentStyle && (c = a.currentStyle), void 0 === b ? c : c[b];
+ R[b] ? R[b](a.style, c) : a.style[K[b] || b] = c
+ }
+ }
+
+ function u(a) {
+ var b = u.get();
+ clearTimeout(u.pid), u.pid = a ? I(function () {
+ m(H.body, b)
+ }, 100) : I(function () {
+ n(b)
+ }, 100)
+ }
+
+ function v(a, b) {
+ return q({css: {padding: "20px 20px 40px", display: "inline-block", position: "relative", textAlign: "left", whiteSpace: "normal", verticalAlign: "middle", transform: "translate3d(0, 0, 0)"}, children: b.baseHtml ? [
+ {ply: ":layer", tag: ".ply-layer", className: b.mod, css: j({overflow: "hidden", position: "relative", backfaceVisibility: "hidden"}, b.layer), children: [b.flags.closeBtn && {ply: ":close", tag: ".ply-x", text: J.cross}, {tag: ".ply-inside", children: a}]}
+ ] : a})
+ }
+
+ function w(a) {
+ return q({ply: ":overlay", tag: ".ply-overlay", css: {top: 0, left: 0, right: 0, bottom: 0, position: "fixed"}, children: [
+ {tag: "div", css: j({width: "100%", height: "100%"}, a)}
+ ]})
+ }
+
+ function x(a, b, c) {
+ a.wrapEl = q({tag: "form", css: {whiteSpace: "nowrap", zIndex: b.zIndex}}), c || (a.overlayEl = w(b.overlay), a.overlayBoxEl = a.overlayEl.firstChild, m(a.wrapEl, a.overlayEl));
+ var d = q();
+ t(d, {height: "100%", display: "inline-block", verticalAlign: "middle"}), m(a.wrapEl, d);
+ var e = b.el;
+ return a.el = e && e.cloneNode ? e.cloneNode(!0) : q({html: e || ""}), a.layerEl = v(a.el, b), a.contentEl = y(a.layerEl), a.context = new A(a.layerEl), m(a.wrapEl, a.layerEl), a.bodyEl = b.body && k(b.body) || H.body, a.wrapEl.tabIndex = -1, t(a.wrapEl, {top: 0, left: 0, right: 0, bottom: 0, position: "fixed", textAlign: "center", overflow: "auto", outline: 0}), a
+ }
+
+ function y(a) {
+ return a.firstChild.lastChild.firstChild
+ }
+
+ function z(a, b) {
+ b = a instanceof Object ? a : b || {}, b.el = b.el || a;
+ var c = this;
+ c.cid = "c" + F++, N.zIndex++, c.options = b = j({}, N, b), b.flags = j({}, N.flags, b.flags), x(c, b), c.setEffect(b.effect), c.fx = function (a) {
+ return!(c.fx.queue = c.fx.queue.then(a, a).then(function () {
+ return c
+ }))
+ }, c.fx.queue = f(), c.on("click", ":overlay", function () {
+ c.hasFlag("closeByOverlay") && c.closeBy("overlay")
+ }), c.on("click", ":close", function (a, b) {
+ a.preventDefault(), c.closeBy("BUTTON" === b.nodeName ? "cancel" : "x")
+ }), c.options.init(this)
+ }
+
+ function A(a) {
+ this.el = a
+ }
+
+ function B(a, b) {
+ return null == a ? {skip: !0} : ("string" == typeof a && (a = {text: a}), "object" == typeof a && (a.name = a.name || b), a)
+ }
+
+ function C(a, b, c) {
+ var d, e = C[a];
+ return e || (a = a.split(/\s+/).slice(0, -1).join(" "), e = b && (C[a + " [name=" + b.name + "]"] || C[a + " [type=" + b.type + "]"]) || C[a + " *"] || C[":default"]), d = q(e(b, c)), b && b.name && d.setAttribute(M + "-name", b.name), d.className += " ply-ui", d
+ }
+
+ function D(a, b) {
+ D["_" + a] = b, D[a] = function (a, c) {
+ return d(function (d, e) {
+ b(a, c, d, e)
+ }).then(function (a) {
+ return a.appendChild || (a = C(":root", a)), a
+ })
+ }
+ }
+
+ function E(a, b, c, d) {
+ return b.mod = a, b.effect = b.effect || "slide", b.flags = j({closeBtn: !1}, b.flags), {header: c.title, content: c.form ? {"dialog-form": {children: c.form}} : {el: c.text || c}, ctrls: {ok: c.ok || d.ok, cancel: c.cancel === !1 ? null : c.cancel || d.cancel}}
+ }
+
+ var F = 1, G = function () {
+ }, H = a.document, I = a.setTimeout, J = {ok: "OK", cancel: "Cancel", cross: "✖"}, K = function () {
+ var a = {}, b = H.createElement("div").style, c = "opacity transition transform perspective transformStyle transformOrigin backfaceVisibility".split(" "), d = ["Webkit", "Moz", "O", "MS"];
+ return h(c, function (c, e) {
+ if (a[c] = c in b && c, !a[c])for (e = 0; 4 > e; e++) {
+ var f = d[e] + c.charAt(0).toUpperCase() + c.substr(1);
+ if (a[c] = f in b && f)break
+ }
+ }), a
+ }(), L = {esc: 27}, M = "data-ply", N = {zIndex: 1e4, layer: {}, overlay: {opacity: .6, backgroundColor: "rgb(0, 0, 0)"}, flags: {closeBtn: !0, bodyScroll: !1, closeByEsc: !0, closeByOverlay: !0, hideLayerInStack: !0, visibleOverlayInStack: !1}, baseHtml: !0, init: G, open: G, close: G, destroy: G, callback: G}, O = b || a.Promise, P = a.jQuery || a.Zepto || a.ender || a.$, Q = /^(\w+)?(#\w+)?((?:\.[\w_-]+)*)/i, R = {opacity: !K.opacity && function (a, b) {
+ a.zoom = 1, a.filter = "alpha(opacity=" + 100 * b + ")"
+ }};
+ u.get = function () {
+ return u.el || (u.el = q({tag: ".ply-loading", children: {".ply-loading-spinner": !0}}))
+ }, z.fn = z.prototype = {constructor: z, _activate: function () {
+ if (!this.hasFlag("bodyScroll")) {
+ var a = this.bodyEl, b = q({css: {overflow: "auto", visibility: "hidden", height: "5px"}, children: [
+ {tag: "div", css: {height: "100px"}}
+ ]});
+ this.__overflow = t(a, "overflow"), this.__paddingRight = t(a, "paddingRight"), m(a, b), t(a, {overflow: "hidden", paddingRight: b.offsetWidth - b.firstChild.offsetWidth + "px"}), n(b)
+ }
+ o(this.wrapEl, "submit", this._getHandleEvent("submit"))
+ }, _deactivate: function () {
+ this.hasFlag("bodyScroll") || t(this.bodyEl, {overflow: this.__overflow, paddingRight: this.__paddingRight}), p(this.layerEl, "submit", this._getHandleEvent("submit"))
+ }, _getHandleEvent: function (a) {
+ var b = this, c = b.__handleEvent || (b.__handleEvent = {});
+ return c[a] || (c[a] = function (c) {
+ b._handleEvent(a, c)
+ }), c[a]
+ }, _handleEvent: function (a, b) {
+ b.preventDefault(), this.closeBy(a)
+ }, applyEffect: function (a, b, c) {
+ return a = this[a] || a, a.nodeType || (c = b, b = a, a = this.layerEl), c = z.effects.get(c || this.effects), z.effects.apply.call(c, a, b)
+ }, closeBy: function (a) {
+ var b = this, c = {by: a, state: "submit" === a, layer: this, data: this.context.toJSON(), context: this.context}, d = this.options.callback(c);
+ g(d).then(function (a) {
+ a !== !1 && (b.result = c, b.close())
+ })
+ }, on: function (a, b, c) {
+ var d = this;
+ return c || (c = b, b = ":layer"), c["_" + b] = function (a) {
+ var e = a.target;
+ do if (1 === e.nodeType && e.getAttribute(M) === b)return c.call(d, a, e); while (e !== d.wrapEl && (e = e.parentNode))
+ }, o(d.wrapEl, a, c["_" + b]), d
+ }, off: function (a, b, c) {
+ return c || (c = b, b = "layer"), p(this.wrapEl, a, c["_" + b] || G), this
+ }, hasFlag: function (a) {
+ return!!this.options.flags[a]
+ }, setEffect: function (a) {
+ return this.effects = z.effects.get(a), this
+ }, _toggleState: function (a, b) {
+ var c = this, d = a ? "open" : "close", f = z.stack.last;
+ return c.visible != a && (c.visible = a, c[a ? "_activate" : "_deactivate"](), z.stack[a ? "add" : "remove"](c), c.fx(function () {
+ return s(c.wrapEl).then(function () {
+ var g = z.stack.length === (a ? 1 : 0), h = f && f.hasFlag("hideLayerInStack"), i = g || c.hasFlag("visibleOverlayInStack");
+ return a ? (!i && n(c.overlayBoxEl), m(c.bodyEl, c.wrapEl), c.wrapEl.focus(), r(c.layerEl), h && f.applyEffect("close.layer", b).then(function () {
+ n(f.layerEl)
+ })) : (f = z.stack.last) && (m(f.wrapEl, f.layerEl), f.hasFlag("hideLayerInStack") && f.applyEffect("open.layer", b).then(function () {
+ r(f.el)
+ })), e([c.applyEffect(d + ".layer", b), i && c.applyEffect("overlayEl", d + ".overlay", b)]).then(function () {
+ a || (n(c.wrapEl), m(c.overlayEl, c.overlayBoxEl)), c.options[d](c)
+ })
+ })
+ })), c.fx.queue
+ }, open: function (a) {
+ return this.result = null, this._toggleState(!0, a)
+ }, close: function (a) {
+ return this._toggleState(!1, a)
+ }, _swap: function (a, b, c, d, f) {
+ var g = this;
+ return g.visible ? g.fx(function () {
+ return s(b).then(function () {
+ return d(), e([g.applyEffect(a, "close.layer", c), g.applyEffect(b, "open.layer", c)]).then(function () {
+ n(a), f(), g.wrapEl.focus(), r(b)
+ })
+ })
+ }) : f(), g.fx.queue
+ }, swap: function (a, b) {
+ a = j({}, this.options, a);
+ var c = this, d = x({}, a, !0), e = b || a.effect ? z.effects.get(b || a.effect) : c.effects, f = c.layerEl, g = d.layerEl;
+ return c._swap(f, g, e, function () {
+ m(c.bodyEl, c.wrapEl), m(c.bodyEl, d.wrapEl)
+ }, function () {
+ n(d.wrapEl), m(c.wrapEl, g), c.el = d.el, c.layerEl = g, c.contentEl = y(g), c.context.el = g
+ })
+ }, innerSwap: function (a, b) {
+ a = j({}, this.options, a);
+ var c = this, d = x({}, a, !0), e = b || a.effect ? z.effects.get(b || a.effect) : c.effects, f = k(".ply-inside", d.layerEl), g = k(".ply-inside", c.layerEl);
+ return c._swap(g, f, e, function () {
+ t(g, {width: g.offsetWidth + "px", position: "absolute"}), m(g.parentNode, f)
+ }, G)
+ }, destroy: function () {
+ n(this.wrapEl), this._deactivate(), z.stack.remove(this), this.visible = !1, this.options.destroy(this)
+ }};
+ var S = [], T = S.push, U = S.splice;
+ return z.stack = {_idx: {}, last: null, length: 0, _pop: function (a) {
+ var b = z.stack.last;
+ a.keyCode === L.esc && b.hasFlag("closeByEsc") && b.closeBy("esc")
+ }, add: function (a) {
+ var b = T.call(this, a);
+ this.last = a, this._idx[a.cid] = b - 1, 1 === b && o(H, "keyup", this._pop)
+ }, remove: function (a) {
+ var b = this._idx[a.cid];
+ b >= 0 && (U.call(this, b, 1), delete this._idx[a.cid], this.last = this[this.length - 1], this.last || p(H, "keyup", this._pop))
+ }}, z.effects = {defaults: {duration: 300, open: {layer: null, overlay: null}, close: {layer: null, overlay: null}}, setup: function (a) {
+ this.defaults = this.get(a)
+ }, set: function (a) {
+ j(this, a)
+ }, get: function (a) {
+ function b(a) {
+ var b = /^([\w_-]+)(?::(\d+%?))?(\[[^\]]+\])?/.exec(a) || [];
+ return{name: b[1] || a, duration: b[2] || null, args: JSON.parse(b[3] || "null") || {}}
+ }
+
+ function c(c, d, e) {
+ var f = b(d), g = c[f.name] || e || {}, h = f.duration || g.duration || c.duration || a.duration;
+ return"string" == typeof g && (g = b(g), delete g.args), /%/.test(g.duration) && (g.duration = parseInt(g.duration, 10) / 100 * h), g.duration = 0 | (g.duration || h), g
+ }
+
+ var d = i(this.defaults);
+ if ("string" == typeof a) {
+ var e = b(a);
+ a = i(this[e.name] || {open: {}, close: {}}), a.duration = e.duration || a.duration, a.open.args = e.args[0], a.close.args = e.args[1]
+ } else if (a instanceof Array) {
+ var f = b(a[0]), g = b(a[1]), h = this[f.name], j = this[g.name];
+ a = {open: i(h && h.open || {layer: a[0], overlay: a[0]}), close: i(j && j.close || {layer: a[1], overlay: a[1]})}, a.open.args = f.args[0], a.close.args = g.args[0]
+ } else a instanceof Object || (a = {});
+ a.duration = 0 | (a.duration || d.duration);
+ for (var k in{open: 0, close: 0}) {
+ var l = a[k] || d[k] || {};
+ "string" == typeof l && (l = {layer: l}), l.layer = c(l, "layer", d[k].layer), l.overlay = c(l, "overlay", d[k].overlay), void 0 === l.args && delete l.args, a[k] = l
+ }
+ return a
+ }, apply: function (a, b) {
+ b = b.split(".");
+ var e, g, j = this[b[0]], k = a.firstChild, l = [a.getAttribute("style"), k && k.getAttribute("style")];
+ return K.transition && j && (g = j[b[1]]) && (e = z.effects[g.name]) && (e.to || e.from) ? (e = i(e), t(a, "transition", "none"), t(k, "transition", "none"), h(e.to, function (b, c, d) {
+ "&" === b && (d[c] = t(a, c))
+ }), c(e.from) ? e.from(a, j.args) : e.from && t(a, e.from), d(function (b) {
+ e.width = a.offsetWidth, t(a, "transition", "all " + g.duration + "ms"), t(k, "transition", "all " + g.duration + "ms"), c(e.to) ? e.to(a, j.args) : t(a, e.to), I(b, g.duration)
+ }).then(function () {
+ a.setAttribute("style", l[0]), k && k.setAttribute("style", l[1])
+ })) : f()
+ }}, z.effects.set({fade: {open: {layer: "fade-in:80%", overlay: "fade-in:100%"}, close: {layer: "fade-out:60%", overlay: "fade-out:60%"}}, scale: {open: {layer: "scale-in", overlay: "fade-in"}, close: {layer: "scale-out", overlay: "fade-out"}}, fall: {open: {layer: "fall-in", overlay: "fade-in"}, close: {layer: "fall-out", overlay: "fade-out"}}, slide: {open: {layer: "slide-in", overlay: "fade-in"}, close: {layer: "slide-out", overlay: "fade-out"}}, "3d-flip": {open: {layer: "3d-flip-in", overlay: "fade-in"}, close: {layer: "3d-flip-out", overlay: "fade-out"}}, "3d-sign": {open: {layer: "3d-sign-in", overlay: "fade-in"}, close: {layer: "3d-sign-out", overlay: "fade-out"}}, inner: {open: {layer: "inner-in"}, close: {layer: "inner-out"}}, "fade-in": {from: {opacity: 0}, to: {opacity: "&"}}, "fade-out": {to: {opacity: 0}}, "slide-in": {from: {opacity: 0, transform: "translateY(20%)"}, to: {opacity: "&", transform: "translateY(0)"}}, "slide-out": {to: {opacity: 0, transform: "translateY(20%)"}}, "fall-in": {from: {opacity: 0, transform: "scale(1.3)"}, to: {opacity: "&", transform: "scale(1)"}}, "fall-out": {to: {opacity: 0, transform: "scale(1.3)"}}, "scale-in": {from: {opacity: 0, transform: "scale(0.7)"}, to: {opacity: "&", transform: "scale(1)"}}, "scale-out": {to: {opacity: 0, transform: "scale(0.7)"}}, rotate3d: function (a, b, c, d, e) {
+ t(a, {perspective: "1300px"}), t(a.firstChild, {opacity: b, transform: "rotate" + c + "(" + d + "deg)", transformStyle: "preserve-3d", transformOrigin: e ? "50% 0" : "50%"})
+ }, "3d-sign-in": {from: function (a) {
+ z.effects.rotate3d(a, 0, "X", -60, "50% 0")
+ }, to: function (a) {
+ t(a.firstChild, {opacity: 1, transform: "rotateX(0)"})
+ }}, "3d-sign-out": {from: function (a) {
+ z.effects.rotate3d(a, 1, "X", 0, "50% 0")
+ }, to: function (a) {
+ t(a.firstChild, {opacity: 0, transform: "rotateX(-60deg)"})
+ }}, "3d-flip-in": {from: function (a, b) {
+ z.effects.rotate3d(a, 0, "Y", b || -70)
+ }, to: function (a) {
+ t(a.firstChild, {opacity: 1, transform: "rotateY(0)"})
+ }}, "3d-flip-out": {from: function (a) {
+ z.effects.rotate3d(a, 1, "Y", 0)
+ }, to: function (a, b) {
+ t(a.firstChild, {opacity: 0, transform: "rotateY(" + (b || 70) + "deg)"})
+ }}, "inner-in": {from: function (a) {
+ t(a, "transform", "translateX(100%)")
+ }, to: function (a) {
+ t(a, "transform", "translateX(0%)")
+ }}, "inner-out": {from: function (a) {
+ t(a, "transform", "translateX(0%)")
+ }, to: function (a) {
+ t(a, "transform", "translateX(-100%)")
+ }}}), A.fn = A.prototype = {constructor: A, getEl: function (a) {
+ return this.el ? k("[" + M + '-name="' + a + '"]', this.el) : void 0
+ }, val: function (a, b) {
+ var c = "string" == typeof a ? this.getEl(a) : a;
+ return c && null == c.value && (c = l(c, "input")[0] || l(c, "textarea")[0] || l(c, "select")[0]), c && null != b && (c.value = b), c && c.value || ""
+ }, toJSON: function () {
+ for (var a, b = this.el.querySelectorAll("[" + M + "-name]"), c = {}, d = b.length; d--;)a = b[d], c[a.getAttribute(M + "-name")] = this.val(a);
+ return c
+ }}, C.factory = function (a, b, c) {
+ C[a.replace(/^\s+|\s+$/g, "").replace(/\s+/g, " ")] = function (d, e) {
+ var f = H.createDocumentFragment();
+ if (null != d || ":root" === a) {
+ d = c ? d : B(d), h(c ? d : d.children, function (b, c) {
+ var d = ((e || a) + " " + c).replace(/^:\w+\s+/, ""), g = C(d, B(b, c), d);
+ m(f, g)
+ }), c || delete d.children;
+ var g = b(d, f);
+ return g.appendChild || j(g, d), g
+ }
+ return f
+ }
+ }, C.factory(":default", function (a, b) {
+ return a.children = b, a
+ }), C.factory(":root", function (a) {
+ return{tag: ".ply-form", className: a.mod, children: [C(":header", a.header), C(":content", a.content), a.ctrls && C(":default", {tag: "div.ply-footer", children: a.ctrls})]}
+ }), C.factory(":header", function (a, b) {
+ return{tag: ".ply-header", text: a.text, children: b}
+ }), C.factory(":content", function (a, b) {
+ return{tag: ".ply-content", children: b}
+ }, !0), C.factory("ok", function (a) {
+ return{ply: ":ok", tag: "button.ply-ctrl.ply-ok", text: a === !0 ? J.ok : a}
+ }), C.factory("cancel", function (a) {
+ return{ply: ":close", tag: "button.ply-ctrl.ply-cancel", type: "reset", text: a === !0 ? J.cancel : a}
+ }), D.use = function (a, b, c, d, e) {
+ D["_" + a](b, c, d, e)
+ }, D("default", function (a, b, c) {
+ c(b || {})
+ }), D("alert", function (a, b, c) {
+ c(E("alert", a, b, {ok: !0}))
+ }), D("confirm", function (a, b, c) {
+ c(E("confirm", a, b, {ok: !0, cancel: !0}))
+ }), D("prompt", function (a, b, c) {
+ c(E("prompt", a, b, {ok: !0, cancel: !0}))
+ }), C.factory("dialog-form *", function (a) {
+ return{tag: "input.ply-input", type: a.type || "text", name: a.name, value: a.value, required: !0, placeholder: a.hint || a.text}
+ }), z.create = function (a, b, c) {
+ c || (c = b, b = {});
+ var d = D[a] || D["default"];
+ return d(b, c).then(function (a) {
+ return new z(j(b, {el: a}))
+ })
+ }, z.open = function (a, b, c) {
+ return z.create(a, b, c).then(function (a) {
+ return a.open()
+ })
+ }, z.dialog = function (a, b, c) {
+ return a instanceof Object ? (b = b || {}, d(function (c, d) {
+ var e, f, g, i = b.initState, k = a, l = {}, m = function (a, c) {
+ (b.progress || G)(j({name: e.$name, index: e.$index, length: o, stack: k, current: e, layer: c}, a), l)
+ }, n = function (a, b, c) {
+ var d = JSON.parse(JSON.stringify(a.data));
+ e = a, g = !0, (a.prepare || G)(d, l), z.create(a.ui || "alert", a.options || {}, d).then(function (d) {
+ var e;
+ f ? e = f[/^inner/.test(b) ? "innerSwap" : "swap"](d, b) : (f = d, e = f.open()), e.then(function () {
+ l[a.$name].el = f.layerEl, g = !1
+ }), c(f)
+ })
+ }, o = 0;
+ h(k, function (a, b) {
+ i = i || b, a.effects = a.effects || {}, a.$name = b, a.$index = o++, l[b] = new z.Context
+ }), k.$length = o, n(k[i], null, function (a) {
+ m({}, a), f.options.callback = function (a) {
+ if (g)return!1;
+ var b = a.state || "next" === e.back, f = k[e[b ? "next" : "back"]];
+ return f ? (n(f, e[b ? "nextEffect" : "backEffect"], function (b) {
+ m(a, b)
+ }), !1) : void(a.state ? c : d)(a, l)
+ }
+ })
+ })) : (c || (c = b || {}, b = {}), z.open(a, b, c).then(function (a) {
+ return d(function (b) {
+ a.options.close = function () {
+ b(a.result)
+ }
+ })
+ }))
+ }, z.ui = C, z.factory = D, z.lang = J, z.css = t, z.cssHooks = R, z.keys = L, z.noop = G, z.each = h, z.extend = j, z.promise = d, z.support = K, z.defaults = N, z.attrName = M, z.Context = A, z.dom = {build: q, append: m, remove: n, addEvent: o, removeEvent: p}, z
+});
diff --git a/src/Context.es6 b/src/Context.es6
new file mode 100644
index 0000000..d13afcf
--- /dev/null
+++ b/src/Context.es6
@@ -0,0 +1,74 @@
+//
+// Ply-контекст
+//
+
+
+/**
+ * @class Ply.Context
+ * @param {HTMLElement} el
+ */
+function Context(el) {
+ /**
+ * Корневой элемент
+ * @type {HTMLElement}
+ */
+ this.el = el;
+}
+
+Context.fn = Context.prototype = /** @lends Ply.Context */{
+ constructor: Context,
+
+
+ /**
+ * Получить элемент по имени
+ * @param {String} name
+ * @returns {HTMLElement|undefined}
+ */
+ getEl: function (name) {
+ if (this.el) {
+ return _querySelector('[' + _plyAttr + '-name="' + name + '"]', this.el);
+ }
+ },
+
+
+ /**
+ * Получить или установить значение по имени
+ * @param {String} name
+ * @param {String} [value]
+ * @returns {String}
+ */
+ val: function (name, value) {
+ var el = typeof name === 'string' ? this.getEl(name) : name;
+
+ if (el && (el.value == null)) {
+ el = _getElementsByTagName(el, 'input')[0]
+ || _getElementsByTagName(el, 'textarea')[0]
+ || _getElementsByTagName(el, 'select')[0]
+ ;
+ }
+
+ if (el && value != null) {
+ el.value = value;
+ }
+
+ return el && el.value || "";
+ },
+
+
+ /**
+ * Получить JSON
+ * @returns {Object}
+ */
+ toJSON: function () {
+ var items = this.el.querySelectorAll('[' + _plyAttr + '-name]'),
+ json = {},
+ el,
+ i = items.length
+ ;
+ while (i--) {
+ el = items[i];
+ json[el.getAttribute(_plyAttr + '-name')] = this.val(el);
+ }
+ return json;
+ }
+};
diff --git a/src/Ply.es6 b/src/Ply.es6
index ca68c15..c6067d7 100644
--- a/src/Ply.es6
+++ b/src/Ply.es6
@@ -4,7 +4,7 @@
* Обязательно нужен JSON и Promise
*/
-/*global define, window */
+/*global require, define, window */
((factory) => {
window['Ply'] = factory(window);
})((window, Deferred) => {
@@ -17,547 +17,34 @@
document = window.document,
setTimeout = window.setTimeout,
- $ = window.jQuery
- || /* istanbul ignore next */ window.Zepto
- || /* istanbul ignore next */ window.ender
- || /* istanbul ignore next */ window.$,
-
- Promise = Deferred || window.Promise,
-
-
- /**
- * Разбор строки "tag#id.foo.bar"
- * @const {RegExp}
- */
- R_SELECTOR = /^(\w+)?(#\w+)?((?:\.[\w_-]+)*)/i,
-
-
- /**
- * Поддерживаемые css-свойства
- * @type {Object}
- */
- support = (() => {
- var props = {},
- style = _buildDOM().style,
- names = 'opacity transition transform perspective transformStyle transformOrigin backfaceVisibility'.split(' '),
- prefix = ['Webkit', 'Moz', 'O', 'MS']
- ;
-
- _each(names, (name, i) => {
- props[name] = (name in style) && /* istanbul ignore next */ name;
-
- /* istanbul ignore else */
- if (!props[name]) {
- for (i = 0; i < 4; i++) {
- var pname = prefix[i] + name.charAt(0).toUpperCase() + name.substr(1);
- /* istanbul ignore else */
- if (props[name] = (pname in style) && pname) {
- break;
- }
- }
- }
- });
-
- return props;
- })(),
-
+ lang = require('lang'),
+ support = require('support'),
/**
* Коды кнопок
* @type {Object}
*/
- keys = {
- esc: 27
- },
-
-
- /**
- * Хуки для css
- * @type {Object}
- */
- _cssHooks = {
- },
+ keys = require('keys'),
- array_core = [],
- array_push = array_core.push,
- array_splice = array_core.splice,
_plyAttr = 'data-ply'
;
//
- // Определяем css-хуки
+ // Настройки по умолчанию
//
- if (!support.opacity) {
- _cssHooks.opacity = function (style, value) {
- style.zoom = 1;
- style.filter = 'alpha(opacity=' + (value * 100) + ')';
- };
- }
+ var _defaults = require('defaults');
//
- // Вспомогательные методы
+ // Утилиты, CSS, DOM
//
+ require('utils');
+ require('dom');
+ require('css');
- /**
- * Функция?
- * @param {*} fn
- * @returns {Boolean}
- */
- function isFn(fn) {
- return typeof fn === 'function';
- }
-
-
- /**
- * Создать «Обещание»
- * @param {Function} executor
- * @returns {Promise}
- * @private
- */
- function _promise(executor) {
- /* istanbul ignore if */
- if (Promise) {
- return new Promise(executor);
- } else {
- var dfd = $.Deferred();
- executor(dfd.resolve, dfd.reject);
- return dfd;
- }
- }
-
-
- /**
- * Дождаться разрешения всех «Обещаний»
- * @param {Promise[]} iterable
- * @returns {Promise}
- * @private
- */
- function _promiseAll(iterable) {
- return Promise
- ? /* istanbul ignore next */ Promise.all(iterable)
- : $.when.apply($, iterable);
- }
-
-
- /**
- * Вернуть разрешенное «Обещание»
- * @param {*} [value]
- * @returns {Promise}
- * @private
- */
- function _resolvePromise(value) {
- return _promise((resolve) => resolve(value));
- }
-
-
- /**
- * Привести значение к «Обещанию»
- * @param {*} value
- * @returns {Promise}
- * @private
- */
- function _cast(value) {
- return value && value.then ? value : _resolvePromise(value);
- }
-
-
-
- /**
- * Object iterator
- * @param {Object|Array} obj
- * @param {Function} iterator
- * @private
- */
- function _each(obj, iterator) {
- if (obj) {
- for (var key in obj) {
- /* istanbul ignore else */
- if (obj.hasOwnProperty(key)) {
- iterator(obj[key], key, obj);
- }
- }
- }
- }
-
-
- /**
- * Глубокое клонирование
- * @param {*} obj
- * @returns {*}
- * @private
- */
- function _deepClone(obj) {
- var result = {};
-
- _each(obj, (val, key) => {
- if (isFn(val)) {
- result[key] = val;
- }
- else if (val instanceof Object) {
- result[key] = _deepClone(val);
- }
- else {
- result[key] = val;
- }
- });
-
- return result;
- }
-
-
- /**
- * Перенос свойств одного объект к другому
- * @param {Object} dst
- * @param {...Object} src
- * @returns {Object}
- * @private
- */
- function _extend(dst, ...src) {
- var i = 0, n = src.length;
- for (; i < n; i++) {
- _each(src[i], (val, key) => {
- dst[key] = val;
- });
- }
-
- return dst;
- }
-
-
- /**
- * Выбрать элементы по заданному селектору
- * @param {String} selector
- * @param {HTMLElement} [ctx]
- * @returns {HTMLElement}
- */
- function _querySelector(selector, ctx) {
- try {
- return (ctx || document).querySelector(selector);
- } catch (err) {
- /* istanbul ignore next */
- return $(selector, ctx)[0];
- }
- }
-
-
- /**
- * Найти элементы по имени
- * @param {HTMLElement} el
- * @param {String} name
- * @returns {NodeList}
- */
- function _getElementsByTagName(el, name) {
- return el.getElementsByTagName(name);
- }
-
-
- /**
- * Присоединить элемент
- * @param {HTMLElement} parent
- * @param {HTMLElement} el
- * @private
- */
- function _appendChild(parent, el) {
- try {
- parent && el && parent.appendChild(el);
- } catch (e) {}
- }
-
-
- /**
- * Удалить элемент
- * @param {HTMLElement} el
- * @private
- */
- function _removeElement(el) {
- /* istanbul ignore else */
- if (el && el.parentNode) {
- el.parentNode.removeChild(el);
- }
- }
-
-
- /**
- * Добавить слуашетеля
- * @param {HTMLElement} el
- * @param {String} name
- * @param {Function} fn
- * @private
- */
- function _addEvent(el, name, fn) {
- var handle = fn.handle = fn.handle || ((evt) => {
- /* istanbul ignore if */
- if (!evt.target) {
- evt.target = evt.srcElement || document;
- }
-
- /* istanbul ignore if */
- if (evt.target.nodeType === 3) {
- evt.target = evt.target.parentNode;
- }
-
- /* istanbul ignore if */
- if (!evt.preventDefault) {
- evt.preventDefault = () => {
- evt.returnValue = false;
- };
- }
-
- /* istanbul ignore if */
- if (!evt.stopPropagation) {
- evt.stopPropagation = () => {
- evt.cancelBubble = true;
- };
- }
-
- fn.call(el, evt);
- });
-
- /* istanbul ignore else */
- if (el.addEventListener) {
- el.addEventListener(name, handle, false);
- } else {
- el.attachEvent('on' + name, handle);
- }
- }
-
-
- /**
- * Удалить слуашетеля
- * @param {HTMLElement} el
- * @param {String} name
- * @param {Function} fn
- * @private
- */
- function _removeEvent(el, name, fn) {
- var handle = fn.handle;
- if (handle) {
- /* istanbul ignore else */
- if (el.removeEventListener) {
- el.removeEventListener(name, handle, false);
- } else {
- el.detachEvent('on' + name, handle);
- }
- }
- }
-
-
- /**
- * Установка или получение css свойства
- * @param {HTMLElement} el
- * @param {Object|String} prop
- * @param {String} [val]
- * @returns {*}
- * @private
- */
- function _css(el, prop, val) {
- if (el && el.style && prop) {
- if (prop instanceof Object) {
- for (var name in prop) {
- _css(el, name, prop[name]);
- }
- }
- else if (val === void 0) {
- /* istanbul ignore else */
- if (document.defaultView && document.defaultView.getComputedStyle) {
- val = document.defaultView.getComputedStyle(el, '');
- }
- else if (el.currentStyle) {
- val = el.currentStyle;
- }
-
- return prop === void 0 ? val : val[prop];
- } else if (_cssHooks[prop]) {
- _cssHooks[prop](el.style, val);
- } else {
- el.style[support[prop] || prop] = val;
- }
- }
- }
-
-
- /**
- * Создание DOM структуры по спецификации
- * @param {String|Object|HTMLElement} [spec]
- * @returns {HTMLElement}
- * @private
- */
- function _buildDOM(spec) {
- if (spec == null) {
- spec = 'div';
- }
-
- if (spec.appendChild) {
- return spec;
- }
- else if (spec.skip) {
- return document.createDocumentFragment();
- }
-
- if (typeof spec === 'string') { // selector
- spec = { tag: spec };
- }
-
- var el,
- children = spec.children,
- selector = R_SELECTOR.exec(spec.tag || '')
- ;
-
- // Это нам больше не нужно
- delete spec.children;
-
- // Разбираем селектор
- spec.tag = selector[1] || 'div';
- spec.id = spec.id || (selector[2] || '').substr(1);
-
- // Собираем className
- selector = (selector[3] || '').split('.');
- selector[0] = (spec.className || '');
- spec.className = selector.join(' ');
-
- // Создаем элемент, теперь можно
- el = document.createElement(spec.tag);
- delete spec.tag;
-
- // Определяем свойсва
- _each(spec, (value, name) => {
- if (value) {
- if (name === 'css') {
- // Определяем CSS свойства
- _css(el, spec.css);
- }
- else if (name === 'text') {
- (value != null) && _appendChild(el, document.createTextNode(value));
- }
- else if (name === 'html') {
- (value != null) && (el.innerHTML = value);
- }
- else if (name === 'ply') {
- // Ply-аттрибут
- el.setAttribute(_plyAttr, value);
- }
- else if (name in el) {
- try {
- el[name] = value;
- } catch (e) {
- el.setAttribute(name, value);
- }
- }
- else if (/^data-/.test(name)) {
- el.setAttribute(name, value);
- }
- }
- });
-
- // Детишки
- if (children && children.appendChild) {
- _appendChild(el, children);
- }
- else {
- _each(children, (spec, selector) => {
- if (spec) {
- if (typeof spec === 'string') {
- spec = { text: spec };
- }
- else if (typeof spec !== 'object') {
- spec = {};
- }
-
- /* istanbul ignore else */
- if (typeof selector === 'string') {
- spec.tag = spec.tag || selector;
- }
-
- _appendChild(el, _buildDOM(spec));
- }
- });
- }
-
- return el;
- }
-
-
- /**
- * Выбрать первый не заполненый элемент
- * @param {HTMLElement} parentNode
- * @private
- */
- function _autoFocus(parentNode) {
- var items = _getElementsByTagName(parentNode, 'input'),
- i = 0,
- n = items.length,
- el,
- element
- ;
-
- for (; i < n; i++) {
- el = items[i];
-
- /* istanbul ignore else */
- if (el.type === 'submit') {
- !element && (element = el);
- }
- else if (!/hidden|check|radio/.test(el.type) && el.value == '') {
- element = el;
- break;
- }
- }
-
- if (!element) {
- element = _getElementsByTagName(parentNode, 'button')[0];
- }
-
- try { element.focus(); } catch (err) { }
- }
-
-
- /**
- * Предзагрузить все изображения
- * @param {HTMLElement} parentNode
- * @returns {Promise}
- * @private
- */
- function _preloadImage(parentNode) {
- _loading(true);
-
- return _promise((resolve) => {
- var items = _getElementsByTagName(parentNode, 'img'),
- i = items.length,
- queue = i,
- img,
- complete = () => {
- /* istanbul ignore else */
- if (--queue <= 0) {
- i = items.length;
- while (i--) {
- img = items[i];
- _removeEvent(img, 'load', complete);
- _removeEvent(img, 'error', complete);
- }
- _loading(false);
- resolve();
- }
- }
- ;
-
- while (i--) {
- img = items[i];
- if (img.complete) {
- queue--;
- } else {
- _addEvent(img, 'load', complete);
- _addEvent(img, 'error', complete);
- }
- }
-
- !queue && complete();
- });
- }
-
/**
* «Загрузка»
@@ -589,6 +76,7 @@
};
+
/**
* Создать слой с контентом
* @param {HTMLElement} contentEl
@@ -619,7 +107,7 @@
children: [options.flags.closeBtn && {
ply: ':close',
tag: '.ply-x',
- text: Ply.lang.cross
+ text: lang.cross
}, {
tag: '.ply-inside',
children: contentEl
@@ -730,41 +218,6 @@
- //
- // Настройки по умолчанию
- //
- var _defaults = {
- zIndex: 10000,
-
- layer: {}, // css
-
- overlay: {
- opacity: .6,
- backgroundColor: 'rgb(0, 0, 0)'
- },
-
- flags: {
- closeBtn: true,
- bodyScroll: false,
- closeByEsc: true,
- closeByOverlay: true,
- hideLayerInStack: true,
- visibleOverlayInStack: false
- },
-
- baseHtml: true,
-
- // Callback's
- init: noop,
- open: noop,
- close: noop,
- destroy: noop,
- callback: noop
- };
-
-
-
-
//
// Основной код
//
@@ -1230,490 +683,37 @@
};
+ //
// Ply-стек
- Ply.stack = {
- _idx: {},
-
-
- /**
- * Последний Ply в стеке
- * @type {Ply}
- */
- last: null,
-
-
- /**
- * Длинна стека
- * @type {Number}
- */
- length: 0,
-
-
- /**
- * Удаить последний ply-слой из стека
- * @param {Event} evt
- * @private
- */
- _pop: function (evt) {
- var layer = Ply.stack.last;
-
- if (evt.keyCode === keys.esc && layer.hasFlag('closeByEsc')) {
- layer.closeBy('esc');
- }
- },
-
-
- /**
- * Добавить ply в стек
- * @param {Ply} layer
- */
- add: function (layer) {
- var idx = array_push.call(this, layer);
-
- this.last = layer;
- this._idx[layer.cid] = idx - 1;
-
- if (idx === 1) {
- _addEvent(document, 'keyup', this._pop);
- }
- },
-
-
- /**
- * Удалить ply из стека
- * @param {Ply} layer
- */
- remove: function (layer) {
- var idx = this._idx[layer.cid];
-
- if (idx >= 0) {
- array_splice.call(this, idx, 1);
-
- delete this._idx[layer.cid];
- this.last = this[this.length-1];
-
- if (!this.last) {
- _removeEvent(document, 'keyup', this._pop);
- }
- }
- }
- };
+ //
+ require('stack');
//
// Эффекты
//
- Ply.effects = {
- // Установки по умолчанию
- defaults: {
- duration: 300,
-
- open: {
- layer: null,
- overlay: null
- },
-
- close: {
- layer: null,
- overlay: null
- }
- },
-
-
- /**
- * Настройти эффекты по умолчанию
- * @static
- * @param {Object} options
- */
- setup: function (options) {
- this.defaults = this.get(options);
- },
-
-
-
- /**
- * Получить опции на основе переданных и по умолчанию
- * @static
- * @param {Object} options опции
- * @returns {Object}
- */
- get: function (options) {
- var defaults = _deepClone(this.defaults);
-
- // Функция разбора выражения `name:duration[args]`
- function parseKey(key) {
- var match = /^([\w_-]+)(?::(\d+%?))?(\[[^\]]+\])?/.exec(key) || [];
- return {
- name: match[1] || key,
- duration: match[2] || null,
- args: JSON.parse(match[3] || 'null') || {}
- };
- }
-
-
- function toObj(obj, key, def) {
- var fx = parseKey(key),
- val = (obj[fx.name] || def || {}),
- duration = (fx.duration || val.duration || obj.duration || options.duration)
- ;
-
- if (typeof val === 'string') {
- val = parseKey(val);
- delete val.args;
- }
-
- if (/%/.test(val.duration)) {
- val.duration = parseInt(val.duration, 10) / 100 * duration;
- }
-
- val.duration = (val.duration || duration) | 0;
-
- return val;
- }
-
-
- if (typeof options === 'string') {
- var fx = parseKey(options);
- options = _deepClone(this[fx.name] || { open: {}, close: {} });
- options.duration = fx.duration || options.duration;
- options.open.args = fx.args[0];
- options.close.args = fx.args[1];
- }
- else if (options instanceof Array) {
- var openFx = parseKey(options[0]),
- closeFx = parseKey(options[1]),
- open = this[openFx.name],
- close = this[closeFx.name]
- ;
-
- options = {
- open: _deepClone(open && open.open || { layer: options[0], overlay: options[0] }),
- close: _deepClone(close && close.close || { layer: options[1], overlay: options[1] })
- };
-
- options.open.args = openFx.args[0];
- options.close.args = closeFx.args[0];
- }
- else if (!(options instanceof Object)) {
- options = {};
- }
-
- options.duration = (options.duration || defaults.duration) | 0;
-
- for (var key in {open: 0, close: 0}) {
- var val = options[key] || defaults[key] || {};
- if (typeof val === 'string') {
- // если это строка, то только layer
- val = { layer: val };
- }
- val.layer = toObj(val, 'layer', defaults[key].layer);
- val.overlay = toObj(val, 'overlay', defaults[key].overlay);
-
- if(val.args === void 0){
- // clean
- delete val.args;
- }
-
- options[key] = val;
- }
-
- return options;
- },
-
-
- /**
- * Применить эффекты
- * @static
- * @param {HTMLElement} el элемент, к которому нужно применить эффект
- * @param {String} name название эффекта
- * @returns {Promise|undefined}
- */
- apply: function (el, name) {
- name = name.split('.');
-
- var effects = this[name[0]], // эффекты open/close
- firstEl = el.firstChild,
- oldStyle = [el.getAttribute('style'), firstEl && firstEl.getAttribute('style')],
- fx,
- effect
- ;
-
-
- if (support.transition && effects && (effect = effects[name[1]]) && (fx = Ply.effects[effect.name])) {
- if (fx['to'] || fx['from']) {
- // Клонируем
- fx = _deepClone(fx);
-
- // Выключаем анимацию
- _css(el, 'transition', 'none');
- _css(firstEl, 'transition', 'none');
-
- // Определяем текущее css-значения
- _each(fx['to'], (val, key, target) => {
- if (val === '&') {
- target[key] = _css(el, key);
- }
- });
-
- // Выставляем initied значения
- if (isFn(fx['from'])) {
- fx['from'](el, effects.args);
- } else if (fx['from']) {
- _css(el, fx['from']);
- }
-
- return _promise((resolve) => {
- // Принудительный repaint/reflow
- fx.width = el.offsetWidth;
-
- // Включаем анимацию
- _css(el, 'transition', 'all ' + effect.duration + 'ms');
- _css(firstEl, 'transition', 'all ' + effect.duration + 'ms');
-
- // Изменяем css
- if (isFn(fx['to'])) {
- fx['to'](el, effects.args);
- }
- else {
- _css(el, fx['to']);
- }
-
- // Ждем завершения анимации
- setTimeout(resolve, effect.duration);
- }).then(() => {
- el.setAttribute('style', oldStyle[0]);
- firstEl && firstEl.setAttribute('style', oldStyle[1]);
- });
- }
- }
-
- return _resolvePromise();
- },
-
-
- //
- // Комбинированный эффекты
- //
-
- 'fade': {
- open: { layer: 'fade-in:80%', overlay: 'fade-in:100%' },
- close: { layer: 'fade-out:60%', overlay: 'fade-out:60%' }
- },
-
- 'scale': {
- open: { layer: 'scale-in', overlay: 'fade-in' },
- close: { layer: 'scale-out', overlay: 'fade-out' }
- },
-
- 'fall': {
- open: { layer: 'fall-in', overlay: 'fade-in' },
- close: { layer: 'fall-out', overlay: 'fade-out' }
- },
-
- 'slide': {
- open: { layer: 'slide-in', overlay: 'fade-in' },
- close: { layer: 'slide-out', overlay: 'fade-out' }
- },
-
- '3d-flip': {
- open: { layer: '3d-flip-in', overlay: 'fade-in' },
- close: { layer: '3d-flip-out', overlay: 'fade-out' }
- },
-
- '3d-sign': {
- open: { layer: '3d-sign-in', overlay: 'fade-in' },
- close: { layer: '3d-sign-out', overlay: 'fade-out' }
- },
-
- 'inner': {
- open: { layer: 'inner-in' },
- close: { layer: 'inner-out' }
- },
-
-
- //
- // Описание эффекта
- //
-
- 'fade-in': {
- 'from': { opacity: 0 },
- 'to': { opacity: '&' }
- },
-
- 'fade-out': {
- 'to': { opacity: 0 }
- },
-
- 'slide-in': {
- 'from': { opacity: 0, transform: 'translateY(20%)' },
- 'to': { opacity: '&', transform: 'translateY(0)' }
- },
-
- 'slide-out': {
- 'to': { opacity: 0, transform: 'translateY(20%)' }
- },
-
- 'fall-in': {
- 'from': { opacity: 0, transform: 'scale(1.3)' },
- 'to': { opacity: '&', transform: 'scale(1)' }
- },
-
- 'fall-out': {
- 'to': { opacity: 0, transform: 'scale(1.3)' }
- },
-
- 'scale-in': {
- 'from': { opacity: 0, transform: 'scale(0.7)' },
- 'to': { opacity: '&', transform: 'scale(1)' }
- },
-
- 'scale-out': {
- 'to': { opacity: 0, 'transform': 'scale(0.7)' }
- },
-
- 'rotate3d': (el, opacity, axis, deg, origin) => {
- _css(el, { perspective: '1300px' });
- _css(el.firstChild, {
- opacity: opacity,
- transform: 'rotate' + axis + '(' + deg + 'deg)',
- transformStyle: 'preserve-3d',
- transformOrigin: origin ? '50% 0' : '50%'
- });
- },
-
- '3d-sign-in': {
- 'from': (el) => {
- Ply.effects.rotate3d(el, 0, 'X', -60, '50% 0');
- },
- 'to': (el) => {
- _css(el.firstChild, { opacity: 1, transform: 'rotateX(0)' });
- }
- },
-
- '3d-sign-out': {
- 'from': (el) => {
- Ply.effects.rotate3d(el, 1, 'X', 0, '50% 0');
- },
- 'to': (el) => {
- _css(el.firstChild, { opacity: 0, transform: 'rotateX(-60deg)' });
- }
- },
-
- '3d-flip-in': {
- 'from': (el, args) => {
- Ply.effects.rotate3d(el, 0, 'Y', args || -70);
- },
- 'to': (el) => {
- _css(el.firstChild, { opacity: 1, transform: 'rotateY(0)' });
- }
- },
-
- '3d-flip-out': {
- 'from': (el) => {
- Ply.effects.rotate3d(el, 1, 'Y', 0);
- },
- 'to': (el, args) => {
- _css(el.firstChild, { opacity: 0, transform: 'rotateY(' + (args || 70) + 'deg)' });
- }
- },
-
- 'inner-in': {
- 'from': (el) => { _css(el, 'transform', 'translateX(100%)'); },
- 'to': (el) => { _css(el, 'transform', 'translateX(0%)'); }
- },
- 'inner-out': {
- 'from': (el) => { _css(el, 'transform', 'translateX(0%)'); },
- 'to': (el) => { _css(el, 'transform', 'translateX(-100%)'); }
- }
- };
+ Ply.effects = require('effects');
+ Ply.effects.set(require('effects.preset'));
//
- // Ply-контекст
+ // Ply.Context
//
+ require('Context');
- /**
- * @class Ply.Context
- * @param {HTMLElement} el
- */
- function Context(el) {
- /**
- * Корневой элемент
- * @type {HTMLElement}
- */
- this.el = el;
- }
-
- Context.fn = Context.prototype = /** @lends Ply.Context */{
- constructor: Context,
-
-
- /**
- * Получить элемент по имени
- * @param {String} name
- * @returns {HTMLElement|undefined}
- */
- getEl: function (name) {
- if (this.el) {
- return _querySelector('[' + _plyAttr + '-name="' + name + '"]', this.el);
- }
- },
-
-
- /**
- * Получить или установить значение по имени
- * @param {String} name
- * @param {String} [value]
- * @returns {String}
- */
- val: function (name, value) {
- var el = typeof name === 'string' ? this.getEl(name) : name;
-
- if (el && (el.value == null)) {
- el = _getElementsByTagName(el, 'input')[0]
- || _getElementsByTagName(el, 'textarea')[0]
- || _getElementsByTagName(el, 'select')[0]
- ;
- }
-
- if (el && value != null) {
- el.value = value;
- }
-
- return el && el.value || "";
- },
-
-
- /**
- * Получить JSON
- * @returns {Object}
- */
- toJSON: function () {
- var items = this.el.querySelectorAll('[' + _plyAttr + '-name]'),
- json = {},
- el,
- i = items.length
- ;
- while (i--) {
- el = items[i];
- json[el.getAttribute(_plyAttr + '-name')] = this.val(el);
- }
- return json;
- }
- };
-
+ //
+ // Ply.ui
+ //
+ require('ui');
+ //
// Export
- Ply.lang = {
- ok: 'OK',
- cancel: 'Cancel',
- cross: '✖'
- };
-
+ //
+ Ply.lang = lang;
Ply.css = _css;
Ply.cssHooks = _cssHooks;
@@ -1735,5 +735,7 @@
removeEvent: _removeEvent
};
+
+
return Ply;
});
diff --git a/src/css.es6 b/src/css.es6
new file mode 100644
index 0000000..a551252
--- /dev/null
+++ b/src/css.es6
@@ -0,0 +1,48 @@
+/*global support, document*/
+
+
+/**
+ * Хуки для css
+ * @type {Object}
+ */
+var _cssHooks = {
+ opacity: !support.opacity && function (style, value) {
+ style.zoom = 1;
+ style.filter = 'alpha(opacity=' + (value * 100) + ')';
+ }
+};
+
+
+
+/**
+ * Установка или получение css свойства
+ * @param {HTMLElement} el
+ * @param {Object|String} prop
+ * @param {String} [val]
+ * @returns {*}
+ * @private
+ */
+function _css(el, prop, val) {
+ if (el && el.style && prop) {
+ if (prop instanceof Object) {
+ for (var name in prop) {
+ _css(el, name, prop[name]);
+ }
+ }
+ else if (val === void 0) {
+ /* istanbul ignore else */
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ val = document.defaultView.getComputedStyle(el, '');
+ }
+ else if (el.currentStyle) {
+ val = el.currentStyle;
+ }
+
+ return prop === void 0 ? val : val[prop];
+ } else if (_cssHooks[prop]) {
+ _cssHooks[prop](el.style, val);
+ } else {
+ el.style[support[prop] || prop] = val;
+ }
+ }
+}
diff --git a/src/defaults.es6 b/src/defaults.es6
new file mode 100644
index 0000000..01c26b5
--- /dev/null
+++ b/src/defaults.es6
@@ -0,0 +1,28 @@
+module.exports = {
+ zIndex: 10000,
+
+ layer: {}, // css
+
+ overlay: {
+ opacity: .6,
+ backgroundColor: 'rgb(0, 0, 0)'
+ },
+
+ flags: {
+ closeBtn: true,
+ bodyScroll: false,
+ closeByEsc: true,
+ closeByOverlay: true,
+ hideLayerInStack: true,
+ visibleOverlayInStack: false
+ },
+
+ baseHtml: true,
+
+ // Callback's
+ init: noop,
+ open: noop,
+ close: noop,
+ destroy: noop,
+ callback: noop
+};
diff --git a/src/dom.es6 b/src/dom.es6
new file mode 100644
index 0000000..8217c1b
--- /dev/null
+++ b/src/dom.es6
@@ -0,0 +1,312 @@
+//
+// Работа с DOM
+//
+
+
+var $ = require('jquery');
+
+
+/**
+ * Разбор строки "tag#id.foo.bar"
+ * @const {RegExp}
+ */
+var R_SELECTOR = /^(\w+)?(#\w+)?((?:\.[\w_-]+)*)/i;
+
+
+
+/**
+ * Выбрать элементы по заданному селектору
+ * @param {String} selector
+ * @param {HTMLElement} [ctx]
+ * @returns {HTMLElement}
+ */
+function _querySelector(selector, ctx) {
+ try {
+ return (ctx || document).querySelector(selector);
+ } catch (err) {
+ /* istanbul ignore next */
+ return $(selector, ctx)[0];
+ }
+}
+
+
+/**
+ * Найти элементы по имени
+ * @param {HTMLElement} el
+ * @param {String} name
+ * @returns {NodeList}
+ */
+function _getElementsByTagName(el, name) {
+ return el.getElementsByTagName(name);
+}
+
+
+/**
+ * Присоединить элемент
+ * @param {HTMLElement} parent
+ * @param {HTMLElement} el
+ * @private
+ */
+function _appendChild(parent, el) {
+ try {
+ parent && el && parent.appendChild(el);
+ } catch (e) {}
+}
+
+
+/**
+ * Удалить элемент
+ * @param {HTMLElement} el
+ * @private
+ */
+function _removeElement(el) {
+ /* istanbul ignore else */
+ if (el && el.parentNode) {
+ el.parentNode.removeChild(el);
+ }
+}
+
+
+/**
+ * Добавить слуашетеля
+ * @param {HTMLElement} el
+ * @param {String} name
+ * @param {Function} fn
+ * @private
+ */
+function _addEvent(el, name, fn) {
+ var handle = fn.handle = fn.handle || ((evt) => {
+ /* istanbul ignore if */
+ if (!evt.target) {
+ evt.target = evt.srcElement || document;
+ }
+
+ /* istanbul ignore if */
+ if (evt.target.nodeType === 3) {
+ evt.target = evt.target.parentNode;
+ }
+
+ /* istanbul ignore if */
+ if (!evt.preventDefault) {
+ evt.preventDefault = () => {
+ evt.returnValue = false;
+ };
+ }
+
+ /* istanbul ignore if */
+ if (!evt.stopPropagation) {
+ evt.stopPropagation = () => {
+ evt.cancelBubble = true;
+ };
+ }
+
+ fn.call(el, evt);
+ });
+
+ /* istanbul ignore else */
+ if (el.addEventListener) {
+ el.addEventListener(name, handle, false);
+ } else {
+ el.attachEvent('on' + name, handle);
+ }
+}
+
+
+/**
+ * Удалить слуашетеля
+ * @param {HTMLElement} el
+ * @param {String} name
+ * @param {Function} fn
+ * @private
+ */
+function _removeEvent(el, name, fn) {
+ var handle = fn.handle;
+ if (handle) {
+ /* istanbul ignore else */
+ if (el.removeEventListener) {
+ el.removeEventListener(name, handle, false);
+ } else {
+ el.detachEvent('on' + name, handle);
+ }
+ }
+}
+
+
+
+/**
+ * Создание DOM структуры по спецификации
+ * @param {String|Object|HTMLElement} [spec]
+ * @returns {HTMLElement}
+ * @private
+ */
+function _buildDOM(spec) {
+ if (spec == null) {
+ spec = 'div';
+ }
+
+ if (spec.appendChild) {
+ return spec;
+ }
+ else if (spec.skip) {
+ return document.createDocumentFragment();
+ }
+
+ if (typeof spec === 'string') { // selector
+ spec = { tag: spec };
+ }
+
+ var el,
+ children = spec.children,
+ selector = R_SELECTOR.exec(spec.tag || '')
+ ;
+
+ // Это нам больше не нужно
+ delete spec.children;
+
+ // Разбираем селектор
+ spec.tag = selector[1] || 'div';
+ spec.id = spec.id || (selector[2] || '').substr(1);
+
+ // Собираем className
+ selector = (selector[3] || '').split('.');
+ selector[0] = (spec.className || '');
+ spec.className = selector.join(' ');
+
+ // Создаем элемент, теперь можно
+ el = document.createElement(spec.tag);
+ delete spec.tag;
+
+ // Определяем свойсва
+ _each(spec, (value, name) => {
+ if (value) {
+ if (name === 'css') {
+ // Определяем CSS свойства
+ _css(el, spec.css);
+ }
+ else if (name === 'text') {
+ (value != null) && _appendChild(el, document.createTextNode(value));
+ }
+ else if (name === 'html') {
+ (value != null) && (el.innerHTML = value);
+ }
+ else if (name === 'ply') {
+ // Ply-аттрибут
+ el.setAttribute(_plyAttr, value);
+ }
+ else if (name in el) {
+ try {
+ el[name] = value;
+ } catch (e) {
+ el.setAttribute(name, value);
+ }
+ }
+ else if (/^data-/.test(name)) {
+ el.setAttribute(name, value);
+ }
+ }
+ });
+
+ // Детишки
+ if (children && children.appendChild) {
+ _appendChild(el, children);
+ }
+ else {
+ _each(children, (spec, selector) => {
+ if (spec) {
+ if (typeof spec === 'string') {
+ spec = { text: spec };
+ }
+ else if (typeof spec !== 'object') {
+ spec = {};
+ }
+
+ /* istanbul ignore else */
+ if (typeof selector === 'string') {
+ spec.tag = spec.tag || selector;
+ }
+
+ _appendChild(el, _buildDOM(spec));
+ }
+ });
+ }
+
+ return el;
+}
+
+
+/**
+ * Выбрать первый не заполненый элемент
+ * @param {HTMLElement} parentNode
+ * @private
+ */
+function _autoFocus(parentNode) {
+ var items = _getElementsByTagName(parentNode, 'input'),
+ i = 0,
+ n = items.length,
+ el,
+ element
+ ;
+
+ for (; i < n; i++) {
+ el = items[i];
+
+ /* istanbul ignore else */
+ if (el.type === 'submit') {
+ !element && (element = el);
+ }
+ else if (!/hidden|check|radio/.test(el.type) && el.value == '') {
+ element = el;
+ break;
+ }
+ }
+
+ if (!element) {
+ element = _getElementsByTagName(parentNode, 'button')[0];
+ }
+
+ try { element.focus(); } catch (err) { }
+}
+
+
+/**
+ * Предзагрузить все изображения
+ * @param {HTMLElement} parentNode
+ * @returns {Promise}
+ * @private
+ */
+function _preloadImage(parentNode) {
+ _loading(true);
+
+ return _promise((resolve) => {
+ var items = _getElementsByTagName(parentNode, 'img'),
+ i = items.length,
+ queue = i,
+ img,
+ complete = () => {
+ /* istanbul ignore else */
+ if (--queue <= 0) {
+ i = items.length;
+ while (i--) {
+ img = items[i];
+ _removeEvent(img, 'load', complete);
+ _removeEvent(img, 'error', complete);
+ }
+ _loading(false);
+ resolve();
+ }
+ }
+ ;
+
+ while (i--) {
+ img = items[i];
+ if (img.complete) {
+ queue--;
+ } else {
+ _addEvent(img, 'load', complete);
+ _addEvent(img, 'error', complete);
+ }
+ }
+
+ !queue && complete();
+ });
+}
diff --git a/src/effects.es6 b/src/effects.es6
new file mode 100644
index 0000000..c19a82a
--- /dev/null
+++ b/src/effects.es6
@@ -0,0 +1,191 @@
+module.exports = {
+ // Установки по умолчанию
+ defaults: {
+ duration: 300,
+
+ open: {
+ layer: null,
+ overlay: null
+ },
+
+ close: {
+ layer: null,
+ overlay: null
+ }
+ },
+
+
+ /**
+ * Настройти эффекты по умолчанию
+ * @static
+ * @param {Object} options
+ */
+ setup: function (options) {
+ this.defaults = this.get(options);
+ },
+
+
+ set: function (desc) {
+ _extend(this, desc);
+ },
+
+
+ /**
+ * Получить опции на основе переданных и по умолчанию
+ * @static
+ * @param {Object} options опции
+ * @returns {Object}
+ */
+ get: function (options) {
+ var defaults = _deepClone(this.defaults);
+
+ // Функция разбора выражения `name:duration[args]`
+ function parseKey(key) {
+ var match = /^([\w_-]+)(?::(\d+%?))?(\[[^\]]+\])?/.exec(key) || [];
+ return {
+ name: match[1] || key,
+ duration: match[2] || null,
+ args: JSON.parse(match[3] || 'null') || {}
+ };
+ }
+
+
+ function toObj(obj, key, def) {
+ var fx = parseKey(key),
+ val = (obj[fx.name] || def || {}),
+ duration = (fx.duration || val.duration || obj.duration || options.duration)
+ ;
+
+ if (typeof val === 'string') {
+ val = parseKey(val);
+ delete val.args;
+ }
+
+ if (/%/.test(val.duration)) {
+ val.duration = parseInt(val.duration, 10) / 100 * duration;
+ }
+
+ val.duration = (val.duration || duration) | 0;
+
+ return val;
+ }
+
+
+ if (typeof options === 'string') {
+ var fx = parseKey(options);
+ options = _deepClone(this[fx.name] || { open: {}, close: {} });
+ options.duration = fx.duration || options.duration;
+ options.open.args = fx.args[0];
+ options.close.args = fx.args[1];
+ }
+ else if (options instanceof Array) {
+ var openFx = parseKey(options[0]),
+ closeFx = parseKey(options[1]),
+ open = this[openFx.name],
+ close = this[closeFx.name]
+ ;
+
+ options = {
+ open: _deepClone(open && open.open || { layer: options[0], overlay: options[0] }),
+ close: _deepClone(close && close.close || { layer: options[1], overlay: options[1] })
+ };
+
+ options.open.args = openFx.args[0];
+ options.close.args = closeFx.args[0];
+ }
+ else if (!(options instanceof Object)) {
+ options = {};
+ }
+
+ options.duration = (options.duration || defaults.duration) | 0;
+
+ for (var key in {open: 0, close: 0}) {
+ var val = options[key] || defaults[key] || {};
+ if (typeof val === 'string') {
+ // если это строка, то только layer
+ val = { layer: val };
+ }
+ val.layer = toObj(val, 'layer', defaults[key].layer);
+ val.overlay = toObj(val, 'overlay', defaults[key].overlay);
+
+ if(val.args === void 0){
+ // clean
+ delete val.args;
+ }
+
+ options[key] = val;
+ }
+
+ return options;
+ },
+
+
+ /**
+ * Применить эффекты
+ * @static
+ * @param {HTMLElement} el элемент, к которому нужно применить эффект
+ * @param {String} name название эффекта
+ * @returns {Promise|undefined}
+ */
+ apply: function (el, name) {
+ name = name.split('.');
+
+ var effects = this[name[0]], // эффекты open/close
+ firstEl = el.firstChild,
+ oldStyle = [el.getAttribute('style'), firstEl && firstEl.getAttribute('style')],
+ fx,
+ effect
+ ;
+
+
+ if (support.transition && effects && (effect = effects[name[1]]) && (fx = Ply.effects[effect.name])) {
+ if (fx['to'] || fx['from']) {
+ // Клонируем
+ fx = _deepClone(fx);
+
+ // Выключаем анимацию
+ _css(el, 'transition', 'none');
+ _css(firstEl, 'transition', 'none');
+
+ // Определяем текущее css-значения
+ _each(fx['to'], (val, key, target) => {
+ if (val === '&') {
+ target[key] = _css(el, key);
+ }
+ });
+
+ // Выставляем initied значения
+ if (isFn(fx['from'])) {
+ fx['from'](el, effects.args);
+ } else if (fx['from']) {
+ _css(el, fx['from']);
+ }
+
+ return _promise((resolve) => {
+ // Принудительный repaint/reflow
+ fx.width = el.offsetWidth;
+
+ // Включаем анимацию
+ _css(el, 'transition', 'all ' + effect.duration + 'ms');
+ _css(firstEl, 'transition', 'all ' + effect.duration + 'ms');
+
+ // Изменяем css
+ if (isFn(fx['to'])) {
+ fx['to'](el, effects.args);
+ }
+ else {
+ _css(el, fx['to']);
+ }
+
+ // Ждем завершения анимации
+ setTimeout(resolve, effect.duration);
+ }).then(() => {
+ el.setAttribute('style', oldStyle[0]);
+ firstEl && firstEl.setAttribute('style', oldStyle[1]);
+ });
+ }
+ }
+
+ return _resolvePromise();
+ }
+};
diff --git a/src/effects.preset.es6 b/src/effects.preset.es6
new file mode 100644
index 0000000..d164dec
--- /dev/null
+++ b/src/effects.preset.es6
@@ -0,0 +1,137 @@
+module.exports = {
+ //
+ // Комбинированный эффекты
+ //
+
+ 'fade': {
+ open: { layer: 'fade-in:80%', overlay: 'fade-in:100%' },
+ close: { layer: 'fade-out:60%', overlay: 'fade-out:60%' }
+ },
+
+ 'scale': {
+ open: { layer: 'scale-in', overlay: 'fade-in' },
+ close: { layer: 'scale-out', overlay: 'fade-out' }
+ },
+
+ 'fall': {
+ open: { layer: 'fall-in', overlay: 'fade-in' },
+ close: { layer: 'fall-out', overlay: 'fade-out' }
+ },
+
+ 'slide': {
+ open: { layer: 'slide-in', overlay: 'fade-in' },
+ close: { layer: 'slide-out', overlay: 'fade-out' }
+ },
+
+ '3d-flip': {
+ open: { layer: '3d-flip-in', overlay: 'fade-in' },
+ close: { layer: '3d-flip-out', overlay: 'fade-out' }
+ },
+
+ '3d-sign': {
+ open: { layer: '3d-sign-in', overlay: 'fade-in' },
+ close: { layer: '3d-sign-out', overlay: 'fade-out' }
+ },
+
+ 'inner': {
+ open: { layer: 'inner-in' },
+ close: { layer: 'inner-out' }
+ },
+
+
+ //
+ // Описание эффекта
+ //
+
+ 'fade-in': {
+ 'from': { opacity: 0 },
+ 'to': { opacity: '&' }
+ },
+
+ 'fade-out': {
+ 'to': { opacity: 0 }
+ },
+
+ 'slide-in': {
+ 'from': { opacity: 0, transform: 'translateY(20%)' },
+ 'to': { opacity: '&', transform: 'translateY(0)' }
+ },
+
+ 'slide-out': {
+ 'to': { opacity: 0, transform: 'translateY(20%)' }
+ },
+
+ 'fall-in': {
+ 'from': { opacity: 0, transform: 'scale(1.3)' },
+ 'to': { opacity: '&', transform: 'scale(1)' }
+ },
+
+ 'fall-out': {
+ 'to': { opacity: 0, transform: 'scale(1.3)' }
+ },
+
+ 'scale-in': {
+ 'from': { opacity: 0, transform: 'scale(0.7)' },
+ 'to': { opacity: '&', transform: 'scale(1)' }
+ },
+
+ 'scale-out': {
+ 'to': { opacity: 0, 'transform': 'scale(0.7)' }
+ },
+
+ 'rotate3d': (el, opacity, axis, deg, origin) => {
+ _css(el, { perspective: '1300px' });
+ _css(el.firstChild, {
+ opacity: opacity,
+ transform: 'rotate' + axis + '(' + deg + 'deg)',
+ transformStyle: 'preserve-3d',
+ transformOrigin: origin ? '50% 0' : '50%'
+ });
+ },
+
+ '3d-sign-in': {
+ 'from': (el) => {
+ Ply.effects.rotate3d(el, 0, 'X', -60, '50% 0');
+ },
+ 'to': (el) => {
+ _css(el.firstChild, { opacity: 1, transform: 'rotateX(0)' });
+ }
+ },
+
+ '3d-sign-out': {
+ 'from': (el) => {
+ Ply.effects.rotate3d(el, 1, 'X', 0, '50% 0');
+ },
+ 'to': (el) => {
+ _css(el.firstChild, { opacity: 0, transform: 'rotateX(-60deg)' });
+ }
+ },
+
+ '3d-flip-in': {
+ 'from': (el, args) => {
+ Ply.effects.rotate3d(el, 0, 'Y', args || -70);
+ },
+ 'to': (el) => {
+ _css(el.firstChild, { opacity: 1, transform: 'rotateY(0)' });
+ }
+ },
+
+ '3d-flip-out': {
+ 'from': (el) => {
+ Ply.effects.rotate3d(el, 1, 'Y', 0);
+ },
+ 'to': (el, args) => {
+ _css(el.firstChild, { opacity: 0, transform: 'rotateY(' + (args || 70) + 'deg)' });
+ }
+ },
+
+ 'inner-in': {
+ 'from': (el) => { _css(el, 'transform', 'translateX(100%)'); },
+ 'to': (el) => { _css(el, 'transform', 'translateX(0%)'); }
+ },
+
+ 'inner-out': {
+ 'from': (el) => { _css(el, 'transform', 'translateX(0%)'); },
+ 'to': (el) => { _css(el, 'transform', 'translateX(-100%)'); }
+ }
+};
diff --git a/src/jquery.es6 b/src/jquery.es6
new file mode 100644
index 0000000..96603eb
--- /dev/null
+++ b/src/jquery.es6
@@ -0,0 +1,5 @@
+module.exports = window.jQuery
+ || /* istanbul ignore next */ window.Zepto
+ || /* istanbul ignore next */ window.ender
+ || /* istanbul ignore next */ window.$
+;
diff --git a/src/keys.es6 b/src/keys.es6
new file mode 100644
index 0000000..04e4945
--- /dev/null
+++ b/src/keys.es6
@@ -0,0 +1,7 @@
+/**
+ * Коды кнопок
+ * @type {Object}
+ */
+module.exports = {
+ esc: 27
+};
diff --git a/src/lang.es6 b/src/lang.es6
new file mode 100644
index 0000000..8a08aa0
--- /dev/null
+++ b/src/lang.es6
@@ -0,0 +1,5 @@
+module.exports = {
+ ok: 'OK',
+ cancel: 'Cancel',
+ cross: '✖'
+};
diff --git a/src/stack.es6 b/src/stack.es6
new file mode 100644
index 0000000..9dc1348
--- /dev/null
+++ b/src/stack.es6
@@ -0,0 +1,73 @@
+var array_core = [],
+ array_push = array_core.push,
+ array_splice = array_core.splice
+;
+
+
+Ply.stack = {
+ _idx: {},
+
+
+ /**
+ * Последний Ply в стеке
+ * @type {Ply}
+ */
+ last: null,
+
+
+ /**
+ * Длинна стека
+ * @type {Number}
+ */
+ length: 0,
+
+
+ /**
+ * Удаить последний ply-слой из стека
+ * @param {Event} evt
+ * @private
+ */
+ _pop: function (evt) {
+ var layer = Ply.stack.last;
+
+ if (evt.keyCode === keys.esc && layer.hasFlag('closeByEsc')) {
+ layer.closeBy('esc');
+ }
+ },
+
+
+ /**
+ * Добавить ply в стек
+ * @param {Ply} layer
+ */
+ add: function (layer) {
+ var idx = array_push.call(this, layer);
+
+ this.last = layer;
+ this._idx[layer.cid] = idx - 1;
+
+ if (idx === 1) {
+ _addEvent(document, 'keyup', this._pop);
+ }
+ },
+
+
+ /**
+ * Удалить ply из стека
+ * @param {Ply} layer
+ */
+ remove: function (layer) {
+ var idx = this._idx[layer.cid];
+
+ if (idx >= 0) {
+ array_splice.call(this, idx, 1);
+
+ delete this._idx[layer.cid];
+ this.last = this[this.length-1];
+
+ if (!this.last) {
+ _removeEvent(document, 'keyup', this._pop);
+ }
+ }
+ }
+};
diff --git a/src/support.es6 b/src/support.es6
new file mode 100644
index 0000000..a73c7e8
--- /dev/null
+++ b/src/support.es6
@@ -0,0 +1,25 @@
+/*global _buildDOM*/
+module.exports = (() => {
+ var props = {},
+ style = document.createElement('div').style,
+ names = 'opacity transition transform perspective transformStyle transformOrigin backfaceVisibility'.split(' '),
+ prefix = ['Webkit', 'Moz', 'O', 'MS']
+ ;
+
+ _each(names, (name, i) => {
+ props[name] = (name in style) && /* istanbul ignore next */ name;
+
+ /* istanbul ignore else */
+ if (!props[name]) {
+ for (i = 0; i < 4; i++) {
+ var pname = prefix[i] + name.charAt(0).toUpperCase() + name.substr(1);
+ /* istanbul ignore else */
+ if (props[name] = (pname in style) && pname) {
+ break;
+ }
+ }
+ }
+ });
+
+ return props;
+})();
diff --git a/src/Ply.ui.es6 b/src/ui.es6
similarity index 93%
rename from src/Ply.ui.es6
rename to src/ui.es6
index 4fa0d7c..c044e92 100644
--- a/src/Ply.ui.es6
+++ b/src/ui.es6
@@ -1,35 +1,23 @@
/*global define, Ply */
-((factory) => {
- factory(Ply);
-})((Ply) => {
+;;;(Ply => {
'use strict';
- var _plyAttr = Ply.attrName,
- noop = Ply.noop,
- _each = Ply.each,
- _extend = Ply.extend,
- _promise = Ply.promise,
- _buildDOM = Ply.dom.build,
- _appendChild = Ply.dom.append,
- _lang = Ply.lang,
-
- _toBlock = (block, name) => {
- if (block == null) {
- return { skip: true };
- }
-
- if (typeof block === 'string') {
- block = { text: block };
- }
+ function _toBlock(block, name) {
+ if (block == null) {
+ return { skip: true };
+ }
- if (typeof block === 'object') {
- block.name = block.name || name;
- }
+ if (typeof block === 'string') {
+ block = { text: block };
+ }
- return block;
+ if (typeof block === 'object') {
+ block.name = block.name || name;
}
- ;
+
+ return block;
+ }
@@ -143,7 +131,7 @@
return {
ply: ':ok',
tag: 'button.ply-ctrl.ply-ok',
- text: data === true ? _lang.ok : data
+ text: data === true ? lang.ok : data
};
});
@@ -154,7 +142,7 @@
ply: ':close',
tag: 'button.ply-ctrl.ply-cancel',
type: 'reset',
- text: data === true ? _lang.cancel : data
+ text: data === true ? lang.cancel : data
};
});
@@ -417,4 +405,4 @@
// Export
Ply.ui = ui;
Ply.factory = factory;
-});
+;;;})();
diff --git a/src/utils.es6 b/src/utils.es6
new file mode 100644
index 0000000..d282c1e
--- /dev/null
+++ b/src/utils.es6
@@ -0,0 +1,133 @@
+//
+// Вспомогательные методы
+//
+
+var Promise = Deferred || window.Promise;
+
+
+
+
+/**
+ * Функция?
+ * @param {*} fn
+ * @returns {Boolean}
+ */
+function isFn(fn) {
+ return typeof fn === 'function';
+}
+
+
+/**
+ * Создать «Обещание»
+ * @param {Function} executor
+ * @returns {Promise}
+ * @private
+ */
+function _promise(executor) {
+ /* istanbul ignore if */
+ if (Promise) {
+ return new Promise(executor);
+ } else {
+ var dfd = $.Deferred();
+ executor(dfd.resolve, dfd.reject);
+ return dfd;
+ }
+}
+
+
+/**
+ * Дождаться разрешения всех «Обещаний»
+ * @param {Promise[]} iterable
+ * @returns {Promise}
+ * @private
+ */
+function _promiseAll(iterable) {
+ return Promise
+ ? /* istanbul ignore next */ Promise.all(iterable)
+ : $.when.apply($, iterable);
+}
+
+
+/**
+ * Вернуть разрешенное «Обещание»
+ * @param {*} [value]
+ * @returns {Promise}
+ * @private
+ */
+function _resolvePromise(value) {
+ return _promise((resolve) => resolve(value));
+}
+
+
+/**
+ * Привести значение к «Обещанию»
+ * @param {*} value
+ * @returns {Promise}
+ * @private
+ */
+function _cast(value) {
+ return value && value.then ? value : _resolvePromise(value);
+}
+
+
+
+/**
+ * Object iterator
+ * @param {Object|Array} obj
+ * @param {Function} iterator
+ * @private
+ */
+function _each(obj, iterator) {
+ if (obj) {
+ for (var key in obj) {
+ /* istanbul ignore else */
+ if (obj.hasOwnProperty(key)) {
+ iterator(obj[key], key, obj);
+ }
+ }
+ }
+}
+
+
+/**
+ * Глубокое клонирование
+ * @param {*} obj
+ * @returns {*}
+ * @private
+ */
+function _deepClone(obj) {
+ var result = {};
+
+ _each(obj, (val, key) => {
+ if (isFn(val)) {
+ result[key] = val;
+ }
+ else if (val instanceof Object) {
+ result[key] = _deepClone(val);
+ }
+ else {
+ result[key] = val;
+ }
+ });
+
+ return result;
+}
+
+
+/**
+ * Перенос свойств одного объект к другому
+ * @param {Object} dst
+ * @param {...Object} src
+ * @returns {Object}
+ * @private
+ */
+function _extend(dst, ...src) {
+ var i = 0, n = src.length;
+ for (; i < n; i++) {
+ _each(src[i], (val, key) => {
+ dst[key] = val;
+ });
+ }
+
+ return dst;
+}
diff --git a/tests/Ply.ui.tests.js b/tests/Ply.ui.tests.js
index 4386b78..7f8213e 100644
--- a/tests/Ply.ui.tests.js
+++ b/tests/Ply.ui.tests.js
@@ -101,7 +101,7 @@
setTimeout(function () {
var el = ui.layer.layerEl;
(el.getElementsByTagName('button')[1] || el.getElementsByTagName('button')[0]).click();
- }, 50);
+ }, 100);
}
}).then(function () {
equal(log.join('\n'), [
diff --git a/tests/index.html b/tests/index.html
index 129ef67..7b8d193 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -126,7 +126,6 @@
-