From f3e5a041d1ebc06e3674c298d97b2ce8e1adf1c3 Mon Sep 17 00:00:00 2001 From: wolfcode <37436228+wolf-leo@users.noreply.github.com> Date: Mon, 11 Nov 2024 11:22:47 +0800 Subject: [PATCH] feat(ueditor): add custom upload service and other enhancements - Add custom upload service support - Implement server response preparation function - Enable loading config from server - Add content import button to toolbar - Update image alignment buttons order - Add tip error function for better error handling - Remove unused comments and simplify configuration options --- .../third-party/webuploader/webuploader.js | 10182 ++- public/static/plugs/ueditor/ueditor.all.js | 67053 ++++++++-------- public/static/plugs/ueditor/ueditor.config.js | 106 +- 3 files changed, 45541 insertions(+), 31800 deletions(-) diff --git a/public/static/plugs/ueditor/third-party/webuploader/webuploader.js b/public/static/plugs/ueditor/third-party/webuploader/webuploader.js index 50d95ce..4d552a3 100644 --- a/public/static/plugs/ueditor/third-party/webuploader/webuploader.js +++ b/public/static/plugs/ueditor/third-party/webuploader/webuploader.js @@ -1,4 +1,10178 @@ -/* WebUploader 1.0.0 */!function(a,b){var c,d={},e=function(a,b){var c,d,e;if("string"==typeof a)return h(a);for(c=[],d=a.length,e=0;d>e;e++)c.push(h(a[e]));return b.apply(null,c)},f=function(a,b,c){2===arguments.length&&(c=b,b=null),e(b||[],function(){g(a,c,arguments)})},g=function(a,b,c){var f,g={exports:b};"function"==typeof b&&(c.length||(c=[e,g.exports,g]),f=b.apply(null,c),void 0!==f&&(g.exports=f)),d[a]=g.exports},h=function(b){var c=d[b]||a[b];if(!c)throw new Error("`"+b+"` is undefined");return c},i=function(a){var b,c,e,f,g,h;h=function(a){return a&&a.charAt(0).toUpperCase()+a.substr(1)};for(b in d)if(c=a,d.hasOwnProperty(b)){for(e=b.split("/"),g=h(e.pop());f=h(e.shift());)c[f]=c[f]||{},c=c[f];c[g]=d[b]}return a},j=function(c){return a.__dollar=c,i(b(a,f,e))};"object"==typeof module&&"object"==typeof module.exports?module.exports=j():"function"==typeof define&&define.amd?define(["jquery"],j):(c=a.WebUploader,a.WebUploader=j(),a.WebUploader.noConflict=function(){a.WebUploader=c})}(window,function(a,b,c){return b("dollar-third",[],function(){var b=a.require,c=a.__dollar||a.jQuery||a.Zepto||b("jquery")||b("zepto");if(!c)throw new Error("jQuery or Zepto not found!");return c}),b("dollar",["dollar-third"],function(a){return a}),b("promise-third",["dollar"],function(a){return{Deferred:a.Deferred,when:a.when,isPromise:function(a){return a&&"function"==typeof a.then}}}),b("promise",["promise-third"],function(a){return a}),b("base",["dollar","promise"],function(b,c){function d(a){return function(){return h.apply(a,arguments)}}function e(a,b){return function(){return a.apply(b,arguments)}}function f(a){var b;return Object.create?Object.create(a):(b=function(){},b.prototype=a,new b)}var g=function(){},h=Function.call;return{version:"1.0.0",$:b,Deferred:c.Deferred,isPromise:c.isPromise,when:c.when,browser:function(a){var b={},c=a.match(/WebKit\/([\d.]+)/),d=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),e=a.match(/MSIE\s([\d\.]+)/)||a.match(/(?:trident)(?:.*rv:([\w.]+))?/i),f=a.match(/Firefox\/([\d.]+)/),g=a.match(/Safari\/([\d.]+)/),h=a.match(/OPR\/([\d.]+)/);return c&&(b.webkit=parseFloat(c[1])),d&&(b.chrome=parseFloat(d[1])),e&&(b.ie=parseFloat(e[1])),f&&(b.firefox=parseFloat(f[1])),g&&(b.safari=parseFloat(g[1])),h&&(b.opera=parseFloat(h[1])),b}(navigator.userAgent),os:function(a){var b={},c=a.match(/(?:Android);?[\s\/]+([\d.]+)?/),d=a.match(/(?:iPad|iPod|iPhone).*OS\s([\d_]+)/);return c&&(b.android=parseFloat(c[1])),d&&(b.ios=parseFloat(d[1].replace(/_/g,"."))),b}(navigator.userAgent),inherits:function(a,c,d){var e;return"function"==typeof c?(e=c,c=null):e=c&&c.hasOwnProperty("constructor")?c.constructor:function(){return a.apply(this,arguments)},b.extend(!0,e,a,d||{}),e.__super__=a.prototype,e.prototype=f(a.prototype),c&&b.extend(!0,e.prototype,c),e},noop:g,bindFn:e,log:function(){return a.console?e(console.log,console):g}(),nextTick:function(){return function(a){setTimeout(a,1)}}(),slice:d([].slice),guid:function(){var a=0;return function(b){for(var c=(+new Date).toString(32),d=0;5>d;d++)c+=Math.floor(65535*Math.random()).toString(32);return(b||"wu_")+c+(a++).toString(32)}}(),formatSize:function(a,b,c){var d;for(c=c||["B","K","M","G","TB"];(d=c.shift())&&a>1024;)a/=1024;return("B"===d?a:a.toFixed(b||2))+d}}}),b("mediator",["base"],function(a){function b(a,b,c,d){return f.grep(a,function(a){return!(!a||b&&a.e!==b||c&&a.cb!==c&&a.cb._cb!==c||d&&a.ctx!==d)})}function c(a,b,c){f.each((a||"").split(h),function(a,d){c(d,b)})}function d(a,b){for(var c,d=!1,e=-1,f=a.length;++e1?(d.isPlainObject(b)&&d.isPlainObject(c[a])?d.extend(c[a],b):c[a]=b,void 0):a?c[a]:c},getStats:function(){var a=this.request("get-stats");return a?{successNum:a.numOfSuccess,progressNum:a.numOfProgress,cancelNum:a.numOfCancel,invalidNum:a.numOfInvalid,uploadFailNum:a.numOfUploadFailed,queueNum:a.numOfQueue,interruptNum:a.numOfInterrupt}:{}},trigger:function(a){var c=[].slice.call(arguments,1),e=this.options,f="on"+a.substring(0,1).toUpperCase()+a.substring(1);return b.trigger.apply(this,arguments)===!1||d.isFunction(e[f])&&e[f].apply(this,c)===!1||d.isFunction(this[f])&&this[f].apply(this,c)===!1||b.trigger.apply(b,[this,a].concat(c))===!1?!1:!0},destroy:function(){this.request("destroy",arguments),this.off()},request:a.noop}),a.create=c.create=function(a){return new c(a)},a.Uploader=c,c}),b("runtime/runtime",["base","mediator"],function(a,b){function c(b){this.options=d.extend({container:document.body},b),this.uid=a.guid("rt_")}var d=a.$,e={},f=function(a){for(var b in a)if(a.hasOwnProperty(b))return b;return null};return d.extend(c.prototype,{getContainer:function(){var a,b,c=this.options;return this._container?this._container:(a=d(c.container||document.body),b=d(document.createElement("div")),b.attr("id","rt_"+this.uid),b.css({position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),a.append(b),a.addClass("webuploader-container"),this._container=b,this._parent=a,b)},init:a.noop,exec:a.noop,destroy:function(){this._container&&this._container.remove(),this._parent&&this._parent.removeClass("webuploader-container"),this.off()}}),c.orders="html5,flash",c.addRuntime=function(a,b){e[a]=b},c.hasRuntime=function(a){return!!(a?e[a]:f(e))},c.create=function(a,b){var g,h;if(b=b||c.orders,d.each(b.split(/\s*,\s*/g),function(){return e[this]?(g=this,!1):void 0}),g=g||f(e),!g)throw new Error("Runtime Error");return h=new e[g](a)},b.installTo(c.prototype),c}),b("runtime/client",["base","mediator","runtime/runtime"],function(a,b,c){function d(b,d){var f,g=a.Deferred();this.uid=a.guid("client_"),this.runtimeReady=function(a){return g.done(a)},this.connectRuntime=function(b,h){if(f)throw new Error("already connected!");return g.done(h),"string"==typeof b&&e.get(b)&&(f=e.get(b)),f=f||e.get(null,d),f?(a.$.extend(f.options,b),f.__promise.then(g.resolve),f.__client++):(f=c.create(b,b.runtimeOrder),f.__promise=g.promise(),f.once("ready",g.resolve),f.init(),e.add(f),f.__client=1),d&&(f.__standalone=d),f},this.getRuntime=function(){return f},this.disconnectRuntime=function(){f&&(f.__client--,f.__client<=0&&(e.remove(f),delete f.__promise,f.destroy()),f=null)},this.exec=function(){if(f){var c=a.slice(arguments);return b&&c.unshift(b),f.exec.apply(this,c)}},this.getRuid=function(){return f&&f.uid},this.destroy=function(a){return function(){a&&a.apply(this,arguments),this.trigger("destroy"),this.off(),this.exec("destroy"),this.disconnectRuntime()}}(this.destroy)}var e;return e=function(){var a={};return{add:function(b){a[b.uid]=b},get:function(b,c){var d;if(b)return a[b];for(d in a)if(!c||!a[d].__standalone)return a[d];return null},remove:function(b){delete a[b.uid]}}}(),b.installTo(d.prototype),d}),b("lib/dnd",["base","mediator","runtime/client"],function(a,b,c){function d(a){a=this.options=e.extend({},d.options,a),a.container=e(a.container),a.container.length&&c.call(this,"DragAndDrop")}var e=a.$;return d.options={accept:null,disableGlobalDnd:!1},a.inherits(c,{constructor:d,init:function(){var a=this;a.connectRuntime(a.options,function(){a.exec("init"),a.trigger("ready")})}}),b.installTo(d.prototype),d}),b("widgets/widget",["base","uploader"],function(a,b){function c(a){if(!a)return!1;var b=a.length,c=e.type(a);return 1===a.nodeType&&b?!0:"array"===c||"function"!==c&&"string"!==c&&(0===b||"number"==typeof b&&b>0&&b-1 in a)}function d(a){this.owner=a,this.options=a.options}var e=a.$,f=b.prototype._init,g=b.prototype.destroy,h={},i=[];return e.extend(d.prototype,{init:a.noop,invoke:function(a,b){var c=this.responseMap;return c&&a in c&&c[a]in this&&e.isFunction(this[c[a]])?this[c[a]].apply(this,b):h},request:function(){return this.owner.request.apply(this.owner,arguments)}}),e.extend(b.prototype,{_init:function(){var a=this,b=a._widgets=[],c=a.options.disableWidgets||"";return e.each(i,function(d,e){(!c||!~c.indexOf(e._name))&&b.push(new e(a))}),f.apply(a,arguments)},request:function(b,d,e){var f,g,i,j,k=0,l=this._widgets,m=l&&l.length,n=[],o=[];for(d=c(d)?d:[d];m>k;k++)f=l[k],g=f.invoke(b,d),g!==h&&(a.isPromise(g)?o.push(g):n.push(g));return e||o.length?(i=a.when.apply(a,o),j=i.pipe?"pipe":"then",i[j](function(){var b=a.Deferred(),c=arguments;return 1===c.length&&(c=c[0]),setTimeout(function(){b.resolve(c)},1),b.promise()})[e?j:"done"](e||a.noop)):n[0]},destroy:function(){g.apply(this,arguments),this._widgets=null}}),b.register=d.register=function(b,c){var f,g={init:"init",destroy:"destroy",name:"anonymous"};return 1===arguments.length?(c=b,e.each(c,function(a){return"_"===a[0]||"name"===a?("name"===a&&(g.name=c.name),void 0):(g[a.replace(/[A-Z]/g,"-$&").toLowerCase()]=a,void 0)})):g=e.extend(g,b),c.responseMap=g,f=a.inherits(d,c),f._name=g.name,i.push(f),f},b.unRegister=d.unRegister=function(a){if(a&&"anonymous"!==a)for(var b=i.length;b--;)i[b]._name===a&&i.splice(b,1)},d}),b("widgets/filednd",["base","uploader","lib/dnd","widgets/widget"],function(a,b,c){var d=a.$;return b.options.dnd="",b.register({name:"dnd",init:function(b){if(b.dnd&&"html5"===this.request("predict-runtime-type")){var e,f=this,g=a.Deferred(),h=d.extend({},{disableGlobalDnd:b.disableGlobalDnd,container:b.dnd,accept:b.accept});return this.dnd=e=new c(h),e.once("ready",g.resolve),e.on("drop",function(a){f.request("add-file",[a])}),e.on("accept",function(a){return f.owner.trigger("dndAccept",a)}),e.init(),g.promise()}},destroy:function(){this.dnd&&this.dnd.destroy()}})}),b("lib/filepaste",["base","mediator","runtime/client"],function(a,b,c){function d(a){a=this.options=e.extend({},a),a.container=e(a.container||document.body),c.call(this,"FilePaste")}var e=a.$;return a.inherits(c,{constructor:d,init:function(){var a=this;a.connectRuntime(a.options,function(){a.exec("init"),a.trigger("ready")})}}),b.installTo(d.prototype),d}),b("widgets/filepaste",["base","uploader","lib/filepaste","widgets/widget"],function(a,b,c){var d=a.$;return b.register({name:"paste",init:function(b){if(b.paste&&"html5"===this.request("predict-runtime-type")){var e,f=this,g=a.Deferred(),h=d.extend({},{container:b.paste,accept:b.accept});return this.paste=e=new c(h),e.once("ready",g.resolve),e.on("paste",function(a){f.owner.request("add-file",[a])}),e.init(),g.promise()}},destroy:function(){this.paste&&this.paste.destroy()}})}),b("lib/blob",["base","runtime/client"],function(a,b){function c(a,c){var d=this;d.source=c,d.ruid=a,this.size=c.size||0,this.type=!c.type&&this.ext&&~"jpg,jpeg,png,gif,bmp".indexOf(this.ext)?"image/"+("jpg"===this.ext?"jpeg":this.ext):c.type||"application/octet-stream",b.call(d,"Blob"),this.uid=c.uid||this.uid,a&&d.connectRuntime(a)}return a.inherits(b,{constructor:c,slice:function(a,b){return this.exec("slice",a,b)},getSource:function(){return this.source}}),c}),b("lib/file",["base","lib/blob"],function(a,b){function c(a,c){var f;this.name=c.name||"untitled"+d++,f=e.exec(c.name)?RegExp.$1.toLowerCase():"",!f&&c.type&&(f=/\/(jpg|jpeg|png|gif|bmp)$/i.exec(c.type)?RegExp.$1.toLowerCase():"",this.name+="."+f),this.ext=f,this.lastModifiedDate=c.lastModifiedDate||c.lastModified&&new Date(c.lastModified).toLocaleString()||(new Date).toLocaleString(),b.apply(this,arguments)}var d=1,e=/\.([^.]+)$/;return a.inherits(b,c)}),b("lib/filepicker",["base","runtime/client","lib/file"],function(b,c,d){function e(a){if(a=this.options=f.extend({},e.options,a),a.container=f(a.id),!a.container.length)throw new Error("按钮指定错误");a.innerHTML=a.innerHTML||a.label||a.container.html()||"",a.button=f(a.button||document.createElement("div")),a.button.html(a.innerHTML),a.container.html(a.button),c.call(this,"FilePicker",!0)}var f=b.$;return e.options={button:null,container:null,label:null,innerHTML:null,multiple:!0,accept:null,name:"file",style:"webuploader-pick"},b.inherits(c,{constructor:e,init:function(){var c=this,e=c.options,g=e.button,h=e.style;h&&g.addClass("webuploader-pick"),c.on("all",function(a){var b;switch(a){case"mouseenter":h&&g.addClass("webuploader-pick-hover");break;case"mouseleave":h&&g.removeClass("webuploader-pick-hover");break;case"change":b=c.exec("getFiles"),c.trigger("select",f.map(b,function(a){return a=new d(c.getRuid(),a),a._refer=e.container,a}),e.container)}}),c.connectRuntime(e,function(){c.refresh(),c.exec("init",e),c.trigger("ready")}),this._resizeHandler=b.bindFn(this.refresh,this),f(a).on("resize",this._resizeHandler)},refresh:function(){var a=this.getRuntime().getContainer(),b=this.options.button,c=b[0]&&b[0].offsetWidth||b.outerWidth()||b.width(),d=b[0]&&b[0].offsetHeight||b.outerHeight()||b.height(),e=b.offset();c&&d&&a.css({bottom:"auto",right:"auto",width:c+"px",height:d+"px"}).offset(e)},enable:function(){var a=this.options.button;a.removeClass("webuploader-pick-disable"),this.refresh()},disable:function(){var a=this.options.button;this.getRuntime().getContainer().css({top:"-99999px"}),a.addClass("webuploader-pick-disable")},destroy:function(){var b=this.options.button;f(a).off("resize",this._resizeHandler),b.removeClass("webuploader-pick-disable webuploader-pick-hover webuploader-pick")}}),e}),b("widgets/filepicker",["base","uploader","lib/filepicker","widgets/widget"],function(a,b,c){var d=a.$;return d.extend(b.options,{pick:null,accept:null}),b.register({name:"picker",init:function(a){return this.pickers=[],a.pick&&this.addBtn(a.pick)},refresh:function(){d.each(this.pickers,function(){this.refresh()})},addBtn:function(b){var e=this,f=e.options,g=f.accept,h=[];if(b)return d.isPlainObject(b)||(b={id:b}),d(b.id).each(function(){var i,j,k;k=a.Deferred(),i=d.extend({},b,{accept:d.isPlainObject(g)?[g]:g,swf:f.swf,runtimeOrder:f.runtimeOrder,id:this}),j=new c(i),j.once("ready",k.resolve),j.on("select",function(a){e.owner.request("add-file",[a])}),j.on("dialogopen",function(){e.owner.trigger("dialogOpen",j.button)}),j.init(),e.pickers.push(j),h.push(k.promise())}),a.when.apply(a,h)},disable:function(){d.each(this.pickers,function(){this.disable()})},enable:function(){d.each(this.pickers,function(){this.enable()})},destroy:function(){d.each(this.pickers,function(){this.destroy()}),this.pickers=null}})}),b("lib/image",["base","runtime/client","lib/blob"],function(a,b,c){function d(a){this.options=e.extend({},d.options,a),b.call(this,"Image"),this.on("load",function(){this._info=this.exec("info"),this._meta=this.exec("meta")})}var e=a.$;return d.options={quality:90,crop:!1,preserveHeaders:!1,allowMagnify:!1},a.inherits(b,{constructor:d,info:function(a){return a?(this._info=a,this):this._info},meta:function(a){return a?(this._meta=a,this):this._meta},loadFromBlob:function(a){var b=this,c=a.getRuid();this.connectRuntime(c,function(){b.exec("init",b.options),b.exec("loadFromBlob",a)})},resize:function(){var b=a.slice(arguments);return this.exec.apply(this,["resize"].concat(b))},crop:function(){var b=a.slice(arguments);return this.exec.apply(this,["crop"].concat(b))},getAsDataUrl:function(a){return this.exec("getAsDataUrl",a)},getAsBlob:function(a){var b=this.exec("getAsBlob",a);return new c(this.getRuid(),b)}}),d}),b("widgets/image",["base","uploader","lib/image","widgets/widget"],function(b,c,d){var e=null;!function(){function b(a){return(b="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a})(a)}function c(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);b&&(d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable})),c.push.apply(c,d)}return c}function f(a){for(var b=1;ba.length)&&(b=a.length);for(var c=0,d=Array(b);b>c;c++)d[c]=a[c];return d}function k(a,b){var c=null==a?null:"undefined"!=typeof Symbol&&a[Symbol.iterator]||a["@@iterator"];if(null!=c){var d,e,f,g,h=[],i=!0,j=!1;try{if(f=(c=c.call(a)).next,0===b){if(Object(c)!==c)return;i=!1}else for(;!(i=(d=f.call(c)).done)&&(h.push(d.value),h.length!==b);i=!0);}catch(k){j=!0,e=k}finally{try{if(!i&&null!=c.return&&(g=c.return(),Object(g)!==g))return}finally{if(j)throw e}}return h}}function l(a){return Array.isArray(a)?a:void 0}function m(a,b,c){return(b=n(b))in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function n(a){var c=o(a,"string");return"symbol"===b(c)?c:String(c)}function o(a,c){if("object"!==b(a)||null===a)return a;var d=a[Symbol.toPrimitive];if(void 0!==d){var e=d.call(a,c||"default");if("object"!==b(e))return e;throw TypeError("@@toPrimitive must return a primitive value.")}return("string"===c?String:Number)(a)}var p;e=(p=function(){function b(a,b){return new Promise(function(c,d){var e;return F(a).then(function(a){try{return e=a,c(new Blob([b.slice(0,2),e,b.slice(2)],{type:"image/jpeg"}))}catch(f){return d(f)}},d)})}function c(a,b){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Date.now();return new Promise(function(d){for(var e=a.split(","),f=e[0].match(/:(.*?);/)[1],g=globalThis.atob(e[1]),h=g.length,i=new Uint8Array(h);h--;)i[h]=g.charCodeAt(h);var j=new Blob([i],{type:f});j.name=b,j.lastModified=c,d(j)})}function e(a){return new Promise(function(b,c){var d=new P;d.onload=function(){return b(d.result)},d.onerror=function(a){return c(a)},d.readAsDataURL(a)})}function h(a){return new Promise(function(b,c){var e=new d;e.onload=function(){return b(e)},e.onerror=function(a){return c(a)},e.src=a})}function i(){if(void 0!==i.cachedResult)return i.cachedResult;var a=K.ETC,b=navigator.userAgent;return/Chrom(e|ium)/i.test(b)?a=K.CHROME:/iP(ad|od|hone)/i.test(b)&&/WebKit/i.test(b)?a=K.IOS:/Safari/i.test(b)?a=K.DESKTOP_SAFARI:/Firefox/i.test(b)?a=K.FIREFOX:(/MSIE/i.test(b)||1==!!document.documentMode)&&(a=K.IE),i.cachedResult=a,i.cachedResult}function j(a,b){for(var c=L[i()],d=a,e=b,f=d*e,g=d>e?e/d:d/e;f>c*c;){var h=(c+d)/2,j=(c+e)/2;j>h?(e=j,d=j*g):(e=h*g,d=h),f=d*e}return{width:d,height:e}}function k(a,b){var c,d;try{if(d=(c=new OffscreenCanvas(a,b)).getContext("2d"),null===d)throw Error("getContext of OffscreenCanvas returns null")}catch(e){d=(c=document.createElement("canvas")).getContext("2d")}return c.width=a,c.height=b,[c,d]}function l(a,b){var c=j(a.width,a.height),d=k(c.width,c.height),e=g(d,2),f=e[0],h=e[1];return b&&/jpe?g/.test(b)&&(h.fillStyle="white",h.fillRect(0,0,f.width,f.height)),h.drawImage(a,0,0,f.width,f.height),f}function n(){return void 0!==n.cachedResult||(n.cachedResult=["iPad Simulator","iPhone Simulator","iPod Simulator","iPad","iPhone","iPod"].includes(navigator.platform)||navigator.userAgent.includes("Mac")&&"undefined"!=typeof document&&"ontouchend"in document),n.cachedResult}function o(a){var b=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return new Promise(function(c,d){var f,g,j=function(){try{return g=l(f,b.fileType||a.type),c([f,g])}catch(e){return d(e)}},k=function(){try{var b,c=function(a){try{throw a}catch(b){return d(b)}};try{return e(a).then(function(a){try{return b=a,h(b).then(function(a){try{return f=a,function(){try{return j()}catch(a){return d(a)}}()}catch(b){return c(b)}},c)}catch(e){return c(e)}},c)}catch(g){c(g)}}catch(i){return d(i)}};try{if(n()||[K.DESKTOP_SAFARI,K.MOBILE_SAFARI].includes(i()))throw Error("Skip createImageBitmap on IOS and Safari");return createImageBitmap(a).then(function(a){try{return f=a,j()}catch(b){return k()}},k)}catch(m){k()}})}function p(a,b,d,e){var f=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1;return new Promise(function(g,h){function i(){return g(k)}if("image/png"===b)return n=(l=(m=a.getContext("2d")).getImageData(0,0,a.width,a.height)).data,o=I.encode([n.buffer],a.width,a.height,4096*f),(k=new Blob([o],{type:b})).name=d,k.lastModified=e,i.call(this);var j=function(){return i.call(this)};if("image/bmp"===b)return new Promise(function(b){return J.toBlob(a,b)}).then(function(a){try{return(k=a).name=d,k.lastModified=e,j.call(this)}catch(b){return h(b)}}.bind(this),h);var k,l,m,n,o,p,q=function(){return j.call(this)};return"function"==typeof OffscreenCanvas&&a instanceof OffscreenCanvas?a.convertToBlob({type:b,quality:f}).then(function(a){try{return(k=a).name=d,k.lastModified=e,q.call(this)}catch(b){return h(b)}}.bind(this),h):c(p=a.toDataURL(b,f),d,e).then(function(a){try{return k=a,q.call(this)}catch(b){return h(b)}}.bind(this),h)})}function q(a){a.width=0,a.height=0}function r(){return new Promise(function(a,b){var d,e,f,g,h;return void 0!==r.cachedResult?a(r.cachedResult):(d="data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==",c("data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==","test.jpg",Date.now()).then(function(c){try{return e=c,o(e).then(function(c){try{return f=c[1],p(f,e.type,e.name,e.lastModified).then(function(c){try{return g=c,q(f),o(g).then(function(c){try{return h=c[0],r.cachedResult=1===h.width&&2===h.height,a(r.cachedResult)}catch(d){return b(d)}},b)}catch(d){return b(d)}},b)}catch(d){return b(d)}},b)}catch(d){return b(d)}},b))})}function s(a){return new Promise(function(b,c){var d=new P;d.onload=function(a){var c=new DataView(a.target.result);if(65496!=c.getUint16(0,!1))return b(-2);for(var d=c.byteLength,e=2;d>e&&!(8>=c.getUint16(e+2,!1));){var f=c.getUint16(e,!1);if(e+=2,65505==f){if(1165519206!=c.getUint32(e+=2,!1))return b(-1);var g=18761==c.getUint16(e+=6,!1);e+=c.getUint32(e+4,g);var h=c.getUint16(e,g);e+=2;for(var i=0;h>i;i++)if(274==c.getUint16(e+12*i,g))return b(c.getUint16(e+12*i+8,g))}else{if(65280!=(65280&f))break;e+=c.getUint16(e,!1)}}return b(-1)},d.onerror=function(a){return c(a)},d.readAsArrayBuffer(a)})}function t(a,b){var c,d,e,f=a.width,h=a.height,i=b.maxWidthOrHeight,j=a;return isFinite(i)&&(f>i||h>i)&&(c=k(f,h),j=(d=g(c,2))[0],e=d[1],f>h?(j.width=i,j.height=h/f*i):(j.width=f/h*i,j.height=i),e.drawImage(a,0,0,j.width,j.height),q(a)),j}function u(a,b){var c=a.width,d=a.height,e=k(c,d),f=g(e,2),h=f[0],i=f[1];switch(b>4&&9>b?(h.width=d,h.height=c):(h.width=c,h.height=d),b){case 2:i.transform(-1,0,0,1,c,0);break;case 3:i.transform(-1,0,0,-1,c,d);break;case 4:i.transform(1,0,0,-1,0,d);break;case 5:i.transform(0,1,1,0,0,0);break;case 6:i.transform(0,1,-1,0,d,0);break;case 7:i.transform(0,-1,-1,0,d,c);break;case 8:i.transform(0,-1,1,0,0,c)}return i.drawImage(a,0,0,c,d),q(a),h}function v(a,b){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return new Promise(function(d,e){function f(){var a=arguments.length>0&&void 0!==arguments[0]?arguments[0]:5;if(b.signal&&b.signal.aborted)throw b.signal.reason;i+=a,b.onProgress(Math.min(i,100))}function h(a){if(b.signal&&b.signal.aborted)throw b.signal.reason;i=Math.min(Math.max(a,i),100),b.onProgress(i)}var i,j,l,m,n,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J;return i=c,j=b.maxIteration||10,l=1024*1024*b.maxSizeMB,f(),o(a,b).then(function(c){try{var i;return m=(i=g(c,2))[1],f(),n=t(m,b),f(),new Promise(function(c,d){function e(){return c(f)}var f;return(f=b.exifOrientation)?e.call(this):s(a).then(function(a){try{return f=a,e.call(this)}catch(b){return d(b)}}.bind(this),d)}).then(function(c){try{return v=c,f(),r().then(function(c){try{return w=c?n:u(n,v),f(),x=b.initialQuality||1,y=b.fileType||a.type,p(w,y,a.name,a.lastModified,x).then(function(c){try{var i,o=function t(){if(j--&&(E>l||E>C)){var b,c,d,f;return d=J?.95*I.width:I.width,f=J?.95*I.height:I.height,b=k(d,f),G=(c=g(b,2))[0],(H=c[1]).drawImage(I,0,0,d,f),x*="image/png"===y?.85:.95,p(G,y,a.name,a.lastModified,x).then(function(a){try{return F=a,q(I),I=G,E=F.size,h(Math.min(99,Math.floor(100*((D-E)/(D-l))))),t}catch(b){return e(b)}},e)}return[1]},r=function(){return q(I),q(G),q(n),q(w),q(m),h(100),d(F)};return z=c,f(),A=z.size>l,B=z.size>a.size,A||B?(C=a.size,E=D=z.size,I=w,J=!b.alwaysKeepResolution&&A,(i=function(a){for(;a;){if(a.then)return void a.then(i,e);try{if(a.pop){if(a.length)return a.pop()?r.call(this):a;a=o}else a=a.call(this)}catch(b){return e(b)}}}.bind(this))(o)):(h(100),d(z))}catch(s){return e(s)}}.bind(this),e)}catch(i){return e(i)}}.bind(this),e)}catch(i){return e(i)}}.bind(this),e)}catch(o){return e(o)}}.bind(this),e)})}function w(a,c){return new Promise(function(d,e){function g(){try{l.name=a.name,l.lastModified=a.lastModified}catch(c){}try{k.preserveExif&&"image/jpeg"===a.type&&(!k.fileType||k.fileType&&k.fileType===a.type)&&(l=b(a,l))}catch(e){}return d(l)}if(k=f({},c),m=0,n=(j=k).onProgress,k.maxSizeMB=k.maxSizeMB||Number.POSITIVE_INFINITY,o="boolean"!=typeof k.useWebWorker||k.useWebWorker,delete k.useWebWorker,k.onProgress=function(a){m=a,"function"==typeof n&&n(m)},!/^image/.test(a.type))return e(Error("The file given is not an image"));if(p="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!o||"function"!=typeof Worker||p)return v(a,k).then(function(a){try{return l=a,g.call(this)}catch(b){return e(b)}}.bind(this),e);var h,i,j,k,l,m,n,o,p,q=function(){try{return g.call(this)}catch(a){return e(a)}}.bind(this),r=function(){try{return v(a,k).then(function(a){try{return l=a,q()}catch(b){return e(b)}},e)}catch(b){return e(b)}};try{return k.libURL=k.libURL||"https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js",(h=a,i=k,new Promise(function(a,b){var c,d="\nlet scriptImported = false\nself.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n options.onProgress = (progress) => self.postMessage({ progress, id })\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n self.importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message + '\\n' + e.stack, id })\n }\n})\n";y||(c=[],"function"==typeof d?c.push("(".concat(d,")()")):c.push(d),y=URL.createObjectURL(new Blob(c)));var e=new Worker(y);e.addEventListener("message",function(c){if(i.signal&&i.signal.aborted)e.terminate();else if(void 0===c.data.progress){if(c.data.error)return b(Error(c.data.error)),void e.terminate();a(c.data.file),e.terminate()}else i.onProgress(c.data.progress)}),e.addEventListener("error",b),i.signal&&i.signal.addEventListener("abort",function(){b(i.signal.reason),e.terminate()}),e.postMessage({file:h,imageCompressionLibUrl:i.libURL,options:f(f({},i),{},{onProgress:void 0,signal:void 0})})})).then(function(a){try{return l=a,q()}catch(b){return r()}},r)}catch(s){r()}})}var x,y,z,A,B,C,D,E,F=function(a){return new Promise(function(b,c){var d=new FileReader;d.addEventListener("load",function(a){var d=a.target.result,e=new DataView(d),f=0;if(65496!==e.getUint16(f))return c("not a valid JPEG");for(f+=2;;){var g=e.getUint16(f);if(65498===g)break;var h=e.getUint16(f+2);if(65505===g&&1165519206===e.getUint32(f+4)){var i=f+10,j=void 0;switch(e.getUint16(i)){case 18761:j=!0;break;case 19789:j=!1;break;default:return c("TIFF header contains invalid endian")}if(42!==e.getUint16(i+2,j))return c("TIFF header contains invalid version");for(var k=e.getUint32(i+4,j),l=i+k+2+12*e.getUint16(i+k,j),m=i+k+2;l>m;m+=12)if(274==e.getUint16(m,j)){if(3!==e.getUint16(m+2,j))return c("Orientation data type is invalid");if(1!==e.getUint32(m+4,j))return c("Orientation data count is invalid");e.setUint16(m+8,1,j);break}return b(d.slice(f,f+2+h))}f+=2+h}return b(new Blob)}),d.readAsArrayBuffer(a)})},G={};z={get exports(){return G},set exports(a){G=a}},C={},z.exports=C,C.parse=function(a,b){for(var c=C.bin.readUshort,d=C.bin.readUint,e=0,f={},g=new Uint8Array(a),h=g.length-4;101010256!=d(g,h);)h--;e=h,e+=4;var i=c(g,e+=4);c(g,e+=2);var j=d(g,e+=2),k=d(g,e+=4);e+=4,e=k;for(var l=0;i>l;l++){d(g,e),e+=4,e+=4,e+=4,d(g,e+=4),j=d(g,e+=4);var m=d(g,e+=4),n=c(g,e+=4),o=c(g,e+2),p=c(g,e+4);e+=6;var q=d(g,e+=8);e+=4,e+=n+o+p,C._readLocal(g,q,f,j,m,b)}return f},C._readLocal=function(a,b,c,d,e,f){var g=C.bin.readUshort,h=C.bin.readUint;h(a,b),g(a,b+=4),g(a,b+=2);var i=g(a,b+=2);h(a,b+=2),h(a,b+=4),b+=4;var j=g(a,b+=8),k=g(a,b+=2);b+=2;var l=C.bin.readUTF8(a,b,j);if(b+=j,b+=k,f)c[l]={size:e,csize:d};else{var m=new Uint8Array(a.buffer,b);if(0==i)c[l]=new Uint8Array(m.buffer.slice(b,b+d));else{if(8!=i)throw"unknown compression method: "+i;var n=new Uint8Array(e);C.inflateRaw(m,n),c[l]=n}}},C.inflateRaw=function(a,b){return C.F.inflate(a,b)},C.inflate=function(a,b){return a[0],a[1],C.inflateRaw(new Uint8Array(a.buffer,a.byteOffset+2,a.length-6),b)},C.deflate=function(a,b){null==b&&(b={level:6});var c=0,d=new Uint8Array(50+Math.floor(1.1*a.length));d[c]=120,d[c+1]=156,c+=2,c=C.F.deflateRaw(a,d,c,b.level);var e=C.adler(a,0,a.length);return d[c+0]=255&e>>>24,d[c+1]=255&e>>>16,d[c+2]=255&e>>>8,d[c+3]=255&e>>>0,new Uint8Array(d.buffer,0,c+4)},C.deflateRaw=function(a,b){null==b&&(b={level:6}); -var c=new Uint8Array(50+Math.floor(1.1*a.length)),d=C.F.deflateRaw(a,c,d,b.level);return new Uint8Array(c.buffer,0,d)},C.encode=function(a,b){null==b&&(b=!1);var c=0,d=C.bin.writeUint,e=C.bin.writeUshort,f={};for(var g in a){var h=!C._noNeed(g)&&!b,i=a[g],j=C.crc.crc(i,0,i.length);f[g]={cpr:h,usize:i.length,crc:j,file:h?C.deflateRaw(i):i}}for(var g in f)c+=f[g].file.length+30+46+2*C.bin.sizeUTF8(g);c+=22;var k=new Uint8Array(c),l=0,m=[];for(var g in f){var n=f[g];m.push(l),l=C._writeHeader(k,l,g,n,0)}var o=0,p=l;for(var g in f)n=f[g],m.push(l),l=C._writeHeader(k,l,g,n,1,m[o++]);var q=l-p;return d(k,l,101010256),l+=4,e(k,l+=4,o),e(k,l+=2,o),d(k,l+=2,q),d(k,l+=4,p),l+=4,l+=2,k.buffer},C._noNeed=function(a){var b=a.split(".").pop().toLowerCase();return-1!="png,jpg,jpeg,zip".indexOf(b)},C._writeHeader=function(a,b,c,d,e,f){var g=C.bin.writeUint,h=C.bin.writeUshort,i=d.file;return g(a,b,0==e?67324752:33639248),b+=4,1==e&&(b+=2),h(a,b,20),h(a,b+=2,0),h(a,b+=2,d.cpr?8:0),g(a,b+=2,0),g(a,b+=4,d.crc),g(a,b+=4,i.length),g(a,b+=4,d.usize),h(a,b+=4,C.bin.sizeUTF8(c)),h(a,b+=2,0),b+=2,1==e&&(b+=2,b+=2,g(a,b+=6,f),b+=4),b+=C.bin.writeUTF8(a,b,c),0==e&&(a.set(i,b),b+=i.length),b},C.crc={table:function(){for(var a=new Uint32Array(256),b=0;256>b;b++){for(var c=b,d=0;8>d;d++)1&c?c=3988292384^c>>>1:c>>>=1;a[b]=c}return a}(),update:function(a,b,c,d){for(var e=0;d>e;e++)a=C.crc.table[255&(a^b[c+e])]^a>>>8;return a},crc:function(a,b,c){return 4294967295^C.crc.update(4294967295,a,b,c)}},C.adler=function(a,b,c){for(var d=1,e=0,f=b,g=b+c;g>f;){for(var h=Math.min(f+5552,g);h>f;)e+=d+=a[f++];d%=65521,e%=65521}return e<<16|d},C.bin={readUshort:function(a,b){return a[b]|a[b+1]<<8},writeUshort:function(a,b,c){a[b]=255&c,a[b+1]=255&c>>8},readUint:function(a,b){return 16777216*a[b+3]+(a[b+2]<<16|a[b+1]<<8|a[b])},writeUint:function(a,b,c){a[b]=255&c,a[b+1]=255&c>>8,a[b+2]=255&c>>16,a[b+3]=255&c>>24},readASCII:function(a,b,c){for(var d="",e=0;c>e;e++)d+=String.fromCharCode(a[b+e]);return d},writeASCII:function(a,b,c){for(var d=0;df;f++)e+="%"+C.bin.pad(a[b+f].toString(16));try{d=decodeURIComponent(e)}catch(g){return C.bin.readASCII(a,b,c)}return d},writeUTF8:function(a,b,c){for(var d=c.length,e=0,f=0;d>f;f++){var g=c.charCodeAt(f);if(0==(4294967168&g))a[b+e]=g,e++;else if(0==(4294965248&g))a[b+e]=192|g>>6,a[b+e+1]=128|63&g>>0,e+=2;else if(0==(4294901760&g))a[b+e]=224|g>>12,a[b+e+1]=128|63&g>>6,a[b+e+2]=128|63&g>>0,e+=3;else{if(0!=(4292870144&g))throw"e";a[b+e]=240|g>>18,a[b+e+1]=128|63&g>>12,a[b+e+2]=128|63&g>>6,a[b+e+3]=128|63&g>>0,e+=4}}return e},sizeUTF8:function(a){for(var b=a.length,c=0,d=0;b>d;d++){var e=a.charCodeAt(d);if(0==(4294967168&e))c++;else if(0==(4294965248&e))c+=2;else if(0==(4294901760&e))c+=3;else{if(0!=(4292870144&e))throw"e";c+=4}}return c}},C.F={},C.F.deflateRaw=function(a,b,c,d){var e=[[0,0,0,0,0],[4,4,8,4,0],[4,5,16,8,0],[4,6,16,16,0],[4,10,16,32,0],[8,16,32,32,0],[8,16,128,128,0],[8,32,128,256,0],[32,128,258,1024,1],[32,258,258,4096,1]][d],f=C.F.U,g=C.F._goodIndex;C.F._hash;var h=C.F._putsE,i=0,j=c<<3,k=0,l=a.length;if(0==d){for(;l>i;)h(b,j,i+(x=Math.min(65535,l-i))==l?1:0),j=C.F._copyExact(a,i,x,b,j+8),i+=x;return j>>>3}var m=f.lits,n=f.strt,o=f.prev,p=0,q=0,r=0,s=0,t=0,u=0;for(l>2&&(n[u=C.F._hash(a,0)]=0),i=0;l>i;i++){if(t=u,l-2>i+1){u=C.F._hash(a,i+1);var v=32767&i+1;o[v]=n[u],n[u]=v}if(i>=k){(p>14e3||q>26697)&&l-i>100&&(i>k&&(m[p]=i-k,p+=2,k=i),j=C.F._writeBlock(i==l-1||k==l?1:0,m,p,s,a,r,i-r,b,j),p=q=s=0,r=i);var w=0;l-2>i&&(w=C.F._bestMatch(a,i,o,t,Math.min(e[2],l-i),e[3]));var x=w>>>16,y=65535&w;if(0!=w){y=65535&w;var z=g(x=w>>>16,f.of0);f.lhst[257+z]++;var A=g(y,f.df0);f.dhst[A]++,s+=f.exb[z]+f.dxb[A],m[p]=x<<23|i-k,m[p+1]=y<<16|z<<8|A,p+=2,k=i+x}else f.lhst[a[i]]++;q++}}for(r==i&&0!=a.length||(i>k&&(m[p]=i-k,p+=2,k=i),j=C.F._writeBlock(1,m,p,s,a,r,i-r,b,j),p=0,q=0,p=q=s=0,r=i);0!=(7&j);)j++;return j>>>3},C.F._bestMatch=function(a,b,c,d,e,f){var g=32767&b,h=c[g],i=32767&g-h+32768;if(h==g||d!=C.F._hash(a,b-i))return 0;for(var j=0,k=0,l=Math.min(32767,b);l>=i&&0!=--f&&h!=g;){if(0==j||a[b+j]==a[b+j-i]){var m=C.F._howLong(a,b,i);if(m>j){if(k=i,(j=m)>=e)break;m>i+2&&(m=i+2);for(var n=0,o=0;m-2>o;o++){var p=32767&b-i+o+32768,q=32767&p-c[p]+32768;q>n&&(n=q,h=p)}}}i+=32767&(g=h)-(h=c[g])+32768}return j<<16|k},C.F._howLong=function(a,b,c){if(a[b]!=a[b-c]||a[b+1]!=a[b+1-c]||a[b+2]!=a[b+2-c])return 0;var d=b,e=Math.min(a.length,b+258);for(b+=3;e>b&&a[b]==a[b-c];)b++;return b-d},C.F._hash=function(a,b){return 65535&(a[b]<<8|a[b+1])+(a[b+2]<<4)},C.saved=0,C.F._writeBlock=function(a,b,c,d,e,f,g,h,i){var j,k,l,m,n,o,p,q,r,s,t,u=C.F.U,v=C.F._putsF,w=C.F._putsE;u.lhst[256]++,m=(l=C.F.getTrees())[0],n=l[1],o=l[2],p=l[3],q=l[4],r=l[5],s=l[6],t=l[7];var x=32+(0==(7&i+3)?0:8-(7&i+3))+(g<<3),y=d+C.F.contSize(u.fltree,u.lhst)+C.F.contSize(u.fdtree,u.dhst),z=d+C.F.contSize(u.ltree,u.lhst)+C.F.contSize(u.dtree,u.dhst);z+=14+3*r+C.F.contSize(u.itree,u.ihst)+(2*u.ihst[16]+3*u.ihst[17]+7*u.ihst[18]);for(var A=0;286>A;A++)u.lhst[A]=0;for(A=0;30>A;A++)u.dhst[A]=0;for(A=0;19>A;A++)u.ihst[A]=0;var B=y>x&&z>x?0:z>y?1:2;if(v(h,i,a),v(h,i+1,B),i+=3,0==B){for(;0!=(7&i);)i++;i=C.F._copyExact(e,f,g,h,i)}else{if(1==B&&(j=u.fltree,k=u.fdtree),2==B){C.F.makeCodes(u.ltree,m),C.F.revCodes(u.ltree,m),C.F.makeCodes(u.dtree,n),C.F.revCodes(u.dtree,n),C.F.makeCodes(u.itree,o),C.F.revCodes(u.itree,o),j=u.ltree,k=u.dtree,w(h,i,p-257),w(h,i+=5,q-1),w(h,i+=5,r-4),i+=4;for(var D=0;r>D;D++)w(h,i+3*D,u.itree[1+(u.ordr[D]<<1)]);i+=3*r,i=C.F._codeTiny(s,u.itree,h,i),i=C.F._codeTiny(t,u.itree,h,i)}for(var E=f,F=0;c>F;F+=2){for(var G=b[F],H=G>>>23,I=E+(8388607&G);I>E;)i=C.F._writeLit(e[E++],j,h,i);if(0!=H){var J=b[F+1],K=J>>16,L=255&J>>8,M=255&J;w(h,i=C.F._writeLit(257+L,j,h,i),H-u.of0[L]),i+=u.exb[L],v(h,i=C.F._writeLit(M,k,h,i),K-u.df0[M]),i+=u.dxb[M],E+=H}}i=C.F._writeLit(256,j,h,i)}return i},C.F._copyExact=function(a,b,c,d,e){var f=e>>>3;return d[f]=c,d[f+1]=c>>>8,d[f+2]=255-d[f],d[f+3]=255-d[f+1],f+=4,d.set(new Uint8Array(a.buffer,b,c),f),e+(c+4<<3)},C.F.getTrees=function(){for(var a=C.F.U,b=C.F._hufTree(a.lhst,a.ltree,15),c=C.F._hufTree(a.dhst,a.dtree,15),d=[],e=C.F._lenCodes(a.ltree,d),f=[],g=C.F._lenCodes(a.dtree,f),h=0;h4&&0==a.itree[1+(a.ordr[j-1]<<1)];)j--;return[b,c,i,e,g,j,d,f]},C.F.getSecond=function(a){for(var b=[],c=0;c>1)+",");return b},C.F.contSize=function(a,b){for(var c=0,d=0;d15&&(C.F._putsE(c,d,g,h),d+=h)}return d},C.F._lenCodes=function(a,b){for(var c=a.length;2!=c&&0==a[c-1];)c-=2;for(var d=0;c>d;d+=2){var e=a[d+1],f=c>d+3?a[d+3]:-1,g=c>d+5?a[d+5]:-1,h=0==d?-1:a[d-1];if(0==e&&f==e&&g==e){for(var i=d+5;c>i+2&&a[i+2]==e;)i+=2;(j=Math.min(i+1-d>>>1,138))<11?b.push(17,j-3):b.push(18,j-11),d+=2*j-2}else if(e==h&&f==e&&g==e){for(i=d+5;c>i+2&&a[i+2]==e;)i+=2;var j=Math.min(i+1-d>>>1,6);b.push(16,j-3),d+=2*j-2}else b.push(e,0)}return c>>>1},C.F._hufTree=function(a,b,c){var d=[],e=a.length,f=b.length,g=0;for(g=0;f>g;g+=2)b[g]=0,b[g+1]=0;for(g=0;e>g;g++)0!=a[g]&&d.push({lit:g,f:a[g]});var h=d.length,i=d.slice(0);if(0==h)return 0;if(1==h){var j=d[0].lit;return i=0==j?1:0,b[1+(j<<1)]=1,b[1+(i<<1)]=1,1}d.sort(function(a,b){return a.f-b.f});var k=d[0],l=d[1],m=0,n=1,o=2;for(d[0]={lit:-1,f:k.f+l.f,l:k,r:l,d:0};n!=h-1;)k=m!=n&&(o==h||d[m].fc&&(C.F.restrictDepth(i,c,p),p=c),g=0;h>g;g++)b[1+(i[g].lit<<1)]=i[g].d;return p},C.F.setDepth=function(a,b){return-1!=a.lit?(a.d=b,b):Math.max(C.F.setDepth(a.l,b+1),C.F.setDepth(a.r,b+1))},C.F.restrictDepth=function(a,b,c){var d=0,e=1<b;d++){var g=a[d].d;a[d].d=b,f+=e-(1<>>=c-b;f>0;)(g=a[d].d)=0;d--)a[d].d==b&&0>f&&(a[d].d--,f++);0!=f&&console.log("debt left")},C.F._goodIndex=function(a,b){var c=0;return b[16|c]<=a&&(c|=16),b[8|c]<=a&&(c|=8),b[4|c]<=a&&(c|=4),b[2|c]<=a&&(c|=2),b[1|c]<=a&&(c|=1),c},C.F._writeLit=function(a,b,c,d){return C.F._putsF(c,d,b[a<<1]),d+b[1+(a<<1)]},C.F.inflate=function(a,b){var c=Uint8Array;if(3==a[0]&&0==a[1])return b||new c(0);var d=C.F,e=d._bitsF,f=d._bitsE,g=d._decodeTiny,h=d.makeCodes,i=d.codes2map,j=d._get17,k=d.U,l=null==b;l&&(b=new c(a.length>>>2<<3));for(var m,n,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;0==o;)if(o=e(a,w,1),p=e(a,w+1,2),w+=3,0!=p){if(l&&(b=C.F._check(b,v+131072)),1==p&&(m=k.flmap,n=k.fdmap,t=511,u=31),2==p){q=f(a,w,5)+257,r=f(a,w+5,5)+1,s=f(a,w+10,4)+4,w+=14;for(var x=0;38>x;x+=2)k.itree[x]=0,k.itree[x+1]=0;var y=1;for(x=0;s>x;x++){var z=f(a,w+3*x,3);k.itree[1+(k.ordr[x]<<1)]=z,z>y&&(y=z)}w+=3*s,h(k.itree,y),i(k.itree,y,k.imap),m=k.lmap,n=k.dmap,w=g(k.imap,(1<>>4;if(0==E>>>8)b[v++]=E;else{if(256==E)break;var F=v+E-254;if(E>264){var G=k.ldef[E-257];F=v+(G>>>3)+f(a,w,7&G),w+=7&G}var H=n[j(a,w)&u];w+=15&H;var I=H>>>4,J=k.ddef[I],K=(J>>>4)+e(a,w,15&J);for(w+=15&J,l&&(b=C.F._check(b,v+131072));F>v;)b[v]=b[v++-K],b[v]=b[v++-K],b[v]=b[v++-K],b[v]=b[v++-K];v=F}}}else{0!=(7&w)&&(w+=8-(7&w));var L=4+(w>>>3),M=a[L-4]|a[L-3]<<8;l&&(b=C.F._check(b,v+M)),b.set(new c(a.buffer,a.byteOffset+L,M),v),w=L+M<<3,v+=M}return b.length==v?b:b.slice(0,v)},C.F._check=function(a,b){var c=a.length;if(c>=b)return a;var d=new Uint8Array(Math.max(c<<1,b));return d.set(a,0),d},C.F._decodeTiny=function(a,b,c,d,e,f){for(var g=C.F._bitsE,h=C.F._get17,i=0;c>i;){var j=a[h(d,e)&b];e+=15&j;var k=j>>>4;if(15>=k)f[i]=k,i++;else{var l=0,m=0;16==k?(m=3+g(d,e,2),e+=2,l=f[i-1]):17==k?(m=3+g(d,e,3),e+=3):18==k&&(m=11+g(d,e,7),e+=7);for(var n=i+m;n>i;)f[i]=l,i++}}return e},C.F._copyOut=function(a,b,c,d){for(var e=0,f=0,g=d.length>>>1;c>f;){var h=a[f+b];d[f<<1]=0,d[1+(f<<1)]=h,h>e&&(e=h),f++}for(;g>f;)d[f<<1]=0,d[1+(f<<1)]=0,f++;return e},C.F.makeCodes=function(a,b){for(var c,d,e,f,g=C.F.U,h=a.length,i=g.bl_count,j=0;b>=j;j++)i[j]=0;for(j=1;h>j;j+=2)i[a[j]]++;var k=g.next_code;for(c=0,i[0]=0,d=1;b>=d;d++)c=c+i[d-1]<<1,k[d]=c;for(e=0;h>e;e+=2)0!=(f=a[e+1])&&(a[e]=k[f],k[f]++)},C.F.codes2map=function(a,b,c){for(var d=a.length,e=C.F.U.rev15,f=0;d>f;f+=2)if(0!=a[f+1])for(var g=f>>1,h=a[f+1],i=g<<4|h,j=b-h,k=a[f]<>>15-b]=i,k++},C.F.revCodes=function(a,b){for(var c=C.F.U.rev15,d=15-b,e=0;e>>d}},C.F._putsE=function(a,b,c){c<<=7&b;var d=b>>>3;a[d]|=c,a[d+1]|=c>>>8},C.F._putsF=function(a,b,c){c<<=7&b;var d=b>>>3;a[d]|=c,a[d+1]|=c>>>8,a[d+2]|=c>>>16},C.F._bitsE=function(a,b,c){return(a[b>>>3]|a[1+(b>>>3)]<<8)>>>(7&b)&(1<>>3]|a[1+(b>>>3)]<<8|a[2+(b>>>3)]<<16)>>>(7&b)&(1<>>3]|a[1+(b>>>3)]<<8|a[2+(b>>>3)]<<16)>>>(7&b)},C.F._get25=function(a,b){return(a[b>>>3]|a[1+(b>>>3)]<<8|a[2+(b>>>3)]<<16|a[3+(b>>>3)]<<24)>>>(7&b)},C.F.U=(A=Uint16Array,B=Uint32Array,{next_code:new A(16),bl_count:new A(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new A(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new B(32),flmap:new A(512),fltree:[],fdmap:new A(32),fdtree:[],lmap:new A(32768),ltree:[],ttree:[],dmap:new A(32768),dtree:[],imap:new A(512),itree:[],rev15:new A(32768),lhst:new B(286),dhst:new B(30),ihst:new B(19),lits:new B(15e3),strt:new A(65536),prev:new A(32768)}),function(){function a(a,b,c){for(;0!=b--;)a.push(0,c)}for(var b=C.F.U,c=0;32768>c;c++){var d=c;d=(4278255360&(d=(4042322160&(d=(3435973836&(d=(2863311530&d)>>>1|(1431655765&d)<<1))>>>2|(858993459&d)<<2))>>>4|(252645135&d)<<4))>>>8|(16711935&d)<<8,b.rev15[c]=(d>>>16|d<<16)>>>17}for(c=0;32>c;c++)b.ldef[c]=b.of0[c]<<3|b.exb[c],b.ddef[c]=b.df0[c]<<4|b.dxb[c];a(b.fltree,144,8),a(b.fltree,112,9),a(b.fltree,24,7),a(b.fltree,8,8),C.F.makeCodes(b.fltree,9),C.F.codes2map(b.fltree,9,b.flmap),C.F.revCodes(b.fltree,9),a(b.fdtree,32,5),C.F.makeCodes(b.fdtree,5),C.F.codes2map(b.fdtree,5,b.fdmap),C.F.revCodes(b.fdtree,5),a(b.itree,19,0),a(b.ltree,286,0),a(b.dtree,30,0),a(b.ttree,320,0)}();var H=(D={__proto__:null,"default":G},(E=[G]).forEach(function(a){a&&"string"!=typeof a&&!Array.isArray(a)&&Object.keys(a).forEach(function(b){if("default"!==b&&!(b in D)){var c=Object.getOwnPropertyDescriptor(a,b);Object.defineProperty(D,b,c.get?c:{enumerable:!0,get:function(){return a[b]}})}})}),Object.freeze(D)),I=function(){function a(a,b,c,e){var f=b*c,g=Math.ceil(b*d(e)/8),h=new Uint8Array(4*f),i=new Uint32Array(h.buffer),j=e.ctype,k=e.depth,m=l.readUshort;if(6==j){var n=f<<2;if(8==k)for(var o=0;n>o;o+=4)h[o]=a[o],h[o+1]=a[o+1],h[o+2]=a[o+2],h[o+3]=a[o+3];if(16==k)for(o=0;n>o;o++)h[o]=a[o<<1]}else if(2==j){var p=e.tabs.tRNS;if(null==p){if(8==k)for(o=0;f>o;o++){var q=3*o;i[o]=-16777216|a[q+2]<<16|a[q+1]<<8|a[q]}if(16==k)for(o=0;f>o;o++)q=6*o,i[o]=-16777216|a[q+4]<<16|a[q+2]<<8|a[q]}else{var r=p[0],s=p[1],t=p[2];if(8==k)for(o=0;f>o;o++){var u=o<<2;q=3*o,i[o]=-16777216|a[q+2]<<16|a[q+1]<<8|a[q],a[q]==r&&a[q+1]==s&&a[q+2]==t&&(h[u+3]=0)}if(16==k)for(o=0;f>o;o++)u=o<<2,q=6*o,i[o]=-16777216|a[q+4]<<16|a[q+2]<<8|a[q],m(a,q)==r&&m(a,q+2)==s&&m(a,q+4)==t&&(h[u+3]=0)}}else if(3==j){var v,w=e.tabs.PLTE,x=e.tabs.tRNS,y=x?x.length:0;if(1==k)for(var z=0;c>z;z++){var A=z*g,B=z*b;for(o=0;b>o;o++){u=B+o<<2;var C=3*(v=1&a[A+(o>>3)]>>7-((7&o)<<0));h[u]=w[C],h[u+1]=w[C+1],h[u+2]=w[C+2],h[u+3]=y>v?x[v]:255}}if(2==k)for(z=0;c>z;z++)for(A=z*g,B=z*b,o=0;b>o;o++)u=B+o<<2,C=3*(v=3&a[A+(o>>2)]>>6-((3&o)<<1)),h[u]=w[C],h[u+1]=w[C+1],h[u+2]=w[C+2],h[u+3]=y>v?x[v]:255;if(4==k)for(z=0;c>z;z++)for(A=z*g,B=z*b,o=0;b>o;o++)u=B+o<<2,C=3*(v=15&a[A+(o>>1)]>>4-((1&o)<<2)),h[u]=w[C],h[u+1]=w[C+1],h[u+2]=w[C+2],h[u+3]=y>v?x[v]:255;if(8==k)for(o=0;f>o;o++)u=o<<2,C=3*(v=a[o]),h[u]=w[C],h[u+1]=w[C+1],h[u+2]=w[C+2],h[u+3]=y>v?x[v]:255}else if(4==j){if(8==k)for(o=0;f>o;o++){u=o<<2;var D,E=a[D=o<<1];h[u]=E,h[u+1]=E,h[u+2]=E,h[u+3]=a[D+1]}if(16==k)for(o=0;f>o;o++)u=o<<2,E=a[D=o<<2],h[u]=E,h[u+1]=E,h[u+2]=E,h[u+3]=a[D+2]}else if(0==j)for(r=e.tabs.tRNS?e.tabs.tRNS:-1,z=0;c>z;z++){var F=z*g,G=z*b;if(1==k)for(var H=0;b>H;H++){var I=(E=255*(1&a[F+(H>>>3)]>>>7-(7&H)))==255*r?0:255;i[G+H]=I<<24|E<<16|E<<8|E}else if(2==k)for(H=0;b>H;H++)I=(E=85*(3&a[F+(H>>>2)]>>>6-((3&H)<<1)))==85*r?0:255,i[G+H]=I<<24|E<<16|E<<8|E;else if(4==k)for(H=0;b>H;H++)I=(E=17*(15&a[F+(H>>>1)]>>>4-((1&H)<<2)))==17*r?0:255,i[G+H]=I<<24|E<<16|E<<8|E;else if(8==k)for(H=0;b>H;H++)I=(E=a[F+H])==r?0:255,i[G+H]=I<<24|E<<16|E<<8|E;else if(16==k)for(H=0;b>H;H++)E=a[F+(H<<1)],I=m(a,F+(H<<1))==r?0:255,i[G+H]=I<<24|E<<16|E<<8|E}return h}function b(a,b,f,g){var h=d(a),i=new Uint8Array((Math.ceil(f*h/8)+1+a.interlace)*g);return b=a.tabs.CgBI?m(b,i):c(b,i),0==a.interlace?b=e(b,a,0,f,g):1==a.interlace&&(b=function(a,b){for(var c=b.width,f=b.height,g=d(b),h=g>>3,i=Math.ceil(c*g/8),j=new Uint8Array(f*i),k=0,l=[0,0,4,0,2,0,1],m=[0,4,0,2,0,1,0],n=[8,8,8,4,4,2,2],o=[8,8,4,4,2,2,1],p=0;7>p;){for(var q=n[p],r=o[p],s=0,t=0,u=l[p];f>u;)u+=q,t++;for(var v=m[p];c>v;)v+=r,s++;var w=Math.ceil(s*g/8);e(a,b,k,s,t);for(var x=0,y=l[p];f>y;){for(var z,A=m[p],B=k+x*w<<3;c>A;){if(1==g&&(z=1&(z=a[B>>3])>>7-(7&B),j[y*i+(A>>3)]|=z<<7-((7&A)<<0)),2==g&&(z=3&(z=a[B>>3])>>6-(7&B),j[y*i+(A>>2)]|=z<<6-((3&A)<<1)),4==g&&(z=15&(z=a[B>>3])>>4-(7&B),j[y*i+(A>>1)]|=z<<4-((1&A)<<2)),g>=8)for(var C=y*i+A*h,D=0;h>D;D++)j[C+D]=a[(B>>3)+D];B+=g,A+=r}x++,y+=q}0!=s*t&&(k+=t*(1+w)),p+=1}return j}(b,a)),b}function c(a,b){return m(new Uint8Array(a.buffer,2,a.length-6),b)}function d(a){return[1,null,3,1,2,null,4][a.ctype]*a.depth}function e(a,b,c,e,g){var h,i,j=d(b),k=Math.ceil(e*j/8);j=Math.ceil(j/8);var l=a[c],m=0;if(l>1&&(a[c]=[0,0,1][l-2]),3==l)for(m=j;k>m;m++)a[m+1]=255&a[m+1]+(a[m+1-j]>>>1);for(var n=0;g>n;n++)if(l=a[(i=(h=c+n*k)+n+1)-1],m=0,0==l)for(;k>m;m++)a[h+m]=a[i+m];else if(1==l){for(;j>m;m++)a[h+m]=a[i+m];for(;k>m;m++)a[h+m]=a[i+m]+a[h+m-j]}else if(2==l)for(;k>m;m++)a[h+m]=a[i+m]+a[h+m-k];else if(3==l){for(;j>m;m++)a[h+m]=a[i+m]+(a[h+m-k]>>>1);for(;k>m;m++)a[h+m]=a[i+m]+(a[h+m-k]+a[h+m-j]>>>1)}else{for(;j>m;m++)a[h+m]=a[i+m]+f(0,a[h+m-k],0);for(;k>m;m++)a[h+m]=a[i+m]+f(a[h+m-j],a[h+m-k],a[h+m-j-k])}return a}function f(a,b,c){var d=a+b-c,e=d-a,f=d-b,g=d-c;return f*f>=e*e&&g*g>=e*e?a:g*g>=f*f?b:c}function g(a,b,c){c.width=l.readUint(a,b),b+=4,c.height=l.readUint(a,b),b+=4,c.depth=a[b],b++,c.ctype=a[b],b++,c.compress=a[b],b++,c.filter=a[b],b++,c.interlace=a[b],b++}function h(a,b,c,d,e,f,g,h,i){for(var j=Math.min(b,e),k=Math.min(c,f),l=0,m=0,n=0;k>n;n++)for(var o=0;j>o;o++)if(g>=0&&h>=0?(l=n*b+o<<2,m=(h+n)*e+g+o<<2):(l=(-h+n)*b-g+o<<2,m=n*e+o<<2),0==i)d[m]=a[l],d[m+1]=a[l+1],d[m+2]=a[l+2],d[m+3]=a[l+3];else if(1==i){var p=a[l+3]*(1/255),q=a[l]*p,r=a[l+1]*p,s=a[l+2]*p,t=d[m+3]*(1/255),u=d[m]*t,v=d[m+1]*t,w=d[m+2]*t,x=1-p,y=p+t*x,z=0==y?0:1/y;d[m+3]=255*y,d[m+0]=(q+u*x)*z,d[m+1]=(r+v*x)*z,d[m+2]=(s+w*x)*z}else if(2==i)p=a[l+3],q=a[l],r=a[l+1],s=a[l+2],t=d[m+3],u=d[m],v=d[m+1],w=d[m+2],p==t&&q==u&&r==v&&s==w?(d[m]=0,d[m+1]=0,d[m+2]=0,d[m+3]=0):(d[m]=q,d[m+1]=r,d[m+2]=s,d[m+3]=p);else if(3==i){if(p=a[l+3],q=a[l],r=a[l+1],s=a[l+2],t=d[m+3],u=d[m],v=d[m+1],w=d[m+2],p==t&&q==u&&r==v&&s==w)continue;if(220>p&&t>20)return!1}return!0}var i,j,k,l={nextZero:function(a,b){for(;0!=a[b];)b++;return b},readUshort:function(a,b){return a[b]<<8|a[b+1]},writeUshort:function(a,b,c){a[b]=255&c>>8,a[b+1]=255&c},readUint:function(a,b){return 16777216*a[b]+(a[b+1]<<16|a[b+2]<<8|a[b+3])},writeUint:function(a,b,c){a[b]=255&c>>24,a[b+1]=255&c>>16,a[b+2]=255&c>>8,a[b+3]=255&c},readASCII:function(a,b,c){for(var d="",e=0;c>e;e++)d+=String.fromCharCode(a[b+e]);return d},writeASCII:function(a,b,c){for(var d=0;de;e++)d.push(a[b+e]);return d},pad:function(a){return a.length<2?"0".concat(a):a},readUTF8:function(a,b,c){for(var d,e="",f=0;c>f;f++)e+="%".concat(l.pad(a[b+f].toString(16)));try{d=decodeURIComponent(e)}catch(g){return l.readASCII(a,b,c)}return d}},m=((i={H:{}}).H.N=function(a,b){var c,d,e=Uint8Array,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;if(3==a[0]&&0==a[1])return b||new e(0);var p=i.H,q=p.b,r=p.e,s=p.R,t=p.n,u=p.A,v=p.Z,w=p.m,x=null==b;for(x&&(b=new e(a.length>>>2<<5));0==f;)if(f=q(a,o,1),g=q(a,o+1,2),o+=3,0!=g){if(x&&(b=i.H.W(b,n+131072)),1==g&&(c=w.J,d=w.h,l=511,m=31),2==g){h=r(a,o,5)+257,j=r(a,o+5,5)+1,k=r(a,o+10,4)+4,o+=14;for(var y=1,z=0;38>z;z+=2)w.Q[z]=0,w.Q[z+1]=0;for(z=0;k>z;z++){var A=r(a,o+3*z,3);w.Q[1+(w.X[z]<<1)]=A,A>y&&(y=A)}o+=3*k,t(w.Q,y),u(w.Q,y,w.u),c=w.w,d=w.d,o=s(w.u,(1<>>4;if(0==E>>>8)b[n++]=E;else{if(256==E)break;var F=n+E-254;if(E>264){var G=w.q[E-257];F=n+(G>>>3)+r(a,o,7&G),o+=7&G}var H=d[v(a,o)&m];o+=15&H;var I=H>>>4,J=w.c[I],K=(J>>>4)+q(a,o,15&J);for(o+=15&J;F>n;)b[n]=b[n++-K],b[n]=b[n++-K],b[n]=b[n++-K],b[n]=b[n++-K];n=F}}}else{0!=(7&o)&&(o+=8-(7&o));var L=4+(o>>>3),M=a[L-4]|a[L-3]<<8;x&&(b=i.H.W(b,n+M)),b.set(new e(a.buffer,a.byteOffset+L,M),n),o=L+M<<3,n+=M}return b.length==n?b:b.slice(0,n)},i.H.W=function(a,b){var c=a.length;if(c>=b)return a;var d=new Uint8Array(c<<1);return d.set(a,0),d},i.H.R=function(a,b,c,d,e,f){for(var g=i.H.e,h=i.H.Z,j=0;c>j;){var k=a[h(d,e)&b];e+=15&k;var l=k>>>4;if(15>=l)f[j]=l,j++;else{var m=0,n=0;16==l?(n=3+g(d,e,2),e+=2,m=f[j-1]):17==l?(n=3+g(d,e,3),e+=3):18==l&&(n=11+g(d,e,7),e+=7);for(var o=j+n;o>j;)f[j]=m,j++}}return e},i.H.V=function(a,b,c,d){for(var e=0,f=0,g=d.length>>>1;c>f;){var h=a[f+b];d[f<<1]=0,d[1+(f<<1)]=h,h>e&&(e=h),f++}for(;g>f;)d[f<<1]=0,d[1+(f<<1)]=0,f++;return e},i.H.n=function(a,b){for(var c,d,e,f,g=i.H.m,h=a.length,j=g.j,k=0;b>=k;k++)j[k]=0;for(k=1;h>k;k+=2)j[a[k]]++;var l=g.K;for(c=0,j[0]=0,d=1;b>=d;d++)c=c+j[d-1]<<1,l[d]=c;for(e=0;h>e;e+=2)0!=(f=a[e+1])&&(a[e]=l[f],l[f]++)},i.H.A=function(a,b,c){for(var d=a.length,e=i.H.m.r,f=0;d>f;f+=2)if(0!=a[f+1])for(var g=f>>1,h=a[f+1],j=g<<4|h,k=b-h,l=a[f]<>>15-b]=j,l++},i.H.l=function(a,b){for(var c=i.H.m.r,d=15-b,e=0;e>>d}},i.H.M=function(a,b,c){c<<=7&b;var d=b>>>3;a[d]|=c,a[d+1]|=c>>>8},i.H.I=function(a,b,c){c<<=7&b;var d=b>>>3;a[d]|=c,a[d+1]|=c>>>8,a[d+2]|=c>>>16},i.H.e=function(a,b,c){return(a[b>>>3]|a[1+(b>>>3)]<<8)>>>(7&b)&(1<>>3]|a[1+(b>>>3)]<<8|a[2+(b>>>3)]<<16)>>>(7&b)&(1<>>3]|a[1+(b>>>3)]<<8|a[2+(b>>>3)]<<16)>>>(7&b)},i.H.i=function(a,b){return(a[b>>>3]|a[1+(b>>>3)]<<8|a[2+(b>>>3)]<<16|a[3+(b>>>3)]<<24)>>>(7&b)},i.H.m=(j=Uint16Array,k=Uint32Array,{K:new j(16),j:new j(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new j(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new k(32),J:new j(512),_:[],h:new j(32),$:[],w:new j(32768),C:[],v:[],d:new j(32768),D:[],u:new j(512),Q:[],r:new j(32768),s:new k(286),Y:new k(30),a:new k(19),t:new k(15e3),k:new j(65536),g:new j(32768)}),function(){function a(a,b,c){for(;0!=b--;)a.push(0,c)}for(var b=i.H.m,c=0;32768>c;c++){var d=c;d=(4278255360&(d=(4042322160&(d=(3435973836&(d=(2863311530&d)>>>1|(1431655765&d)<<1))>>>2|(858993459&d)<<2))>>>4|(252645135&d)<<4))>>>8|(16711935&d)<<8,b.r[c]=(d>>>16|d<<16)>>>17}for(c=0;32>c;c++)b.q[c]=b.S[c]<<3|b.T[c],b.c[c]=b.p[c]<<4|b.z[c];a(b._,144,8),a(b._,112,9),a(b._,24,7),a(b._,8,8),i.H.n(b._,9),i.H.A(b._,9,b.J),i.H.l(b._,9),a(b.$,32,5),i.H.n(b.$,5),i.H.A(b.$,5,b.h),i.H.l(b.$,5),a(b.Q,19,0),a(b.C,286,0),a(b.D,30,0),a(b.v,320,0)}(),i.H.N);return{decode:function(a){for(var d,e,f=new Uint8Array(a),h=8,i=l,j=i.readUshort,k=i.readUint,n={tabs:{},frames:[]},o=new Uint8Array(f.length),p=0,q=0,r=[137,80,78,71,13,10,26,10],s=0;8>s;s++)if(f[s]!=r[s])throw"The input is not a PNG file!";for(;hs;s++)o[p+s]=f[h+s];p+=t}else if("acTL"==u)n.tabs[u]={num_frames:k(f,h),num_plays:k(f,h+4)},e=new Uint8Array(f.length);else if("fcTL"==u){0!=q&&((d=n.frames[n.frames.length-1]).data=b(n,e.slice(0,q),d.rect.width,d.rect.height),q=0);var z={x:k(f,h+12),y:k(f,h+16),width:k(f,h+4),height:k(f,h+8)},A=j(f,h+22);A=j(f,h+20)/(0==A?100:A);var B={rect:z,delay:Math.round(1e3*A),dispose:f[h+24],blend:f[h+25]};n.frames.push(B)}else if("fdAT"==u){for(s=0;t-4>s;s++)e[q+s]=f[h+s+4];q+=t-4}else if("pHYs"==u)n.tabs[u]=[i.readUint(f,h),i.readUint(f,h+4),f[h+8]];else if("cHRM"==u)for(s=0,n.tabs[u]=[];8>s;s++)n.tabs[u].push(i.readUint(f,h+4*s));else if("tEXt"==u||"zTXt"==u){null==n.tabs[u]&&(n.tabs[u]={});var C=i.nextZero(f,h),D=i.readASCII(f,h,C-h),E=h+t-C-1;if("tEXt"==u)G=i.readASCII(f,C+1,E);else{var F=c(f.slice(C+2,C+2+E));G=i.readUTF8(F,0,F.length)}n.tabs[u][D]=G}else if("iTXt"==u){null==n.tabs[u]&&(n.tabs[u]={}),C=0,v=h,C=i.nextZero(f,v),D=i.readASCII(f,v,C-v);var G,H=f[v=C+1];f[v+1],v+=2,C=i.nextZero(f,v),i.readASCII(f,v,C-v),v=C+1,C=i.nextZero(f,v),i.readUTF8(f,v,C-v),E=t-((v=C+1)-h),0==H?G=i.readUTF8(f,v,E):(F=c(f.slice(v,v+E)),G=i.readUTF8(F,0,F.length)),n.tabs[u][D]=G}else if("PLTE"==u)n.tabs[u]=i.readBytes(f,h,t);else if("hIST"==u){var I=n.tabs.PLTE.length/3;for(s=0,n.tabs[u]=[];I>s;s++)n.tabs[u].push(j(f,h+2*s))}else if("tRNS"==u)3==n.ctype?n.tabs[u]=i.readBytes(f,h,t):0==n.ctype?n.tabs[u]=j(f,h):2==n.ctype&&(n.tabs[u]=[j(f,h),j(f,h+2),j(f,h+4)]);else if("gAMA"==u)n.tabs[u]=i.readUint(f,h)/1e5;else if("sRGB"==u)n.tabs[u]=f[h];else if("bKGD"==u)0==n.ctype||4==n.ctype?n.tabs[u]=[j(f,h)]:2==n.ctype||6==n.ctype?n.tabs[u]=[j(f,h),j(f,h+2),j(f,h+4)]:3==n.ctype&&(n.tabs[u]=f[h]);else if("IEND"==u)break;h+=t,i.readUint(f,h),h+=4}return 0!=q&&((d=n.frames[n.frames.length-1]).data=b(n,e.slice(0,q),d.rect.width,d.rect.height)),n.data=b(n,o,n.width,n.height),delete n.compress,delete n.interlace,delete n.filter,n},toRGBA8:function(b){var c=b.width,d=b.height;if(null==b.tabs.acTL)return[a(b.data,c,d,b).buffer];var e=[];null==b.frames[0].data&&(b.frames[0].data=b.data);for(var f=4*c*d,g=new Uint8Array(f),i=new Uint8Array(f),j=new Uint8Array(f),k=0;kr;r++)j[r]=g[r];if(0==l.blend?h(q,o,p,g,c,d,m,n,0):1==l.blend&&h(q,o,p,g,c,d,m,n,1),e.push(g.buffer.slice(0)),0==l.dispose);else if(1==l.dispose)h(i,o,p,g,c,d,m,n,0);else if(2==l.dispose)for(r=0;f>r;r++)g[r]=j[r]}return e},_paeth:f,_copyTile:h,_bin:l}}();!function(){function a(a,b,c,d){b[c]+=a[0]*d>>4,b[c+1]+=a[1]*d>>4,b[c+2]+=a[2]*d>>4,b[c+3]+=a[3]*d>>4}function b(a){return Math.max(0,Math.min(255,a))}function c(a,b){var c=a[0]-b[0],d=a[1]-b[1],e=a[2]-b[2],f=a[3]-b[3];return c*c+d*d+e*e+f*f}function d(d,e,f,g,h,i,j){null==j&&(j=1);for(var k=g.length,l=[],m=0;k>m;m++){var n=g[m];l.push([255&n>>>0,255&n>>>8,255&n>>>16,255&n>>>24])}for(m=0;k>m;m++)for(var o=4294967295,p=0,q=0;k>q;q++){var r=c(l[m],l[q]);q!=m&&o>r&&(o=r,p=q)}var s=new Uint32Array(h.buffer),t=new Int16Array(4*e*f),u=[0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5];for(m=0;mv;v++)for(var w=0;e>w;w++){m=4*(v*e+w),2!=j?x=[b(d[m]+t[m]),b(d[m+1]+t[m+1]),b(d[m+2]+t[m+2]),b(d[m+3]+t[m+3])]:(r=u[4*(3&v)+(3&w)],x=[b(d[m]+r),b(d[m+1]+r),b(d[m+2]+r),b(d[m+3]+r)]),p=0;var x,y=16777215;for(q=0;k>q;q++){var z=c(x,l[q]);y>z&&(y=z,p=q)}var A=l[p],B=[x[0]-A[0],x[1]-A[1],x[2]-A[2],x[3]-A[3]];1==j&&(w!=e-1&&a(B,t,m+4,7),v!=f-1&&(0!=w&&a(B,t,m+4*e-4,3),a(B,t,m+4*e,5),w!=e-1&&a(B,t,m+4*e+4,1))),i[m>>2]=p,s[m>>2]=g[p]}}function e(a,b,c,d,e){null==e&&(e={});var f,g=w.crc,h=u.writeUint,i=u.writeUshort,j=u.writeASCII,k=8,l=a.frames.length>1,m=!1,n=33+(l?20:0);if(null!=e.sRGB&&(n+=13),null!=e.pHYs&&(n+=21),null!=e.iCCP&&(n+=21+(f=pako.deflate(e.iCCP)).length+4),3==a.ctype){for(var o=a.plte.length,p=0;o>p;p++)255!=a.plte[p]>>>24&&(m=!0);n+=8+3*o+4+(m?8+1*o+4:0)}for(var q=0;qp;p++)r[p]=s[p];if(h(r,k,13),j(r,k+=4,"IHDR"),h(r,k+=4,b),h(r,k+=4,c),r[k+=4]=a.depth,r[++k]=a.ctype,r[++k]=0,r[++k]=0,r[++k]=0,h(r,++k,g(r,k-17,17)),k+=4,null!=e.sRGB&&(h(r,k,1),j(r,k+=4,"sRGB"),r[k+=4]=e.sRGB,h(r,++k,g(r,k-5,5)),k+=4),null!=e.iCCP){var t=13+f.length;h(r,k,t),j(r,k+=4,"iCCP"),j(r,k+=4,"ICC profile"),k+=11,k+=2,r.set(f,k),h(r,k+=f.length,g(r,k-(t+4),t+4)),k+=4}if(null!=e.pHYs&&(h(r,k,9),j(r,k+=4,"pHYs"),h(r,k+=4,e.pHYs[0]),h(r,k+=4,e.pHYs[1]),r[k+=4]=e.pHYs[2],h(r,++k,g(r,k-13,13)),k+=4),l&&(h(r,k,8),j(r,k+=4,"acTL"),h(r,k+=4,a.frames.length),h(r,k+=4,null!=e.loop?e.loop:0),h(r,k+=4,g(r,k-12,12)),k+=4),3==a.ctype){for(h(r,k,3*(o=a.plte.length)),j(r,k+=4,"PLTE"),k+=4,p=0;o>p;p++){var v=3*p,x=a.plte[p],y=255&x,z=255&x>>>8,A=255&x>>>16;r[k+v+0]=y,r[k+v+1]=z,r[k+v+2]=A}if(h(r,k+=3*o,g(r,k-3*o-4,3*o+4)),k+=4,m){for(h(r,k,o),j(r,k+=4,"tRNS"),k+=4,p=0;o>p;p++)r[k+p]=255&a.plte[p]>>>24;h(r,k+=o,g(r,k-o-4,o+4)),k+=4}}var B=0;for(q=0;qw;w+=4)r&=u[w+3];var x=255!=r,y=function(a,b,c,d,e,f){for(var g,j=[],k=0;kx;x++){for(var y=new Uint8Array(a[k-1-x]),z=new Uint32Array(a[k-1-x]),A=b,B=c,C=-1,D=-1,E=0;c>E;E++)for(var F=0;b>F;F++)n[N=E*b+F]!=z[N]&&(A>F&&(A=F),F>C&&(C=F),B>E&&(B=E),E>D&&(D=E));-1==C&&(A=B=C=D=0),e&&(1==(1&A)&&A--,1==(1&B)&&B--);var G=(C-A+1)*(D-B+1);w>G&&(w=G,v=x,o=A,p=B,q=C-A+1,r=D-B+1)}y=new Uint8Array(a[k-1-v]),1==v&&(j[k-1].dispose=2),l=new Uint8Array(4*q*r),t(y,b,c,l,q,r,-o,-p,0),1==(s=t(m,b,c,l,q,r,-o,-p,3)?1:0)?i(m,b,c,l,{x:o,y:p,width:q,height:r}):t(m,b,c,l,q,r,-o,-p,0)}else l=m.slice(0);j.push({rect:{x:o,y:p,width:q,height:r},img:l,blend:s,dispose:0})}if(d)for(k=0;kh;h+=4){var i=f[h],j=f[h+1],k=f[h+2],l=f[h+3];0==l&&(i=j=k=0),d[e+h]=i,d[e+h+1]=j,d[e+h+2]=k,d[e+h+3]=l}e+=g}return d.buffer}(C),E=l(D,e);for(w=0;w>2,G>>2);B.push(H);var I=new Uint8Array(E.abuf,F,G);o&&d(J.img,J.rect.width,J.rect.height,A,I,H),J.img.set(I),F+=G}}else for(s=0;sw;w++){var M=K[w];if(0!=w&&M==K[w-1])H[w]=H[w-1];else if(w>L&&M==K[w-L])H[w]=H[w-L];else{var N=z[M];if(null==N&&(z[M]=N=A.length,A.push(M),A.length>=300))break;H[w]=N}}}var O=A.length;for(256>=O&&0==n&&(q=Math.max(q=2>=O?1:4>=O?2:16>=O?4:8,m)),s=0;s=O&&0==n){R=Math.ceil(q*L/8);for(var T=new Uint8Array(R*P),U=B[s],V=0;P>V;V++){w=V*R;var W=V*L;if(8==q)for(var X=0;L>X;X++)T[w+X]=U[W+X];else if(4==q)for(X=0;L>X;X++)T[w+(X>>1)]|=U[W+X]<<4-4*(1&X);else if(2==q)for(X=0;L>X;X++)T[w+(X>>2)]|=U[W+X]<<6-2*(3&X);else if(1==q)for(X=0;L>X;X++)T[w+(X>>3)]|=U[W+X]<<7-1*(7&X)}Q=T,p=3,S=1}else if(0==x&&1==y.length){T=new Uint8Array(3*L*P); -var Y=L*P;for(w=0;Y>w;w++){var Z=3*w,$=4*w;T[Z]=Q[$],T[Z+1]=Q[$+1],T[Z+2]=Q[$+2]}Q=T,p=2,S=3,R=3*L}J.img=Q,J.bpl=R,J.bpp=S}return{ctype:p,depth:q,plte:A,frames:y}}function h(a,b,c,d,e,f,g){for(var h=Uint8Array,j=Uint32Array,k=new h(a[e-1]),l=new j(a[e-1]),m=e+1w&&(p=w),w>r&&(r=w),q>x&&(q=x),x>s&&(s=x))}-1==r&&(p=q=r=s=0),g&&(1==(1&p)&&p--,1==(1&q)&&q--),f={x:p,y:q,width:r-p+1,height:s-q+1};var A=d[e];A.rect=f,A.blend=1,A.img=new Uint8Array(4*f.width*f.height),0==d[e-1].dispose?(t(k,b,c,A.img,f.width,f.height,-f.x,-f.y,0),i(n,b,c,A.img,f)):t(n,b,c,A.img,f.width,f.height,-f.x,-f.y,0)}function i(a,b,c,d,e){t(a,b,c,d,e.width,e.height,-e.x,-e.y,2)}function j(a,b,c,d,e,f,g){var h,i=[],j=[0,1,2,3,4];-1!=f?j=[f]:(b*d>5e5||1==c)&&(j=[0]),g&&(h={level:0});for(var l=H,m=0;mn;n++)k(e,a,n,d,c,j[m]);i.push(l.deflate(e,h))}var o,p=1e9;for(m=0;md)for(var i=0;d>i;i++)a[h+i]=b[g+i];else a.set(new Uint8Array(b.buffer,g,d),h);else if(1==f){for(i=0;e>i;i++)a[h+i]=b[g+i];for(i=e;d>i;i++)a[h+i]=255&b[g+i]-b[g+i-e]+256}else if(0==c){for(i=0;e>i;i++)a[h+i]=b[g+i];if(2==f)for(i=e;d>i;i++)a[h+i]=b[g+i];if(3==f)for(i=e;d>i;i++)a[h+i]=255&b[g+i]-(b[g+i-e]>>1)+256;if(4==f)for(i=e;d>i;i++)a[h+i]=255&b[g+i]-v(b[g+i-e],0,0)+256}else{if(2==f)for(i=0;d>i;i++)a[h+i]=255&b[g+i]+256-b[g+i-d];if(3==f){for(i=0;e>i;i++)a[h+i]=255&b[g+i]+256-(b[g+i-d]>>1);for(i=e;d>i;i++)a[h+i]=255&b[g+i]+256-(b[g+i-d]+b[g+i-e]>>1)}if(4==f){for(i=0;e>i;i++)a[h+i]=255&b[g+i]+256-v(0,b[g+i-d],0);for(i=e;d>i;i++)a[h+i]=255&b[g+i]+256-v(b[g+i-e],b[g+i-d],b[g+i-e-d])}}}function l(a,b){var c,d=new Uint8Array(a),e=d.slice(0),f=new Uint32Array(e.buffer),g=m(e,b),h=g[0],i=g[1],j=d.length,k=new Uint8Array(j>>2);if(d.length<2e7)for(var l=0;j>l;l+=4)c=n(h,p=d[l]*(1/255),q=d[l+1]*(1/255),r=d[l+2]*(1/255),s=d[l+3]*(1/255)),k[l>>2]=c.ind,f[l>>2]=c.est.rgba;else for(l=0;j>l;l+=4){var p=d[l]*(1/255),q=d[l+1]*(1/255),r=d[l+2]*(1/255),s=d[l+3]*(1/255);for(c=h;c.left;)c=0>=o(c.est,p,q,r,s)?c.left:c.right;k[l>>2]=c.ind,f[l>>2]=c.est.rgba}return{abuf:e.buffer,inds:k,plte:i}}function m(a,b,c){null==c&&(c=1e-4);var d=new Uint32Array(a.buffer),e={i0:0,i1:a.length,bst:null,est:null,tdst:0,left:null,right:null};e.bst=r(a,e.i0,e.i1),e.est=s(e.bst);for(var f=[e];f.lengthg&&(g=f[i].est.L,h=i);if(c>g)break;var j=f[h],k=p(a,d,j.i0,j.i1,j.est.e,j.est.eMq255);if(j.i0>=k||j.i1<=k)j.est.L=0;else{var l={i0:j.i0,i1:k,bst:null,est:null,tdst:0,left:null,right:null};l.bst=r(a,l.i0,l.i1),l.est=s(l.bst);var m={i0:k,i1:j.i1,bst:null,est:null,tdst:0,left:null,right:null};for(i=0,m.bst={R:[],m:[],N:j.bst.N-l.bst.N};16>i;i++)m.bst.R[i]=j.bst.R[i]-l.bst.R[i];for(i=0;4>i;i++)m.bst.m[i]=j.bst.m[i]-l.bst.m[i];m.est=s(m.bst),j.left=l,j.right=m,f[h]=l,f.push(m)}}for(f.sort(function(a,b){return b.bst.N-a.bst.N}),i=0;i0&&(r=a.right,s=a.left);var t=n(r,b,c,d,e);if(t.tdst<=q*q)return t;var u=n(s,b,c,d,e);return u.tdstc;){for(;q(a,c,e)<=f;)c+=4;for(;q(a,d,e)>f;)d-=4;if(c>=d)break;var g=b[c>>2];b[c>>2]=b[d>>2],b[d>>2]=g,c+=4,d-=4}for(;q(a,c,e)>f;)c-=4;return c+4}function q(a,b,c){return a[b]*c[0]+a[b+1]*c[1]+a[b+2]*c[2]+a[b+3]*c[3]}function r(a,b,c){for(var d=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],e=[0,0,0,0],f=b;c>f;f+=4){var g=a[f]*(1/255),h=a[f+1]*(1/255),i=a[f+2]*(1/255),j=a[f+3]*(1/255);e[0]+=g,e[1]+=h,e[2]+=i,e[3]+=j,d[0]+=g*g,d[1]+=g*h,d[2]+=g*i,d[3]+=g*j,d[5]+=h*h,d[6]+=h*i,d[7]+=h*j,d[10]+=i*i,d[11]+=i*j,d[15]+=j*j}return d[4]=d[1],d[8]=d[2],d[9]=d[6],d[12]=d[3],d[13]=d[7],d[14]=d[11],{R:d,m:e,N:c-b>>2}}function s(a){var b=a.R,c=a.m,d=a.N,e=c[0],f=c[1],g=c[2],h=c[3],i=0==d?0:1/d,j=[b[0]-e*e*i,b[1]-e*f*i,b[2]-e*g*i,b[3]-e*h*i,b[4]-f*e*i,b[5]-f*f*i,b[6]-f*g*i,b[7]-f*h*i,b[8]-g*e*i,b[9]-g*f*i,b[10]-g*g*i,b[11]-g*h*i,b[12]-h*e*i,b[13]-h*f*i,b[14]-h*g*i,b[15]-h*h*i],k=j,l=x,m=[Math.random(),Math.random(),Math.random(),Math.random()],n=0,o=0;if(0!=d)for(var p=0;16>p&&(m=l.multVec(k,m),o=Math.sqrt(l.dot(m,m)),m=l.sml(1/o,m),!(0!=p&&1e-9>Math.abs(o-n)));p++)n=o;var q=[e*i,f*i,g*i,h*i];return{Cov:j,q:q,e:m,L:n,eMq255:l.dot(l.sml(255,q),m),eMq:l.dot(m,q),rgba:(Math.round(255*q[3])<<24|Math.round(255*q[2])<<16|Math.round(255*q[1])<<8|Math.round(255*q[0])<<0)>>>0}}var t=I._copyTile,u=I._bin,v=I._paeth,w={table:function(){for(var a=new Uint32Array(256),b=0;256>b;b++){for(var c=b,d=0;8>d;d++)1&c?c=3988292384^c>>>1:c>>>=1;a[b]=c}return a}(),update:function(a,b,c,d){for(var e=0;d>e;e++)a=w.table[255&(a^b[c+e])]^a>>>8;return a},crc:function(a,b,c){return 4294967295^w.update(4294967295,a,b,c)}},x={multVec:function(a,b){return[a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3],a[4]*b[0]+a[5]*b[1]+a[6]*b[2]+a[7]*b[3],a[8]*b[0]+a[9]*b[1]+a[10]*b[2]+a[11]*b[3],a[12]*b[0]+a[13]*b[1]+a[14]*b[2]+a[15]*b[3]]},dot:function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]},sml:function(a,b){return[a*b[0],a*b[1],a*b[2],a*b[3]]}};I.encode=function(a,b,c,d,h,i,j){null==d&&(d=0),null==j&&(j=!1);var k=g(a,b,c,d,[!1,!1,!1,0,j,!1]);return f(k,-1),e(k,b,c,h,i)},I.encodeLL=function(a,b,c,d,g,h,i,j){for(var k={ctype:0+(1==d?0:2)+(0==g?0:4),depth:h,frames:[]},l=(d+g)*h,m=l*b,n=0;n>>0),c(1),c(32),d(3),d(o),d(2835),d(2835),u+=8,d(16711680),d(65280),d(255),d(4278190080),d(1466527264),function w(){for(;j>t&&s>0;){for(h=122+t*n,e=0;k>e;)s--,g=(f=m[v++])>>>24,r.setUint32(h+e,f<<8|g),e+=4;t++}vb;)d=c.shift(),b+=d[0],d[1]()};return function(a,e,f){c.push([e,f]),a.once("destroy",function(){b-=e,setTimeout(d,1)}),setTimeout(d,1)}}(5242880),g.extend(c.options,{thumb:{width:110,height:110,quality:70,allowMagnify:!0,crop:!0,preserveHeaders:!1,type:"image/jpeg"},compress:{enable:!1,maxWidthOrHeight:2e3,maxSize:10485760}}),c.register({name:"image",makeThumb:function(a,b,c,e){var h,i;return a=this.request("get-file",a),a.type.match(/^image/)?(h=g.extend({},this.options.thumb),g.isPlainObject(c)&&(h=g.extend(h,c),c=null),c=c||h.width,e=e||h.height,i=new d(h),i.once("load",function(){a._info=a._info||i.info(),a._meta=a._meta||i.meta(),1>=c&&c>0&&(c=a._info.width*c),1>=e&&e>0&&(e=a._info.height*e),i.resize(c,e)}),i.once("complete",function(){b(!1,i.getAsDataUrl(h.type)),i.destroy()}),i.once("error",function(a){b(a||!0),i.destroy()}),f(i,a.source.size,function(){a._info&&i.info(a._info),a._meta&&i.meta(a._meta),i.loadFromBlob(a.source)}),void 0):(b(!0),void 0)},beforeSendFile:function(a){var c,d=this.options.compress;return a=this.request("get-file",a),d&&d.enable&&~"image/jpeg,image/jpg,image/png".indexOf(a.type)&&!a._compressed?(d=g.extend({},d),c=b.Deferred(),e(a.source.source,{maxSizeMB:d.maxSize/1024/1024,maxWidthOrHeight:d.maxWidthOrHeight}).then(function(b){d.debug&&console.log("webuploader.compress",(100*(b.size/a.size)).toFixed(2)+"%");var e=a.size;a.source.source=b,a.source.size=b.size,a.size=b.size,a.trigger("resize",b.size,e),a._compressed=!0,c.resolve()}).catch(function(a){console.error("webuploader.compress.error",a),c.resolve()}),c.promise()):void 0}})}),b("file",["base","mediator"],function(a,b){function c(){return f+g++}function d(a){this.name=a.name||"Untitled",this.size=a.size||0,this.type=a.type||"application/octet-stream",this.lastModifiedDate=a.lastModifiedDate||1*new Date,this.id=c(),this.ext=h.exec(this.name)?RegExp.$1:"",this.statusText="",i[this.id]=d.Status.INITED,this.source=a,this.loaded=0,this.on("error",function(a){this.setStatus(d.Status.ERROR,a)})}var e=a.$,f="WU_FILE_",g=0,h=/\.([^.]+)$/,i={};return e.extend(d.prototype,{setStatus:function(a,b){var c=i[this.id];"undefined"!=typeof b&&(this.statusText=b),a!==c&&(i[this.id]=a,this.trigger("statuschange",a,c))},getStatus:function(){return i[this.id]},getSource:function(){return this.source},destroy:function(){this.off(),delete i[this.id]}}),b.installTo(d.prototype),d.Status={INITED:"inited",QUEUED:"queued",PROGRESS:"progress",ERROR:"error",COMPLETE:"complete",CANCELLED:"cancelled",INTERRUPT:"interrupt",INVALID:"invalid"},d}),b("queue",["base","mediator","file"],function(a,b,c){function d(){this.stats={numOfQueue:0,numOfSuccess:0,numOfCancel:0,numOfProgress:0,numOfUploadFailed:0,numOfInvalid:0,numOfDeleted:0,numOfInterrupt:0},this._queue=[],this._map={}}var e=a.$,f=c.Status;return e.extend(d.prototype,{append:function(a){return this._queue.push(a),this._fileAdded(a),this},prepend:function(a){return this._queue.unshift(a),this._fileAdded(a),this},getFile:function(a){return"string"!=typeof a?a:this._map[a]},fetch:function(a){var b,c,d=this._queue.length;for(a=a||f.QUEUED,b=0;d>b;b++)if(c=this._queue[b],a===c.getStatus())return c;return null},sort:function(a){"function"==typeof a&&this._queue.sort(a)},getFiles:function(){for(var a,b=[].slice.call(arguments,0),c=[],d=0,f=this._queue.length;f>d;d++)a=this._queue[d],(!b.length||~e.inArray(a.getStatus(),b))&&c.push(a);return c},removeFile:function(a){var b=this._map[a.id];b&&(delete this._map[a.id],this._delFile(a),a.destroy(),this.stats.numOfDeleted++)},_fileAdded:function(a){var b=this,c=this._map[a.id];c||(this._map[a.id]=a,a.on("statuschange",function(a,c){b._onFileStatusChange(a,c)})),a.setStatus(f.QUEUED)},_delFile:function(a){for(var b=this._queue.length-1;b>=0;b--)if(this._queue[b]==a){this._queue.splice(b,1);break}},_onFileStatusChange:function(a,b){var c=this.stats;switch(b){case f.PROGRESS:c.numOfProgress--;break;case f.QUEUED:c.numOfQueue--;break;case f.ERROR:c.numOfUploadFailed--;break;case f.INVALID:c.numOfInvalid--;break;case f.INTERRUPT:c.numOfInterrupt--}switch(a){case f.QUEUED:c.numOfQueue++;break;case f.PROGRESS:c.numOfProgress++;break;case f.ERROR:c.numOfUploadFailed++;break;case f.COMPLETE:c.numOfSuccess++;break;case f.CANCELLED:c.numOfCancel++;break;case f.INVALID:c.numOfInvalid++;break;case f.INTERRUPT:c.numOfInterrupt++}}}),b.installTo(d.prototype),d}),b("widgets/queue",["base","uploader","queue","file","lib/file","runtime/client","widgets/widget"],function(a,b,c,d,e,f){var g=a.$,h=/\.\w+$/,i=d.Status;return b.register({name:"queue",init:function(b){var d,e,h,i,j,k,l,m=this;if(g.isPlainObject(b.accept)&&(b.accept=[b.accept]),b.accept){for(j=[],h=0,e=b.accept.length;e>h;h++)i=b.accept[h].extensions,i&&j.push(i);j.length&&(k="\\."+j.join(",").replace(/,/g,"$|\\.").replace(/\*/g,".*")+"$"),m.accept=new RegExp(k,"i")}return m.queue=new c,m.stats=m.queue.stats,"html5"===this.request("predict-runtime-type")?(d=a.Deferred(),this.placeholder=l=new f("Placeholder"),l.connectRuntime({runtimeOrder:"html5"},function(){m._ruid=l.getRuid(),d.resolve()}),d.promise()):void 0},_wrapFile:function(a){if(!(a instanceof d)){if(!(a instanceof e)){if(!this._ruid)throw new Error("Can't add external files.");a=new e(this._ruid,a)}a=new d(a)}return a},acceptFile:function(a){var b=!a||!a.size||this.accept&&h.exec(a.name)&&!this.accept.test(a.name);return!b},_addFile:function(a){var b=this;return a=b._wrapFile(a),b.owner.trigger("beforeFileQueued",a)?b.acceptFile(a)?(b.queue.append(a),b.owner.trigger("fileQueued",a),a):(b.owner.trigger("error","Q_TYPE_DENIED",a),void 0):void 0},getFile:function(a){return this.queue.getFile(a)},addFile:function(a){var b=this;a.length||(a=[a]),a=g.map(a,function(a){return b._addFile(a)}),a.length&&(b.owner.trigger("filesQueued",a),b.options.auto&&setTimeout(function(){b.request("start-upload")},20))},getStats:function(){return this.stats},removeFile:function(a,b){var c=this;a=a.id?a:c.queue.getFile(a),this.request("cancel-file",a),b&&this.queue.removeFile(a)},getFiles:function(){return this.queue.getFiles.apply(this.queue,arguments)},fetchFile:function(){return this.queue.fetch.apply(this.queue,arguments)},retry:function(a,b){var c,d,e,f=this;if(a)return a=a.id?a:f.queue.getFile(a),a.setStatus(i.QUEUED),b||f.request("start-upload"),void 0;for(c=f.queue.getFiles(i.ERROR),d=0,e=c.length;e>d;d++)a=c[d],a.setStatus(i.QUEUED);f.request("start-upload")},sortFiles:function(){return this.queue.sort.apply(this.queue,arguments)},reset:function(){this.owner.trigger("reset"),this.queue=new c,this.stats=this.queue.stats},destroy:function(){this.reset(),this.placeholder&&this.placeholder.destroy()}})}),b("widgets/runtime",["uploader","runtime/runtime","widgets/widget"],function(a,b){return a.support=function(){return b.hasRuntime.apply(b,arguments)},a.register({name:"runtime",init:function(){if(!this.predictRuntimeType())throw Error("Runtime Error")},predictRuntimeType:function(){var a,c,d=this.options.runtimeOrder||b.orders,e=this.type;if(!e)for(d=d.split(/\s*,\s*/g),a=0,c=d.length;c>a;a++)if(b.hasRuntime(d[a])){this.type=e=d[a];break}return e}})}),b("lib/transport",["base","runtime/client","mediator"],function(a,b,c){function d(a){var c=this;a=c.options=e.extend(!0,{},d.options,a||{}),b.call(this,"Transport"),this._blob=null,this._formData=a.formData||{},this._headers=a.headers||{},this.on("progress",this._timeout),this.on("load error",function(){c.trigger("progress",1),clearTimeout(c._timer)})}var e=a.$;return d.options={server:"",method:"POST",withCredentials:!1,fileVal:"file",timeout:12e4,formData:{},headers:{},sendAsBinary:!1},e.extend(d.prototype,{appendBlob:function(a,b,c){var d=this,e=d.options;d.getRuid()&&d.disconnectRuntime(),d.connectRuntime(b.ruid,function(){d.exec("init")}),d._blob=b,e.fileVal=a||e.fileVal,e.filename=c||e.filename},append:function(a,b){"object"==typeof a?e.extend(this._formData,a):this._formData[a]=b},setRequestHeader:function(a,b){"object"==typeof a?e.extend(this._headers,a):this._headers[a]=b},send:function(a){this.exec("send",a),this._timeout()},abort:function(){return clearTimeout(this._timer),this.exec("abort")},destroy:function(){this.trigger("destroy"),this.off(),this.exec("destroy"),this.disconnectRuntime()},getResponseHeaders:function(){return this.exec("getResponseHeaders")},getResponse:function(){return this.exec("getResponse")},getResponseAsJson:function(){return this.exec("getResponseAsJson")},getStatus:function(){return this.exec("getStatus")},_timeout:function(){var a=this,b=a.options.timeout;b&&(clearTimeout(a._timer),a._timer=setTimeout(function(){a.abort(),a.trigger("error","timeout")},b))}}),c.installTo(d.prototype),d}),b("widgets/upload",["base","uploader","file","lib/transport","widgets/widget"],function(a,b,c,d){function e(a,b){var c,d,e=[],f=a.source,g=f.size,h=b?Math.ceil(g/b):1,i=0,j=0;for(d={file:a,has:function(){return!!e.length},shift:function(){return e.shift()},unshift:function(a){e.unshift(a)}};h>j;)c=Math.min(b,g-i),e.push({file:a,start:i,end:b?i+c:g,total:g,chunks:h,chunk:j++,cuted:d}),i+=c;return a.blocks=e.concat(),a.remaning=e.length,d}var f=a.$,g=a.isPromise,h=c.Status;f.extend(b.options,{prepareNextFile:!1,chunked:!1,chunkSize:5242880,chunkRetry:2,chunkRetryDelay:1e3,threads:3,formData:{}}),b.register({name:"upload",init:function(){var b=this.owner,c=this;this.runing=!1,this.progress=!1,b.on("startUpload",function(){c.progress=!0}).on("uploadFinished",function(){c.progress=!1}),this.pool=[],this.stack=[],this.pending=[],this.remaning=0,this.__tick=a.bindFn(this._tick,this),b.on("uploadComplete",function(a){a.blocks&&f.each(a.blocks,function(a,b){b.transport&&(b.transport.abort(),b.transport.destroy()),delete b.transport}),delete a.blocks,delete a.remaning})},reset:function(){this.request("stop-upload",!0),this.runing=!1,this.pool=[],this.stack=[],this.pending=[],this.remaning=0,this._trigged=!1,this._promise=null},startUpload:function(b){var c=this;if(f.each(c.request("get-files",h.INVALID),function(){c.request("remove-file",this)}),b?(b=b.id?b:c.request("get-file",b),b.getStatus()===h.INTERRUPT?(b.setStatus(h.QUEUED),f.each(c.pool,function(a,c){c.file===b&&(c.transport&&c.transport.send(),b.setStatus(h.PROGRESS))})):b.getStatus()!==h.PROGRESS&&b.setStatus(h.QUEUED)):f.each(c.request("get-files",[h.INITED]),function(){this.setStatus(h.QUEUED)}),c.runing)return c.owner.trigger("startUpload",b),a.nextTick(c.__tick);c.runing=!0;var d=[];b||f.each(c.pool,function(a,b){var e=b.file;if(e.getStatus()===h.INTERRUPT){if(c._trigged=!1,d.push(e),b.waiting)return;b.transport?b.transport.send():c._doSend(b)}}),f.each(d,function(){this.setStatus(h.PROGRESS)}),b||f.each(c.request("get-files",h.INTERRUPT),function(){this.setStatus(h.PROGRESS)}),c._trigged=!1,a.nextTick(c.__tick),c.owner.trigger("startUpload")},stopUpload:function(b,c){var d=this;if(b===!0&&(c=b,b=null),d.runing!==!1){if(b){if(b=b.id?b:d.request("get-file",b),b.getStatus()!==h.PROGRESS&&b.getStatus()!==h.QUEUED)return;return b.setStatus(h.INTERRUPT),f.each(d.pool,function(a,e){e.file===b&&(e.transport&&e.transport.abort(),c&&(d._putback(e),d._popBlock(e)))}),d.owner.trigger("stopUpload",b),a.nextTick(d.__tick)}d.runing=!1,this._promise&&this._promise.file&&this._promise.file.setStatus(h.INTERRUPT),c&&f.each(d.pool,function(a,b){b.transport&&b.transport.abort(),b.file.setStatus(h.INTERRUPT)}),d.owner.trigger("stopUpload")}},cancelFile:function(a){a=a.id?a:this.request("get-file",a),a.blocks&&f.each(a.blocks,function(a,b){var c=b.transport;c&&(c.abort(),c.destroy(),delete b.transport)}),a.setStatus(h.CANCELLED),this.owner.trigger("fileDequeued",a)},isInProgress:function(){return!!this.progress},_getStats:function(){return this.request("get-stats")},skipFile:function(a,b){a=a.id?a:this.request("get-file",a),a.setStatus(b||h.COMPLETE),a.skipped=!0,a.blocks&&f.each(a.blocks,function(a,b){var c=b.transport;c&&(c.abort(),c.destroy(),delete b.transport)}),this.owner.trigger("uploadSkip",a)},_tick:function(){var b,c,d=this,e=d.options;return d._promise?d._promise.always(d.__tick):(d.pool.length1&&~"http,abort,server".indexOf(a.replace(/-.*/,""))&&b.retried1&&f.extend(m,{chunks:b.chunks,chunk:b.chunk}),i.trigger("uploadBeforeSend",b,m,n),l.appendBlob(j.fileVal,b.blob,k.name),l.append(m),l.setRequestHeader(n),l.send()},_finishFile:function(a,b,c){var d=this.owner;return d.request("after-send-file",arguments,function(){a.setStatus(h.COMPLETE),d.trigger("uploadSuccess",a,b,c)}).fail(function(b){a.getStatus()===h.PROGRESS&&a.setStatus(h.ERROR,b),d.trigger("uploadError",a,b)}).always(function(){d.trigger("uploadComplete",a)})},updateFileProgress:function(a){var b=0,c=0;a.blocks&&(f.each(a.blocks,function(a,b){c+=(b.percentage||0)*(b.end-b.start)}),b=c/a.size,this.owner.trigger("uploadProgress",a,b||0))},destroy:function(){clearTimeout(this.retryTimer)}})}),b("widgets/validator",["base","uploader","file","widgets/widget"],function(a,b,c){var d,e=a.$,f={};return d={addValidator:function(a,b){f[a]=b},removeValidator:function(a){delete f[a]}},b.register({name:"validator",init:function(){var b=this;a.nextTick(function(){e.each(f,function(){this.call(b.owner)})})}}),d.addValidator("fileNumLimit",function(){var a=this,b=a.options,c=0,d=parseInt(b.fileNumLimit,10),e=!0;d&&(a.on("beforeFileQueued",function(a){return this.trigger("beforeFileQueuedCheckfileNumLimit",a,c)?(c>=d&&e&&(e=!1,this.trigger("error","Q_EXCEED_NUM_LIMIT",d,a),setTimeout(function(){e=!0},1)),c>=d?!1:!0):!1}),a.on("fileQueued",function(){c++}),a.on("fileDequeued",function(){c--}),a.on("reset",function(){c=0}))}),d.addValidator("fileSizeLimit",function(){var a=this,b=a.options,c=0,d=parseInt(b.fileSizeLimit,10),e=!0;d&&(a.on("beforeFileQueued",function(a){var b=c+a.size>d;return b&&e&&(e=!1,this.trigger("error","Q_EXCEED_SIZE_LIMIT",d,a),setTimeout(function(){e=!0},1)),b?!1:!0}),a.on("fileQueued",function(a){c+=a.size}),a.on("fileDequeued",function(a){c-=a.size}),a.on("reset",function(){c=0}))}),d.addValidator("fileSingleSizeLimit",function(){var a=this,b=a.options,d=b.fileSingleSizeLimit;d&&a.on("beforeFileQueued",function(a){return a.size>d?(a.setStatus(c.Status.INVALID,"exceed_size"),this.trigger("error","F_EXCEED_SIZE",d,a),!1):void 0})}),d.addValidator("duplicate",function(){function a(a){for(var b,c=0,d=0,e=a.length;e>d;d++)b=a.charCodeAt(d),c=b+(c<<6)+(c<<16)-c;return c}var b=this,c=b.options,d={};c.duplicate||(b.on("beforeFileQueued",function(b){var c=b.__hash||(b.__hash=a(b.name+b.size+b.lastModifiedDate));return d[c]?(this.trigger("error","F_DUPLICATE",b),!1):void 0}),b.on("fileQueued",function(a){var b=a.__hash;b&&(d[b]=!0)}),b.on("fileDequeued",function(a){var b=a.__hash;b&&delete d[b]}),b.on("reset",function(){d={}}))}),d}),b("lib/md5",["runtime/client","mediator"],function(a,b){function c(){a.call(this,"Md5")}return b.installTo(c.prototype),c.prototype.loadFromBlob=function(a){var b=this;b.getRuid()&&b.disconnectRuntime(),b.connectRuntime(a.ruid,function(){b.exec("init"),b.exec("loadFromBlob",a)})},c.prototype.getResult=function(){return this.exec("getResult")},c}),b("widgets/md5",["base","uploader","lib/md5","lib/blob","widgets/widget"],function(a,b,c,d){return b.register({name:"md5",md5File:function(b,e,f){var g=new c,h=a.Deferred(),i=b instanceof d?b:this.request("get-file",b).source;return g.on("progress load",function(a){a=a||{},h.notify(a.total?a.loaded/a.total:1)}),g.on("complete",function(){h.resolve(g.getResult())}),g.on("error",function(a){h.reject(a)}),arguments.length>1&&(e=e||0,f=f||0,0>e&&(e=i.size+e),0>f&&(f=i.size+f),f=Math.min(f,i.size),i=i.slice(e,f)),g.loadFromBlob(i),h.promise()}})}),b("runtime/compbase",[],function(){function a(a,b){this.owner=a,this.options=a.options,this.getRuntime=function(){return b},this.getRuid=function(){return b.uid},this.trigger=function(){return a.trigger.apply(a,arguments)}}return a}),b("runtime/html5/runtime",["base","runtime/runtime","runtime/compbase"],function(b,c,d){function e(){var a={},d=this,e=this.destroy;c.apply(d,arguments),d.type=f,d.exec=function(c,e){var f,h=this,i=h.uid,j=b.slice(arguments,2);return g[c]&&(f=a[i]=a[i]||new g[c](h,d),f[e])?f[e].apply(f,j):void 0},d.destroy=function(){return e&&e.apply(this,arguments)}}var f="html5",g={};return b.inherits(c,{constructor:e,init:function(){var a=this;setTimeout(function(){a.trigger("ready")},1)}}),e.register=function(a,c){var e=g[a]=b.inherits(d,c);return e},a.Blob&&a.FileReader&&a.DataView&&c.addRuntime(f,e),e}),b("runtime/html5/blob",["runtime/html5/runtime","lib/blob"],function(a,b){return a.register("Blob",{slice:function(a,c){var d=this.owner.source,e=d.slice||d.webkitSlice||d.mozSlice;return d=e.call(d,a,c),new b(this.getRuid(),d)}})}),b("runtime/html5/dnd",["base","runtime/html5/runtime","lib/file"],function(a,b,c){var d=a.$,e="webuploader-dnd-";return b.register("DragAndDrop",{init:function(){var b=this.elem=this.options.container;this.dragEnterHandler=a.bindFn(this._dragEnterHandler,this),this.dragOverHandler=a.bindFn(this._dragOverHandler,this),this.dragLeaveHandler=a.bindFn(this._dragLeaveHandler,this),this.dropHandler=a.bindFn(this._dropHandler,this),this.dndOver=!1,b.on("dragenter",this.dragEnterHandler),b.on("dragover",this.dragOverHandler),b.on("dragleave",this.dragLeaveHandler),b.on("drop",this.dropHandler),this.options.disableGlobalDnd&&(d(document).on("dragover",this.dragOverHandler),d(document).on("drop",this.dropHandler))},_dragEnterHandler:function(a){var b,c=this,d=c._denied||!1;return a=a.originalEvent||a,c.dndOver||(c.dndOver=!0,b=a.dataTransfer.items,b&&b.length&&(c._denied=d=!c.trigger("accept",b)),c.elem.addClass(e+"over"),c.elem[d?"addClass":"removeClass"](e+"denied")),a.dataTransfer.dropEffect=d?"none":"copy",!1},_dragOverHandler:function(a){var b=this.elem.parent().get(0);return b&&!d.contains(b,a.currentTarget)?!1:(clearTimeout(this._leaveTimer),this._dragEnterHandler.call(this,a),!1)},_dragLeaveHandler:function(){var a,b=this;return a=function(){b.dndOver=!1,b.elem.removeClass(e+"over "+e+"denied")},clearTimeout(b._leaveTimer),b._leaveTimer=setTimeout(a,100),!1},_dropHandler:function(a){var b,f,g=this,h=g.getRuid(),i=g.elem.parent().get(0);if(i&&!d.contains(i,a.currentTarget))return!1;a=a.originalEvent||a,b=a.dataTransfer;try{f=b.getData("text/html")}catch(j){}return g.dndOver=!1,g.elem.removeClass(e+"over"),b&&!f?(g._getTansferFiles(b,function(a){g.trigger("drop",d.map(a,function(a){return new c(h,a)}))}),!1):void 0},_getTansferFiles:function(b,c){var d,e,f,g,h,i,j,k=[],l=[];for(d=b.items,e=b.files,j=!(!d||!d[0].webkitGetAsEntry),h=0,i=e.length;i>h;h++)f=e[h],g=d&&d[h],j&&g.webkitGetAsEntry().isDirectory?l.push(this._traverseDirectoryTree(g.webkitGetAsEntry(),k)):k.push(f);a.when.apply(a,l).done(function(){k.length&&c(k)})},_traverseDirectoryTree:function(b,c){var d=a.Deferred(),e=this;return b.isFile?b.file(function(a){c.push(a),d.resolve()}):b.isDirectory&&b.createReader().readEntries(function(b){var f,g=b.length,h=[],i=[];for(f=0;g>f;f++)h.push(e._traverseDirectoryTree(b[f],i));a.when.apply(a,h).then(function(){c.push.apply(c,i),d.resolve()},d.reject)}),d.promise()},destroy:function(){var a=this.elem;a&&(a.off("dragenter",this.dragEnterHandler),a.off("dragover",this.dragOverHandler),a.off("dragleave",this.dragLeaveHandler),a.off("drop",this.dropHandler),this.options.disableGlobalDnd&&(d(document).off("dragover",this.dragOverHandler),d(document).off("drop",this.dropHandler)))}})}),b("runtime/html5/filepaste",["base","runtime/html5/runtime","lib/file"],function(a,b,c){return b.register("FilePaste",{init:function(){var b,c,d,e,f=this.options,g=this.elem=f.container,h=".*";if(f.accept){for(b=[],c=0,d=f.accept.length;d>c;c++)e=f.accept[c].mimeTypes,e&&b.push(e);b.length&&(h=b.join(","),h=h.replace(/,/g,"|").replace(/\*/g,".*"))}this.accept=h=new RegExp(h,"i"),this.hander=a.bindFn(this._pasteHander,this),g.on("paste",this.hander)},_pasteHander:function(a){var b,d,e,f,g,h=[],i=this.getRuid();for(a=a.originalEvent||a,b=a.clipboardData.items,f=0,g=b.length;g>f;f++)d=b[f],"file"===d.kind&&(e=d.getAsFile())&&h.push(new c(i,e));h.length&&(a.preventDefault(),a.stopPropagation(),this.trigger("paste",h))},destroy:function(){this.elem.off("paste",this.hander)}})}),b("runtime/html5/filepicker",["base","runtime/html5/runtime"],function(a,b){var c=a.$;return b.register("FilePicker",{init:function(){var a,b,d,e,f,g=this.getRuntime().getContainer(),h=this,i=h.owner,j=h.options,k=this.label=c(document.createElement("label")),l=this.input=c(document.createElement("input"));if(l.attr("type","file"),l.attr("capture","camera"),l.attr("name",j.name),l.addClass("webuploader-element-invisible"),k.on("click",function(a){l.trigger("click"),a.stopPropagation(),i.trigger("dialogopen")}),k.css({opacity:0,width:"100%",height:"100%",display:"block",cursor:"pointer",background:"#ffffff"}),j.multiple&&l.attr("multiple","multiple"),j.accept&&j.accept.length>0){for(a=[],b=0,d=j.accept.length;d>b;b++)a.push(j.accept[b].mimeTypes); -l.attr("accept",a.join(","))}g.append(l),g.append(k),e=function(a){i.trigger(a.type)},f=function(a){var b;return 0===a.target.files.length?!1:(h.files=a.target.files,b=this.cloneNode(!0),b.value=null,this.parentNode.replaceChild(b,this),l.off(),l=c(b).on("change",f).on("mouseenter mouseleave",e),i.trigger("change"),void 0)},l.on("change",f),k.on("mouseenter mouseleave",e)},getFiles:function(){return this.files},destroy:function(){this.input.off(),this.label.off()}})}),b("runtime/html5/util",["base"],function(b){var c=a.createObjectURL&&a||a.URL&&URL.revokeObjectURL&&URL||a.webkitURL,d=b.noop,e=d;return c&&(d=function(){return c.createObjectURL.apply(c,arguments)},e=function(){return c.revokeObjectURL.apply(c,arguments)}),{createObjectURL:d,revokeObjectURL:e,dataURL2Blob:function(a){var b,c,d,e,f,g;for(g=a.split(","),b=~g[0].indexOf("base64")?atob(g[1]):decodeURIComponent(g[1]),d=new ArrayBuffer(b.length),c=new Uint8Array(d),e=0;ei&&(d=h.getUint16(i),d>=65504&&65519>=d||65534===d)&&(e=h.getUint16(i+2)+2,!(i+e>h.byteLength));){if(f=b.parsers[d],!c&&f)for(g=0;g6&&(l.imageHead=a.slice?a.slice(2,k):new Uint8Array(a).subarray(2,k))}return l}},updateImageHead:function(a,b){var c,d,e,f=this._parse(a,!0);return e=2,f.imageHead&&(e=2+f.imageHead.byteLength),d=a.slice?a.slice(e):new Uint8Array(a).subarray(e),c=new Uint8Array(b.byteLength+2+d.byteLength),c[0]=255,c[1]=216,c.set(new Uint8Array(b),2),c.set(new Uint8Array(d),b.byteLength+2),c.buffer}},a.parseMeta=function(){return b.parse.apply(b,arguments)},a.updateImageHead=function(){return b.updateImageHead.apply(b,arguments)},b}),b("runtime/html5/imagemeta/exif",["base","runtime/html5/imagemeta"],function(a,b){var c={};return c.ExifMap=function(){return this},c.ExifMap.prototype.map={Orientation:274},c.ExifMap.prototype.get=function(a){return this[a]||this[this.map[a]]},c.exifTagTypes={1:{getValue:function(a,b){return a.getUint8(b)},size:1},2:{getValue:function(a,b){return String.fromCharCode(a.getUint8(b))},size:1,ascii:!0},3:{getValue:function(a,b,c){return a.getUint16(b,c)},size:2},4:{getValue:function(a,b,c){return a.getUint32(b,c)},size:4},5:{getValue:function(a,b,c){return a.getUint32(b,c)/a.getUint32(b+4,c)},size:8},9:{getValue:function(a,b,c){return a.getInt32(b,c)},size:4},10:{getValue:function(a,b,c){return a.getInt32(b,c)/a.getInt32(b+4,c)},size:8}},c.exifTagTypes[7]=c.exifTagTypes[1],c.getExifValue=function(b,d,e,f,g,h){var i,j,k,l,m,n,o=c.exifTagTypes[f];if(!o)return a.log("Invalid Exif data: Invalid tag type."),void 0;if(i=o.size*g,j=i>4?d+b.getUint32(e+8,h):e+8,j+i>b.byteLength)return a.log("Invalid Exif data: Invalid data offset."),void 0;if(1===g)return o.getValue(b,j,h);for(k=[],l=0;g>l;l+=1)k[l]=o.getValue(b,j+l*o.size,h);if(o.ascii){for(m="",l=0;lb.byteLength)return a.log("Invalid Exif data: Invalid directory offset."),void 0;if(g=b.getUint16(d,e),h=d+2+12*g,h+4>b.byteLength)return a.log("Invalid Exif data: Invalid directory size."),void 0;for(i=0;g>i;i+=1)this.parseExifTag(b,c,d+2+12*i,e,f);return b.getUint32(h,e)},c.parseExifData=function(b,d,e,f){var g,h,i=d+10;if(1165519206===b.getUint32(d+4)){if(i+8>b.byteLength)return a.log("Invalid Exif data: Invalid segment size."),void 0;if(0!==b.getUint16(d+8))return a.log("Invalid Exif data: Missing byte alignment offset."),void 0;switch(b.getUint16(i)){case 18761:g=!0;break;case 19789:g=!1;break;default:return a.log("Invalid Exif data: Invalid byte alignment marker."),void 0}if(42!==b.getUint16(i+2,g))return a.log("Invalid Exif data: Missing TIFF marker."),void 0;h=b.getUint32(i+4,g),f.exif=new c.ExifMap,h=c.parseExifTags(b,i,i+h,g,f)}},b.parsers[65505].push(c.parseExifData),c}),b("runtime/html5/jpegencoder",[],function(){function a(a){function b(a){for(var b=[16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99],c=0;64>c;c++){var d=y((b[c]*a+50)/100);1>d?d=1:d>255&&(d=255),z[P[c]]=d}for(var e=[17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99],f=0;64>f;f++){var g=y((e[f]*a+50)/100);1>g?g=1:g>255&&(g=255),A[P[f]]=g}for(var h=[1,1.387039845,1.306562965,1.175875602,1,.785694958,.5411961,.275899379],i=0,j=0;8>j;j++)for(var k=0;8>k;k++)B[i]=1/(8*z[P[i]]*h[j]*h[k]),C[i]=1/(8*A[P[i]]*h[j]*h[k]),i++}function c(a,b){for(var c=0,d=0,e=new Array,f=1;16>=f;f++){for(var g=1;g<=a[f];g++)e[b[d]]=[],e[b[d]][0]=c,e[b[d]][1]=f,d++,c++;c*=2}return e}function d(){t=c(Q,R),u=c(U,V),v=c(S,T),w=c(W,X)}function e(){for(var a=1,b=2,c=1;15>=c;c++){for(var d=a;b>d;d++)E[32767+d]=c,D[32767+d]=[],D[32767+d][1]=c,D[32767+d][0]=d;for(var e=-(b-1);-a>=e;e++)E[32767+e]=c,D[32767+e]=[],D[32767+e][1]=c,D[32767+e][0]=b-1+e;a<<=1,b<<=1}}function f(){for(var a=0;256>a;a++)O[a]=19595*a,O[a+256>>0]=38470*a,O[a+512>>0]=7471*a+32768,O[a+768>>0]=-11059*a,O[a+1024>>0]=-21709*a,O[a+1280>>0]=32768*a+8421375,O[a+1536>>0]=-27439*a,O[a+1792>>0]=-5329*a}function g(a){for(var b=a[0],c=a[1]-1;c>=0;)b&1<J&&(255==I?(h(255),h(0)):h(I),J=7,I=0)}function h(a){H.push(N[a])}function i(a){h(255&a>>8),h(255&a)}function j(a,b){var c,d,e,f,g,h,i,j,k,l=0,m=8,n=64;for(k=0;m>k;++k){c=a[l],d=a[l+1],e=a[l+2],f=a[l+3],g=a[l+4],h=a[l+5],i=a[l+6],j=a[l+7];var o=c+j,p=c-j,q=d+i,r=d-i,s=e+h,t=e-h,u=f+g,v=f-g,w=o+u,x=o-u,y=q+s,z=q-s;a[l]=w+y,a[l+4]=w-y;var A=.707106781*(z+x);a[l+2]=x+A,a[l+6]=x-A,w=v+t,y=t+r,z=r+p;var B=.382683433*(w-z),C=.5411961*w+B,D=1.306562965*z+B,E=.707106781*y,G=p+E,H=p-E;a[l+5]=H+C,a[l+3]=H-C,a[l+1]=G+D,a[l+7]=G-D,l+=8}for(l=0,k=0;m>k;++k){c=a[l],d=a[l+8],e=a[l+16],f=a[l+24],g=a[l+32],h=a[l+40],i=a[l+48],j=a[l+56];var I=c+j,J=c-j,K=d+i,L=d-i,M=e+h,N=e-h,O=f+g,P=f-g,Q=I+O,R=I-O,S=K+M,T=K-M;a[l]=Q+S,a[l+32]=Q-S;var U=.707106781*(T+R);a[l+16]=R+U,a[l+48]=R-U,Q=P+N,S=N+L,T=L+J;var V=.382683433*(Q-T),W=.5411961*Q+V,X=1.306562965*T+V,Y=.707106781*S,Z=J+Y,$=J-Y;a[l+40]=$+W,a[l+24]=$-W,a[l+8]=Z+X,a[l+56]=Z-X,l++}var _;for(k=0;n>k;++k)_=a[k]*b[k],F[k]=_>0?0|_+.5:0|_-.5;return F}function k(){i(65504),i(16),h(74),h(70),h(73),h(70),h(0),h(1),h(1),h(0),i(1),i(1),h(0),h(0)}function l(a,b){i(65472),i(17),h(8),i(b),i(a),h(3),h(1),h(17),h(0),h(2),h(17),h(1),h(3),h(17),h(1)}function m(){i(65499),i(132),h(0);for(var a=0;64>a;a++)h(z[a]);h(1);for(var b=0;64>b;b++)h(A[b])}function n(){i(65476),i(418),h(0);for(var a=0;16>a;a++)h(Q[a+1]);for(var b=0;11>=b;b++)h(R[b]);h(16);for(var c=0;16>c;c++)h(S[c+1]);for(var d=0;161>=d;d++)h(T[d]);h(1);for(var e=0;16>e;e++)h(U[e+1]);for(var f=0;11>=f;f++)h(V[f]);h(17);for(var g=0;16>g;g++)h(W[g+1]);for(var j=0;161>=j;j++)h(X[j])}function o(){i(65498),i(12),h(3),h(1),h(0),h(2),h(17),h(3),h(17),h(0),h(63),h(0)}function p(a,b,c,d,e){for(var f,h=e[0],i=e[240],k=16,l=63,m=64,n=j(a,b),o=0;m>o;++o)G[P[o]]=n[o];var p=G[0]-c;c=G[0],0==p?g(d[0]):(f=32767+p,g(d[E[f]]),g(D[f]));for(var q=63;q>0&&0==G[q];q--);if(0==q)return g(h),c;for(var r,s=1;q>=s;){for(var t=s;0==G[s]&&q>=s;++s);var u=s-t;if(u>=k){r=u>>4;for(var v=1;r>=v;++v)g(i);u=15&u}f=32767+G[s],g(e[(u<<4)+E[f]]),g(D[f]),s++}return q!=l&&g(h),c}function q(){for(var a=String.fromCharCode,b=0;256>b;b++)N[b]=a(b)}function r(a){if(0>=a&&(a=1),a>100&&(a=100),x!=a){var c=0;c=50>a?Math.floor(5e3/a):Math.floor(200-2*a),b(c),x=a}}function s(){a||(a=50),q(),d(),e(),f(),r(a)}Math.round;var t,u,v,w,x,y=Math.floor,z=new Array(64),A=new Array(64),B=new Array(64),C=new Array(64),D=new Array(65535),E=new Array(65535),F=new Array(64),G=new Array(64),H=[],I=0,J=7,K=new Array(64),L=new Array(64),M=new Array(64),N=new Array(256),O=new Array(2048),P=[0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63],Q=[0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0],R=[0,1,2,3,4,5,6,7,8,9,10,11],S=[0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125],T=[1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250],U=[0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0],V=[0,1,2,3,4,5,6,7,8,9,10,11],W=[0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119],X=[0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,250];this.encode=function(a,b){b&&r(b),H=new Array,I=0,J=7,i(65496),k(),m(),l(a.width,a.height),n(),o();var c=0,d=0,e=0;I=0,J=7,this.encode.displayName="_encode_";for(var f,h,j,q,s,x,y,z,A,D=a.data,E=a.width,F=a.height,G=4*E,N=0;F>N;){for(f=0;G>f;){for(s=G*N+f,x=s,y=-1,z=0,A=0;64>A;A++)z=A>>3,y=4*(7&A),x=s+z*G+y,N+z>=F&&(x-=G*(N+1+z-F)),f+y>=G&&(x-=f+y-G+4),h=D[x++],j=D[x++],q=D[x++],K[A]=(O[h]+O[j+256>>0]+O[q+512>>0]>>16)-128,L[A]=(O[h+768>>0]+O[j+1024>>0]+O[q+1280>>0]>>16)-128,M[A]=(O[h+1280>>0]+O[j+1536>>0]+O[q+1792>>0]>>16)-128;c=p(K,B,c,t,v),d=p(L,C,d,u,w),e=p(M,C,e,u,w),f+=32}N+=8}if(J>=0){var P=[];P[1]=J+1,P[0]=(1<i;)e=d[4*(k-1)+3],0===e?j=k:i=k,k=j+i>>1;return f=k/c,0===f?1:f}function c(a){var b,c,d=a.naturalWidth,e=a.naturalHeight;return d*e>1048576?(b=document.createElement("canvas"),b.width=b.height=1,c=b.getContext("2d"),c.drawImage(a,-d+1,0),0===c.getImageData(0,0,1,1).data[3]):!1}return a.os.ios?a.os.ios>=7?function(a,c,d,e,f,g){var h=c.naturalWidth,i=c.naturalHeight,j=b(c,h,i);return a.getContext("2d").drawImage(c,0,0,h*j,i*j,d,e,f,g)}:function(a,d,e,f,g,h){var i,j,k,l,m,n,o,p=d.naturalWidth,q=d.naturalHeight,r=a.getContext("2d"),s=c(d),t="image/jpeg"===this.type,u=1024,v=0,w=0;for(s&&(p/=2,q/=2),r.save(),i=document.createElement("canvas"),i.width=i.height=u,j=i.getContext("2d"),k=t?b(d,p,q):1,l=Math.ceil(u*g/p),m=Math.ceil(u*h/q/k);q>v;){for(n=0,o=0;p>n;)j.clearRect(0,0,u,u),j.drawImage(d,-n,-v),r.drawImage(i,0,0,u,u,e+o,f+w,l,m),n+=u,o+=l;v+=u,w+=m}r.restore(),i=j=null}:function(b){var c=a.slice(arguments,1),d=b.getContext("2d");d.drawImage.apply(d,c)}}()})}),b("runtime/html5/transport",["base","runtime/html5/runtime"],function(a,b){var c=a.noop,d=a.$;return b.register("Transport",{init:function(){this._status=0,this._response=null},send:function(){var b,c,e,f=this.owner,g=this.options,h=this._initAjax(),i=f._blob,j=g.server;g.sendAsBinary?(j+=g.attachInfoToQuery!==!1?(/\?/.test(j)?"&":"?")+d.param(f._formData):"",c=i.getSource()):(b=new FormData,d.each(f._formData,function(a,c){b.append(a,c)}),b.append(g.fileVal,i.getSource(),g.filename||f._formData.name||"")),g.withCredentials&&"withCredentials"in h?(h.open(g.method,j,!0),h.withCredentials=!0):h.open(g.method,j),this._setRequestHeader(h,g.headers),c?(h.overrideMimeType&&h.overrideMimeType("application/octet-stream"),a.os.android?(e=new FileReader,e.onload=function(){h.send(this.result),e=e.onload=null},e.readAsArrayBuffer(c)):h.send(c)):h.send(b)},getResponse:function(){return this._response},getResponseAsJson:function(){return this._parseJson(this._response)},getResponseHeaders:function(){return this._headers},getStatus:function(){return this._status},abort:function(){var a=this._xhr;a&&(a.upload.onprogress=c,a.onreadystatechange=c,a.abort(),this._xhr=a=null)},destroy:function(){this.abort()},_parseHeader:function(a){var b={};return a&&a.replace(/^([^\:]+):(.*)$/gm,function(a,c,d){b[c.trim()]=d.trim()}),b},_initAjax:function(){var a=this,b=new XMLHttpRequest,d=this.options;return!d.withCredentials||"withCredentials"in b||"undefined"==typeof XDomainRequest||(b=new XDomainRequest),b.upload.onprogress=function(b){var c=0;return b.lengthComputable&&(c=b.loaded/b.total),a.trigger("progress",c)},b.onreadystatechange=function(){if(4===b.readyState){b.upload.onprogress=c,b.onreadystatechange=c,a._xhr=null,a._status=b.status;var d="|",e=d+b.status+d+b.statusText;return b.status>=200&&b.status<300?(a._response=b.responseText,a._headers=a._parseHeader(b.getAllResponseHeaders()),a.trigger("load")):b.status>=500&&b.status<600?(a._response=b.responseText,a._headers=a._parseHeader(b.getAllResponseHeaders()),a.trigger("error","server"+e)):a.trigger("error",a._status?"http"+e:"abort")}},a._xhr=b,b},_setRequestHeader:function(a,b){d.each(b,function(b,c){a.setRequestHeader(b,c)})},_parseJson:function(a){var b;try{b=JSON.parse(a)}catch(c){b={}}return b}})}),b("runtime/html5/md5",["runtime/html5/runtime"],function(a){var b=function(a,b){return 4294967295&a+b},c=function(a,c,d,e,f,g){return c=b(b(c,a),b(e,g)),b(c<>>32-f,d)},d=function(a,b,d,e,f,g,h){return c(b&d|~b&e,a,b,f,g,h)},e=function(a,b,d,e,f,g,h){return c(b&e|d&~e,a,b,f,g,h)},f=function(a,b,d,e,f,g,h){return c(b^d^e,a,b,f,g,h)},g=function(a,b,d,e,f,g,h){return c(d^(b|~e),a,b,f,g,h)},h=function(a,c){var h=a[0],i=a[1],j=a[2],k=a[3];h=d(h,i,j,k,c[0],7,-680876936),k=d(k,h,i,j,c[1],12,-389564586),j=d(j,k,h,i,c[2],17,606105819),i=d(i,j,k,h,c[3],22,-1044525330),h=d(h,i,j,k,c[4],7,-176418897),k=d(k,h,i,j,c[5],12,1200080426),j=d(j,k,h,i,c[6],17,-1473231341),i=d(i,j,k,h,c[7],22,-45705983),h=d(h,i,j,k,c[8],7,1770035416),k=d(k,h,i,j,c[9],12,-1958414417),j=d(j,k,h,i,c[10],17,-42063),i=d(i,j,k,h,c[11],22,-1990404162),h=d(h,i,j,k,c[12],7,1804603682),k=d(k,h,i,j,c[13],12,-40341101),j=d(j,k,h,i,c[14],17,-1502002290),i=d(i,j,k,h,c[15],22,1236535329),h=e(h,i,j,k,c[1],5,-165796510),k=e(k,h,i,j,c[6],9,-1069501632),j=e(j,k,h,i,c[11],14,643717713),i=e(i,j,k,h,c[0],20,-373897302),h=e(h,i,j,k,c[5],5,-701558691),k=e(k,h,i,j,c[10],9,38016083),j=e(j,k,h,i,c[15],14,-660478335),i=e(i,j,k,h,c[4],20,-405537848),h=e(h,i,j,k,c[9],5,568446438),k=e(k,h,i,j,c[14],9,-1019803690),j=e(j,k,h,i,c[3],14,-187363961),i=e(i,j,k,h,c[8],20,1163531501),h=e(h,i,j,k,c[13],5,-1444681467),k=e(k,h,i,j,c[2],9,-51403784),j=e(j,k,h,i,c[7],14,1735328473),i=e(i,j,k,h,c[12],20,-1926607734),h=f(h,i,j,k,c[5],4,-378558),k=f(k,h,i,j,c[8],11,-2022574463),j=f(j,k,h,i,c[11],16,1839030562),i=f(i,j,k,h,c[14],23,-35309556),h=f(h,i,j,k,c[1],4,-1530992060),k=f(k,h,i,j,c[4],11,1272893353),j=f(j,k,h,i,c[7],16,-155497632),i=f(i,j,k,h,c[10],23,-1094730640),h=f(h,i,j,k,c[13],4,681279174),k=f(k,h,i,j,c[0],11,-358537222),j=f(j,k,h,i,c[3],16,-722521979),i=f(i,j,k,h,c[6],23,76029189),h=f(h,i,j,k,c[9],4,-640364487),k=f(k,h,i,j,c[12],11,-421815835),j=f(j,k,h,i,c[15],16,530742520),i=f(i,j,k,h,c[2],23,-995338651),h=g(h,i,j,k,c[0],6,-198630844),k=g(k,h,i,j,c[7],10,1126891415),j=g(j,k,h,i,c[14],15,-1416354905),i=g(i,j,k,h,c[5],21,-57434055),h=g(h,i,j,k,c[12],6,1700485571),k=g(k,h,i,j,c[3],10,-1894986606),j=g(j,k,h,i,c[10],15,-1051523),i=g(i,j,k,h,c[1],21,-2054922799),h=g(h,i,j,k,c[8],6,1873313359),k=g(k,h,i,j,c[15],10,-30611744),j=g(j,k,h,i,c[6],15,-1560198380),i=g(i,j,k,h,c[13],21,1309151649),h=g(h,i,j,k,c[4],6,-145523070),k=g(k,h,i,j,c[11],10,-1120210379),j=g(j,k,h,i,c[2],15,718787259),i=g(i,j,k,h,c[9],21,-343485551),a[0]=b(h,a[0]),a[1]=b(i,a[1]),a[2]=b(j,a[2]),a[3]=b(k,a[3])},i=function(a){var b,c=[];for(b=0;64>b;b+=4)c[b>>2]=a.charCodeAt(b)+(a.charCodeAt(b+1)<<8)+(a.charCodeAt(b+2)<<16)+(a.charCodeAt(b+3)<<24);return c},j=function(a){var b,c=[];for(b=0;64>b;b+=4)c[b>>2]=a[b]+(a[b+1]<<8)+(a[b+2]<<16)+(a[b+3]<<24);return c},k=function(a){var b,c,d,e,f,g,j=a.length,k=[1732584193,-271733879,-1732584194,271733878];for(b=64;j>=b;b+=64)h(k,i(a.substring(b-64,b)));for(a=a.substring(b-64),c=a.length,d=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],b=0;c>b;b+=1)d[b>>2]|=a.charCodeAt(b)<<(b%4<<3);if(d[b>>2]|=128<<(b%4<<3),b>55)for(h(k,d),b=0;16>b;b+=1)d[b]=0;return e=8*j,e=e.toString(16).match(/(.*?)(.{0,8})$/),f=parseInt(e[2],16),g=parseInt(e[1],16)||0,d[14]=f,d[15]=g,h(k,d),k},l=function(a){var b,c,d,e,f,g,i=a.length,k=[1732584193,-271733879,-1732584194,271733878];for(b=64;i>=b;b+=64)h(k,j(a.subarray(b-64,b)));for(a=i>b-64?a.subarray(b-64):new Uint8Array(0),c=a.length,d=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],b=0;c>b;b+=1)d[b>>2]|=a[b]<<(b%4<<3);if(d[b>>2]|=128<<(b%4<<3),b>55)for(h(k,d),b=0;16>b;b+=1)d[b]=0;return e=8*i,e=e.toString(16).match(/(.*?)(.{0,8})$/),f=parseInt(e[2],16),g=parseInt(e[1],16)||0,d[14]=f,d[15]=g,h(k,d),k},m=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"],n=function(a){var b,c="";for(b=0;4>b;b+=1)c+=m[15&a>>8*b+4]+m[15&a>>8*b];return c},o=function(a){var b;for(b=0;b>16)+(b>>16)+(c>>16);return d<<16|65535&c}),q.prototype.append=function(a){return/[\u0080-\uFFFF]/.test(a)&&(a=unescape(encodeURIComponent(a))),this.appendBinary(a),this},q.prototype.appendBinary=function(a){this._buff+=a,this._length+=a.length;var b,c=this._buff.length;for(b=64;c>=b;b+=64)h(this._state,i(this._buff.substring(b-64,b)));return this._buff=this._buff.substr(b-64),this},q.prototype.end=function(a){var b,c,d=this._buff,e=d.length,f=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(b=0;e>b;b+=1)f[b>>2]|=d.charCodeAt(b)<<(b%4<<3);return this._finish(f,e),c=a?this._state:o(this._state),this.reset(),c},q.prototype._finish=function(a,b){var c,d,e,f=b;if(a[f>>2]|=128<<(f%4<<3),f>55)for(h(this._state,a),f=0;16>f;f+=1)a[f]=0;c=8*this._length,c=c.toString(16).match(/(.*?)(.{0,8})$/),d=parseInt(c[2],16),e=parseInt(c[1],16)||0,a[14]=d,a[15]=e,h(this._state,a)},q.prototype.reset=function(){return this._buff="",this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},q.prototype.destroy=function(){delete this._state,delete this._buff,delete this._length},q.hash=function(a,b){/[\u0080-\uFFFF]/.test(a)&&(a=unescape(encodeURIComponent(a)));var c=k(a);return b?c:o(c)},q.hashBinary=function(a,b){var c=k(a);return b?c:o(c)},q.ArrayBuffer=function(){this.reset()},q.ArrayBuffer.prototype.append=function(a){var b,c=this._concatArrayBuffer(this._buff,a),d=c.length;for(this._length+=a.byteLength,b=64;d>=b;b+=64)h(this._state,j(c.subarray(b-64,b)));return this._buff=d>b-64?c.subarray(b-64):new Uint8Array(0),this},q.ArrayBuffer.prototype.end=function(a){var b,c,d=this._buff,e=d.length,f=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(b=0;e>b;b+=1)f[b>>2]|=d[b]<<(b%4<<3);return this._finish(f,e),c=a?this._state:o(this._state),this.reset(),c},q.ArrayBuffer.prototype._finish=q.prototype._finish,q.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array(0),this._length=0,this._state=[1732584193,-271733879,-1732584194,271733878],this},q.ArrayBuffer.prototype.destroy=q.prototype.destroy,q.ArrayBuffer.prototype._concatArrayBuffer=function(a,b){var c=a.length,d=new Uint8Array(c+b.byteLength);return d.set(a),d.set(new Uint8Array(b),c),d},q.ArrayBuffer.hash=function(a,b){var c=l(new Uint8Array(a));return b?c:o(c)},a.register("Md5",{init:function(){},loadFromBlob:function(a){var b,c,d=a.getSource(),e=2097152,f=Math.ceil(d.size/e),g=0,h=this.owner,i=new q.ArrayBuffer,j=this,k=d.mozSlice||d.webkitSlice||d.slice;c=new FileReader,b=function(){var l,m;l=g*e,m=Math.min(l+e,d.size),c.onload=function(b){i.append(b.target.result),h.trigger("progress",{total:a.size,loaded:m})},c.onloadend=function(){c.onloadend=c.onload=null,++g child + * @grammar Base.inherits( super, protos ) => child + * @grammar Base.inherits( super, protos, statics ) => child + * @param {Class} super 父类 + * @param {Object | Function} [protos] 子类或者对象。如果对象中包含constructor,子类将是用此属性值。 + * @param {Function} [protos.constructor] 子类构造器,不指定的话将创建个临时的直接执行父类构造器的方法。 + * @param {Object} [statics] 静态属性或方法。 + * @return {Class} 返回子类。 + * @example + * function Person() { + * console.log( 'Super' ); + * } + * Person.prototype.hello = function() { + * console.log( 'hello' ); + * }; + * + * var Manager = Base.inherits( Person, { + * world: function() { + * console.log( 'World' ); + * } + * }); + * + * // 因为没有指定构造器,父类的构造器将会执行。 + * var instance = new Manager(); // => Super + * + * // 继承子父类的方法 + * instance.hello(); // => hello + * instance.world(); // => World + * + * // 子类的__super__属性指向父类 + * console.log( Manager.__super__ === Person ); // => true + */ + inherits: function( Super, protos, staticProtos ) { + var child; + + if ( typeof protos === 'function' ) { + child = protos; + protos = null; + } else if ( protos && protos.hasOwnProperty('constructor') ) { + child = protos.constructor; + } else { + child = function() { + return Super.apply( this, arguments ); + }; + } + + // 复制静态方法 + $.extend( true, child, Super, staticProtos || {} ); + + /* jshint camelcase: false */ + + // 让子类的__super__属性指向父类。 + child.__super__ = Super.prototype; + + // 构建原型,添加原型方法或属性。 + // 暂时用Object.create实现。 + child.prototype = createObject( Super.prototype ); + protos && $.extend( true, child.prototype, protos ); + + return child; + }, + + /** + * 一个不做任何事情的方法。可以用来赋值给默认的callback. + * @method noop + */ + noop: noop, + + /** + * 返回一个新的方法,此方法将已指定的`context`来执行。 + * @grammar Base.bindFn( fn, context ) => Function + * @method bindFn + * @example + * var doSomething = function() { + * console.log( this.name ); + * }, + * obj = { + * name: 'Object Name' + * }, + * aliasFn = Base.bind( doSomething, obj ); + * + * aliasFn(); // => Object Name + * + */ + bindFn: bindFn, + + /** + * 引用Console.log如果存在的话,否则引用一个[空函数noop](#WebUploader:Base.noop)。 + * @grammar Base.log( args... ) => undefined + * @method log + */ + log: (function() { + if ( window.console ) { + return bindFn( console.log, console ); + } + return noop; + })(), + + nextTick: (function() { + + return function( cb ) { + setTimeout( cb, 1 ); + }; + + // @bug 当浏览器不在当前窗口时就停了。 + // var next = window.requestAnimationFrame || + // window.webkitRequestAnimationFrame || + // window.mozRequestAnimationFrame || + // function( cb ) { + // window.setTimeout( cb, 1000 / 60 ); + // }; + + // // fix: Uncaught TypeError: Illegal invocation + // return bindFn( next, window ); + })(), + + /** + * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。 + * 将用来将非数组对象转化成数组对象。 + * @grammar Base.slice( target, start[, end] ) => Array + * @method slice + * @example + * function doSomthing() { + * var args = Base.slice( arguments, 1 ); + * console.log( args ); + * } + * + * doSomthing( 'ignored', 'arg2', 'arg3' ); // => Array ["arg2", "arg3"] + */ + slice: uncurryThis( [].slice ), + + /** + * 生成唯一的ID + * @method guid + * @grammar Base.guid() => String + * @grammar Base.guid( prefx ) => String + */ + guid: (function() { + var counter = 0; + + return function( prefix ) { + var guid = (+new Date()).toString( 32 ), + i = 0; + + for ( ; i < 5; i++ ) { + guid += Math.floor( Math.random() * 65535 ).toString( 32 ); + } + + return (prefix || 'wu_') + guid + (counter++).toString( 32 ); + }; + })(), + + /** + * 格式化文件大小, 输出成带单位的字符串 + * @method formatSize + * @grammar Base.formatSize( size ) => String + * @grammar Base.formatSize( size, pointLength ) => String + * @grammar Base.formatSize( size, pointLength, units ) => String + * @param {Number} size 文件大小 + * @param {Number} [pointLength=2] 精确到的小数点数。 + * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节,到千字节,一直往上指定。如果单位数组里面只指定了到了K(千字节),同时文件大小大于M, 此方法的输出将还是显示成多少K. + * @example + * console.log( Base.formatSize( 100 ) ); // => 100B + * console.log( Base.formatSize( 1024 ) ); // => 1.00K + * console.log( Base.formatSize( 1024, 0 ) ); // => 1K + * console.log( Base.formatSize( 1024 * 1024 ) ); // => 1.00M + * console.log( Base.formatSize( 1024 * 1024 * 1024 ) ); // => 1.00G + * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) ); // => 1024MB + */ + formatSize: function( size, pointLength, units ) { + var unit; + + units = units || [ 'B', 'K', 'M', 'G', 'TB' ]; + + while ( (unit = units.shift()) && size > 1024 ) { + size = size / 1024; + } + + return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) + + unit; + } + }; + }); + /** + * 事件处理类,可以独立使用,也可以扩展给对象使用。 + * @fileOverview Mediator + */ + define('mediator',[ + 'base' + ], function( Base ) { + var $ = Base.$, + slice = [].slice, + separator = /\s+/, + protos; + + // 根据条件过滤出事件handlers. + function findHandlers( arr, name, callback, context ) { + return $.grep( arr, function( handler ) { + return handler && + (!name || handler.e === name) && + (!callback || handler.cb === callback || + handler.cb._cb === callback) && + (!context || handler.ctx === context); + }); + } + + function eachEvent( events, callback, iterator ) { + // 不支持对象,只支持多个event用空格隔开 + $.each( (events || '').split( separator ), function( _, key ) { + iterator( key, callback ); + }); + } + + function triggerHanders( events, args ) { + var stoped = false, + i = -1, + len = events.length, + handler; + + while ( ++i < len ) { + handler = events[ i ]; + + if ( handler.cb.apply( handler.ctx2, args ) === false ) { + stoped = true; + break; + } + } + + return !stoped; + } + + protos = { + + /** + * 绑定事件。 + * + * `callback`方法在执行时,arguments将会来源于trigger的时候携带的参数。如 + * ```javascript + * var obj = {}; + * + * // 使得obj有事件行为 + * Mediator.installTo( obj ); + * + * obj.on( 'testa', function( arg1, arg2 ) { + * console.log( arg1, arg2 ); // => 'arg1', 'arg2' + * }); + * + * obj.trigger( 'testa', 'arg1', 'arg2' ); + * ``` + * + * 如果`callback`中,某一个方法`return false`了,则后续的其他`callback`都不会被执行到。 + * 切会影响到`trigger`方法的返回值,为`false`。 + * + * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处, + * 就是第一个参数为`type`,记录当前是什么事件在触发。此类`callback`的优先级比脚低,会再正常`callback`执行完后触发。 + * ```javascript + * obj.on( 'all', function( type, arg1, arg2 ) { + * console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2' + * }); + * ``` + * + * @method on + * @grammar on( name, callback[, context] ) => self + * @param {String} name 事件名,支持多个事件用空格隔开 + * @param {Function} callback 事件处理器 + * @param {Object} [context] 事件处理器的上下文。 + * @return {self} 返回自身,方便链式 + * @chainable + * @class Mediator + */ + on: function( name, callback, context ) { + var me = this, + set; + + if ( !callback ) { + return this; + } + + set = this._events || (this._events = []); + + eachEvent( name, callback, function( name, callback ) { + var handler = { e: name }; + + handler.cb = callback; + handler.ctx = context; + handler.ctx2 = context || me; + handler.id = set.length; + + set.push( handler ); + }); + + return this; + }, + + /** + * 绑定事件,且当handler执行完后,自动解除绑定。 + * @method once + * @grammar once( name, callback[, context] ) => self + * @param {String} name 事件名 + * @param {Function} callback 事件处理器 + * @param {Object} [context] 事件处理器的上下文。 + * @return {self} 返回自身,方便链式 + * @chainable + */ + once: function( name, callback, context ) { + var me = this; + + if ( !callback ) { + return me; + } + + eachEvent( name, callback, function( name, callback ) { + var once = function() { + me.off( name, once ); + return callback.apply( context || me, arguments ); + }; + + once._cb = callback; + me.on( name, once, context ); + }); + + return me; + }, + + /** + * 解除事件绑定 + * @method off + * @grammar off( [name[, callback[, context] ] ] ) => self + * @param {String} [name] 事件名 + * @param {Function} [callback] 事件处理器 + * @param {Object} [context] 事件处理器的上下文。 + * @return {self} 返回自身,方便链式 + * @chainable + */ + off: function( name, cb, ctx ) { + var events = this._events; + + if ( !events ) { + return this; + } + + if ( !name && !cb && !ctx ) { + this._events = []; + return this; + } + + eachEvent( name, cb, function( name, cb ) { + $.each( findHandlers( events, name, cb, ctx ), function() { + delete events[ this.id ]; + }); + }); + + return this; + }, + + /** + * 触发事件 + * @method trigger + * @grammar trigger( name[, args...] ) => self + * @param {String} type 事件名 + * @param {*} [...] 任意参数 + * @return {Boolean} 如果handler中return false了,则返回false, 否则返回true + */ + trigger: function( type ) { + var args, events, allEvents; + + if ( !this._events || !type ) { + return this; + } + + args = slice.call( arguments, 1 ); + events = findHandlers( this._events, type ); + allEvents = findHandlers( this._events, 'all' ); + + return triggerHanders( events, args ) && + triggerHanders( allEvents, arguments ); + } + }; + + /** + * 中介者,它本身是个单例,但可以通过[installTo](#WebUploader:Mediator:installTo)方法,使任何对象具备事件行为。 + * 主要目的是负责模块与模块之间的合作,降低耦合度。 + * + * @class Mediator + */ + return $.extend({ + + /** + * 可以通过这个接口,使任何对象具备事件功能。 + * @method installTo + * @param {Object} obj 需要具备事件行为的对象。 + * @return {Object} 返回obj. + */ + installTo: function( obj ) { + return $.extend( obj, protos ); + } + + }, protos ); + }); + /** + * @fileOverview Uploader上传类 + */ + define('uploader',[ + 'base', + 'mediator' + ], function( Base, Mediator ) { + + var $ = Base.$; + + /** + * 上传入口类。 + * @class Uploader + * @constructor + * @grammar new Uploader( opts ) => Uploader + * @example + * var uploader = WebUploader.Uploader({ + * swf: 'path_of_swf/Uploader.swf', + * + * // 开起分片上传。 + * chunked: true + * }); + */ + function Uploader( opts ) { + this.options = $.extend( true, {}, Uploader.options, opts ); + this._init( this.options ); + } + + // default Options + // widgets中有相应扩展 + Uploader.options = { + // 是否开启调试模式 + debug: false, + }; + Mediator.installTo( Uploader.prototype ); + + // 批量添加纯命令式方法。 + $.each({ + upload: 'start-upload', + stop: 'stop-upload', + getFile: 'get-file', + getFiles: 'get-files', + addFile: 'add-file', + addFiles: 'add-file', + sort: 'sort-files', + removeFile: 'remove-file', + cancelFile: 'cancel-file', + skipFile: 'skip-file', + retry: 'retry', + isInProgress: 'is-in-progress', + makeThumb: 'make-thumb', + md5File: 'md5-file', + getDimension: 'get-dimension', + addButton: 'add-btn', + predictRuntimeType: 'predict-runtime-type', + refresh: 'refresh', + disable: 'disable', + enable: 'enable', + reset: 'reset' + }, function( fn, command ) { + Uploader.prototype[ fn ] = function() { + return this.request( command, arguments ); + }; + }); + + $.extend( Uploader.prototype, { + state: 'pending', + + _init: function( opts ) { + var me = this; + + me.request( 'init', opts, function() { + me.state = 'ready'; + me.trigger('ready'); + }); + }, + + /** + * 获取或者设置Uploader配置项。 + * @method option + * @grammar option( key ) => * + * @grammar option( key, val ) => self + * @example + * + * // 初始状态图片上传前不会压缩 + * var uploader = new WebUploader.Uploader({ + * compress: null; + * }); + * + * // 修改后图片上传前,尝试将图片压缩到1600 * 1600 + * uploader.option( 'compress', { + * width: 1600, + * height: 1600 + * }); + */ + option: function( key, val ) { + var opts = this.options; + + // setter + if ( arguments.length > 1 ) { + + if ( $.isPlainObject( val ) && + $.isPlainObject( opts[ key ] ) ) { + $.extend( opts[ key ], val ); + } else { + opts[ key ] = val; + } + + } else { // getter + return key ? opts[ key ] : opts; + } + }, + + /** + * 获取文件统计信息。返回一个包含一下信息的对象。 + * * `successNum` 上传成功的文件数 + * * `progressNum` 上传中的文件数 + * * `cancelNum` 被删除的文件数 + * * `invalidNum` 无效的文件数 + * * `uploadFailNum` 上传失败的文件数 + * * `queueNum` 还在队列中的文件数 + * * `interruptNum` 被暂停的文件数 + * @method getStats + * @grammar getStats() => Object + */ + getStats: function() { + // return this._mgr.getStats.apply( this._mgr, arguments ); + var stats = this.request('get-stats'); + + return stats ? { + successNum: stats.numOfSuccess, + progressNum: stats.numOfProgress, + + // who care? + // queueFailNum: 0, + cancelNum: stats.numOfCancel, + invalidNum: stats.numOfInvalid, + uploadFailNum: stats.numOfUploadFailed, + queueNum: stats.numOfQueue, + interruptNum: stats.numOfInterrupt + } : {}; + }, + + // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器 + trigger: function( type/*, args...*/ ) { + var args = [].slice.call( arguments, 1 ), + opts = this.options, + name = 'on' + type.substring( 0, 1 ).toUpperCase() + + type.substring( 1 ); + + if ( + // 调用通过on方法注册的handler. + Mediator.trigger.apply( this, arguments ) === false || + + // 调用opts.onEvent + $.isFunction( opts[ name ] ) && + opts[ name ].apply( this, args ) === false || + + // 调用this.onEvent + $.isFunction( this[ name ] ) && + this[ name ].apply( this, args ) === false || + + // 广播所有uploader的事件。 + Mediator.trigger.apply( Mediator, + [ this, type ].concat( args ) ) === false ) { + + return false; + } + + return true; + }, + + /** + * 销毁 webuploader 实例 + * @method destroy + * @grammar destroy() => undefined + */ + destroy: function() { + this.request( 'destroy', arguments ); + this.off(); + }, + + // widgets/widget.js将补充此方法的详细文档。 + request: Base.noop + }); + + /** + * 创建Uploader实例,等同于new Uploader( opts ); + * @method create + * @class Base + * @static + * @grammar Base.create( opts ) => Uploader + */ + Base.create = Uploader.create = function( opts ) { + return new Uploader( opts ); + }; + + // 暴露Uploader,可以通过它来扩展业务逻辑。 + Base.Uploader = Uploader; + + return Uploader; + }); + + /** + * @fileOverview Runtime管理器,负责Runtime的选择, 连接 + */ + define('runtime/runtime',[ + 'base', + 'mediator' + ], function( Base, Mediator ) { + + var $ = Base.$, + factories = {}, + + // 获取对象的第一个key + getFirstKey = function( obj ) { + for ( var key in obj ) { + if ( obj.hasOwnProperty( key ) ) { + return key; + } + } + return null; + }; + + // 接口类。 + function Runtime( options ) { + this.options = $.extend({ + container: document.body + }, options ); + this.uid = Base.guid('rt_'); + } + + $.extend( Runtime.prototype, { + + getContainer: function() { + var opts = this.options, + parent, container; + + if ( this._container ) { + return this._container; + } + + parent = $( opts.container || document.body ); + container = $( document.createElement('div') ); + + container.attr( 'id', 'rt_' + this.uid ); + container.css({ + position: 'absolute', + top: '0px', + left: '0px', + width: '1px', + height: '1px', + overflow: 'hidden' + }); + + parent.append( container ); + parent.addClass('webuploader-container'); + this._container = container; + this._parent = parent; + return container; + }, + + init: Base.noop, + exec: Base.noop, + + destroy: function() { + this._container && this._container.remove(); + this._parent && this._parent.removeClass('webuploader-container'); + this.off(); + } + }); + + Runtime.orders = 'html5,flash'; + + + /** + * 添加Runtime实现。 + * @param {String} type 类型 + * @param {Runtime} factory 具体Runtime实现。 + */ + Runtime.addRuntime = function( type, factory ) { + factories[ type ] = factory; + }; + + Runtime.hasRuntime = function( type ) { + return !!(type ? factories[ type ] : getFirstKey( factories )); + }; + + Runtime.create = function( opts, orders ) { + var type, runtime; + + orders = orders || Runtime.orders; + $.each( orders.split( /\s*,\s*/g ), function() { + if ( factories[ this ] ) { + type = this; + return false; + } + }); + + type = type || getFirstKey( factories ); + + if ( !type ) { + throw new Error('Runtime Error'); + } + + runtime = new factories[ type ]( opts ); + return runtime; + }; + + Mediator.installTo( Runtime.prototype ); + return Runtime; + }); + + /** + * @fileOverview Runtime管理器,负责Runtime的选择, 连接 + */ + define('runtime/client',[ + 'base', + 'mediator', + 'runtime/runtime' + ], function( Base, Mediator, Runtime ) { + + var cache; + + cache = (function() { + var obj = {}; + + return { + add: function( runtime ) { + obj[ runtime.uid ] = runtime; + }, + + get: function( ruid, standalone ) { + var i; + + if ( ruid ) { + return obj[ ruid ]; + } + + for ( i in obj ) { + // 有些类型不能重用,比如filepicker. + if ( standalone && obj[ i ].__standalone ) { + continue; + } + + return obj[ i ]; + } + + return null; + }, + + remove: function( runtime ) { + delete obj[ runtime.uid ]; + } + }; + })(); + + function RuntimeClient( component, standalone ) { + var deferred = Base.Deferred(), + runtime; + + this.uid = Base.guid('client_'); + + // 允许runtime没有初始化之前,注册一些方法在初始化后执行。 + this.runtimeReady = function( cb ) { + return deferred.done( cb ); + }; + + this.connectRuntime = function( opts, cb ) { + + // already connected. + if ( runtime ) { + throw new Error('already connected!'); + } + + deferred.done( cb ); + + if ( typeof opts === 'string' && cache.get( opts ) ) { + runtime = cache.get( opts ); + } + + // 像filePicker只能独立存在,不能公用。 + runtime = runtime || cache.get( null, standalone ); + + // 需要创建 + if ( !runtime ) { + runtime = Runtime.create( opts, opts.runtimeOrder ); + runtime.__promise = deferred.promise(); + runtime.once( 'ready', deferred.resolve ); + runtime.init(); + cache.add( runtime ); + runtime.__client = 1; + } else { + // 来自cache + Base.$.extend( runtime.options, opts ); + runtime.__promise.then( deferred.resolve ); + runtime.__client++; + } + + standalone && (runtime.__standalone = standalone); + return runtime; + }; + + this.getRuntime = function() { + return runtime; + }; + + this.disconnectRuntime = function() { + if ( !runtime ) { + return; + } + + runtime.__client--; + + if ( runtime.__client <= 0 ) { + cache.remove( runtime ); + delete runtime.__promise; + runtime.destroy(); + } + + runtime = null; + }; + + this.exec = function() { + if ( !runtime ) { + return; + } + + var args = Base.slice( arguments ); + component && args.unshift( component ); + + return runtime.exec.apply( this, args ); + }; + + this.getRuid = function() { + return runtime && runtime.uid; + }; + + this.destroy = (function( destroy ) { + return function() { + destroy && destroy.apply( this, arguments ); + this.trigger('destroy'); + this.off(); + this.exec('destroy'); + this.disconnectRuntime(); + }; + })( this.destroy ); + } + + Mediator.installTo( RuntimeClient.prototype ); + return RuntimeClient; + }); + /** + * @fileOverview 错误信息 + */ + define('lib/dnd',[ + 'base', + 'mediator', + 'runtime/client' + ], function( Base, Mediator, RuntimeClent ) { + + var $ = Base.$; + + function DragAndDrop( opts ) { + opts = this.options = $.extend({}, DragAndDrop.options, opts ); + + opts.container = $( opts.container ); + + if ( !opts.container.length ) { + return; + } + + RuntimeClent.call( this, 'DragAndDrop' ); + } + + DragAndDrop.options = { + accept: null, + disableGlobalDnd: false + }; + + Base.inherits( RuntimeClent, { + constructor: DragAndDrop, + + init: function() { + var me = this; + + me.connectRuntime( me.options, function() { + me.exec('init'); + me.trigger('ready'); + }); + } + }); + + Mediator.installTo( DragAndDrop.prototype ); + + return DragAndDrop; + }); + /** + * @fileOverview 组件基类。 + */ + define('widgets/widget',[ + 'base', + 'uploader' + ], function( Base, Uploader ) { + + var $ = Base.$, + _init = Uploader.prototype._init, + _destroy = Uploader.prototype.destroy, + IGNORE = {}, + widgetClass = []; + + function isArrayLike( obj ) { + if ( !obj ) { + return false; + } + + var length = obj.length, + type = $.type( obj ); + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === 'array' || type !== 'function' && type !== 'string' && + (length === 0 || typeof length === 'number' && length > 0 && + (length - 1) in obj); + } + + function Widget( uploader ) { + this.owner = uploader; + this.options = uploader.options; + } + + $.extend( Widget.prototype, { + + init: Base.noop, + + // 类Backbone的事件监听声明,监听uploader实例上的事件 + // widget直接无法监听事件,事件只能通过uploader来传递 + invoke: function( apiName, args ) { + + /* + { + 'make-thumb': 'makeThumb' + } + */ + var map = this.responseMap; + + // 如果无API响应声明则忽略 + if ( !map || !(apiName in map) || !(map[ apiName ] in this) || + !$.isFunction( this[ map[ apiName ] ] ) ) { + + return IGNORE; + } + + return this[ map[ apiName ] ].apply( this, args ); + + }, + + /** + * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。 + * @method request + * @grammar request( command, args ) => * | Promise + * @grammar request( command, args, callback ) => Promise + * @for Uploader + */ + request: function() { + return this.owner.request.apply( this.owner, arguments ); + } + }); + + // 扩展Uploader. + $.extend( Uploader.prototype, { + + /** + * @property {String | Array} [disableWidgets=undefined] + * @namespace options + * @for Uploader + * @description 默认所有 Uploader.register 了的 widget 都会被加载,如果禁用某一部分,请通过此 option 指定黑名单。 + */ + + // 覆写_init用来初始化widgets + _init: function() { + var me = this, + widgets = me._widgets = [], + deactives = me.options.disableWidgets || ''; + + $.each( widgetClass, function( _, klass ) { + (!deactives || !~deactives.indexOf( klass._name )) && + widgets.push( new klass( me ) ); + }); + + return _init.apply( me, arguments ); + }, + + request: function( apiName, args, callback ) { + var i = 0, + widgets = this._widgets, + len = widgets && widgets.length, + rlts = [], + dfds = [], + widget, rlt, promise, key; + + args = isArrayLike( args ) ? args : [ args ]; + + for ( ; i < len; i++ ) { + widget = widgets[ i ]; + rlt = widget.invoke( apiName, args ); + + if ( rlt !== IGNORE ) { + + // Deferred对象 + if ( Base.isPromise( rlt ) ) { + dfds.push( rlt ); + } else { + rlts.push( rlt ); + } + } + } + + // 如果有callback,则用异步方式。 + if ( callback || dfds.length ) { + promise = Base.when.apply( Base, dfds ); + key = promise.pipe ? 'pipe' : 'then'; + + // 很重要不能删除。删除了会死循环。 + // 保证执行顺序。让callback总是在下一个 tick 中执行。 + return promise[ key ](function() { + var deferred = Base.Deferred(), + args = arguments; + + if ( args.length === 1 ) { + args = args[ 0 ]; + } + + setTimeout(function() { + deferred.resolve( args ); + }, 1 ); + + return deferred.promise(); + })[ callback ? key : 'done' ]( callback || Base.noop ); + } else { + return rlts[ 0 ]; + } + }, + + destroy: function() { + _destroy.apply( this, arguments ); + this._widgets = null; + } + }); + + /** + * 添加组件 + * @grammar Uploader.register(proto); + * @grammar Uploader.register(map, proto); + * @param {object} responseMap API 名称与函数实现的映射 + * @param {object} proto 组件原型,构造函数通过 constructor 属性定义 + * @method Uploader.register + * @for Uploader + * @example + * Uploader.register({ + * 'make-thumb': 'makeThumb' + * }, { + * init: function( options ) {}, + * makeThumb: function() {} + * }); + * + * Uploader.register({ + * 'make-thumb': function() { + * + * } + * }); + */ + Uploader.register = Widget.register = function( responseMap, widgetProto ) { + var map = { init: 'init', destroy: 'destroy', name: 'anonymous' }, + klass; + + if ( arguments.length === 1 ) { + widgetProto = responseMap; + + // 自动生成 map 表。 + $.each(widgetProto, function(key) { + if ( key[0] === '_' || key === 'name' ) { + key === 'name' && (map.name = widgetProto.name); + return; + } + + map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key; + }); + + } else { + map = $.extend( map, responseMap ); + } + + widgetProto.responseMap = map; + klass = Base.inherits( Widget, widgetProto ); + klass._name = map.name; + widgetClass.push( klass ); + + return klass; + }; + + /** + * 删除插件,只有在注册时指定了名字的才能被删除。 + * @grammar Uploader.unRegister(name); + * @param {string} name 组件名字 + * @method Uploader.unRegister + * @for Uploader + * @example + * + * Uploader.register({ + * name: 'custom', + * + * 'make-thumb': function() { + * + * } + * }); + * + * Uploader.unRegister('custom'); + */ + Uploader.unRegister = Widget.unRegister = function( name ) { + if ( !name || name === 'anonymous' ) { + return; + } + + // 删除指定的插件。 + for ( var i = widgetClass.length; i--; ) { + if ( widgetClass[i]._name === name ) { + widgetClass.splice(i, 1) + } + } + }; + + return Widget; + }); + /** + * @fileOverview DragAndDrop Widget。 + */ + define('widgets/filednd',[ + 'base', + 'uploader', + 'lib/dnd', + 'widgets/widget' + ], function( Base, Uploader, Dnd ) { + var $ = Base.$; + + Uploader.options.dnd = ''; + + /** + * @property {Selector} [dnd=undefined] 指定Drag And Drop拖拽的容器,如果不指定,则不启动。 + * @namespace options + * @for Uploader + */ + + /** + * @property {Selector} [disableGlobalDnd=false] 是否禁掉整个页面的拖拽功能,如果不禁用,图片拖进来的时候会默认被浏览器打开。 + * @namespace options + * @for Uploader + */ + + /** + * @event dndAccept + * @param {DataTransferItemList} items DataTransferItem + * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API,且只能通过 mime-type 验证。 + * @for Uploader + */ + return Uploader.register({ + name: 'dnd', + + init: function( opts ) { + + if ( !opts.dnd || + this.request('predict-runtime-type') !== 'html5' ) { + return; + } + + var me = this, + deferred = Base.Deferred(), + options = $.extend({}, { + disableGlobalDnd: opts.disableGlobalDnd, + container: opts.dnd, + accept: opts.accept + }), + dnd; + + this.dnd = dnd = new Dnd( options ); + + dnd.once( 'ready', deferred.resolve ); + dnd.on( 'drop', function( files ) { + me.request( 'add-file', [ files ]); + }); + + // 检测文件是否全部允许添加。 + dnd.on( 'accept', function( items ) { + return me.owner.trigger( 'dndAccept', items ); + }); + + dnd.init(); + + return deferred.promise(); + }, + + destroy: function() { + this.dnd && this.dnd.destroy(); + } + }); + }); + + /** + * @fileOverview 错误信息 + */ + define('lib/filepaste',[ + 'base', + 'mediator', + 'runtime/client' + ], function( Base, Mediator, RuntimeClent ) { + + var $ = Base.$; + + function FilePaste( opts ) { + opts = this.options = $.extend({}, opts ); + opts.container = $( opts.container || document.body ); + RuntimeClent.call( this, 'FilePaste' ); + } + + Base.inherits( RuntimeClent, { + constructor: FilePaste, + + init: function() { + var me = this; + + me.connectRuntime( me.options, function() { + me.exec('init'); + me.trigger('ready'); + }); + } + }); + + Mediator.installTo( FilePaste.prototype ); + + return FilePaste; + }); + /** + * @fileOverview 组件基类。 + */ + define('widgets/filepaste',[ + 'base', + 'uploader', + 'lib/filepaste', + 'widgets/widget' + ], function( Base, Uploader, FilePaste ) { + var $ = Base.$; + + /** + * @property {Selector} [paste=undefined] 指定监听paste事件的容器,如果不指定,不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`. + * @namespace options + * @for Uploader + */ + return Uploader.register({ + name: 'paste', + + init: function( opts ) { + + if ( !opts.paste || + this.request('predict-runtime-type') !== 'html5' ) { + return; + } + + var me = this, + deferred = Base.Deferred(), + options = $.extend({}, { + container: opts.paste, + accept: opts.accept + }), + paste; + + this.paste = paste = new FilePaste( options ); + + paste.once( 'ready', deferred.resolve ); + paste.on( 'paste', function( files ) { + me.owner.request( 'add-file', [ files ]); + }); + paste.init(); + + return deferred.promise(); + }, + + destroy: function() { + this.paste && this.paste.destroy(); + } + }); + }); + /** + * @fileOverview Blob + */ + define('lib/blob',[ + 'base', + 'runtime/client' + ], function( Base, RuntimeClient ) { + + function Blob( ruid, source ) { + var me = this; + + me.source = source; + me.ruid = ruid; + this.size = source.size || 0; + + // 如果没有指定 mimetype, 但是知道文件后缀。 + if ( !source.type && this.ext && + ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) { + this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext); + } else { + this.type = source.type || 'application/octet-stream'; + } + + RuntimeClient.call( me, 'Blob' ); + this.uid = source.uid || this.uid; + + if ( ruid ) { + me.connectRuntime( ruid ); + } + } + + Base.inherits( RuntimeClient, { + constructor: Blob, + + slice: function( start, end ) { + return this.exec( 'slice', start, end ); + }, + + getSource: function() { + return this.source; + } + }); + + return Blob; + }); + /** + * 为了统一化Flash的File和HTML5的File而存在。 + * 以至于要调用Flash里面的File,也可以像调用HTML5版本的File一下。 + * @fileOverview File + */ + define('lib/file',[ + 'base', + 'lib/blob' + ], function( Base, Blob ) { + + var uid = 1, + rExt = /\.([^.]+)$/; + + function File( ruid, file ) { + var ext; + + this.name = file.name || ('untitled' + uid++); + ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : ''; + + // todo 支持其他类型文件的转换。 + // 如果有 mimetype, 但是文件名里面没有找出后缀规律 + if ( !ext && file.type ) { + ext = /\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ? + RegExp.$1.toLowerCase() : ''; + this.name += '.' + ext; + } + + this.ext = ext; + this.lastModifiedDate = file.lastModifiedDate || + file.lastModified && new Date(file.lastModified).toLocaleString() || + (new Date()).toLocaleString(); + + Blob.apply( this, arguments ); + } + + return Base.inherits( Blob, File ); + }); + + /** + * @fileOverview 错误信息 + */ + define('lib/filepicker',[ + 'base', + 'runtime/client', + 'lib/file' + ], function( Base, RuntimeClient, File ) { + + var $ = Base.$; + + function FilePicker( opts ) { + opts = this.options = $.extend({}, FilePicker.options, opts ); + + opts.container = $( opts.id ); + + if ( !opts.container.length ) { + throw new Error('按钮指定错误'); + } + + opts.innerHTML = opts.innerHTML || opts.label || + opts.container.html() || ''; + + opts.button = $( opts.button || document.createElement('div') ); + opts.button.html( opts.innerHTML ); + opts.container.html( opts.button ); + + RuntimeClient.call( this, 'FilePicker', true ); + } + + FilePicker.options = { + button: null, + container: null, + label: null, + innerHTML: null, + multiple: true, + accept: null, + name: 'file', + style: 'webuploader-pick' //pick element class attribute, default is "webuploader-pick" + }; + + Base.inherits( RuntimeClient, { + constructor: FilePicker, + + init: function() { + var me = this, + opts = me.options, + button = opts.button, + style = opts.style; + + if (style) + button.addClass('webuploader-pick'); + + me.on( 'all', function( type ) { + var files; + + switch ( type ) { + case 'mouseenter': + if (style) + button.addClass('webuploader-pick-hover'); + break; + + case 'mouseleave': + if (style) + button.removeClass('webuploader-pick-hover'); + break; + + case 'change': + files = me.exec('getFiles'); + me.trigger( 'select', $.map( files, function( file ) { + file = new File( me.getRuid(), file ); + + // 记录来源。 + file._refer = opts.container; + return file; + }), opts.container ); + break; + } + }); + + me.connectRuntime( opts, function() { + me.refresh(); + me.exec( 'init', opts ); + me.trigger('ready'); + }); + + this._resizeHandler = Base.bindFn( this.refresh, this ); + $( window ).on( 'resize', this._resizeHandler ); + }, + + refresh: function() { + var shimContainer = this.getRuntime().getContainer(), + button = this.options.button, + /* + width = button.outerWidth ? + button.outerWidth() : button.width(), + + height = button.outerHeight ? + button.outerHeight() : button.height(), + */ + width = button[0] && button[0].offsetWidth || button.outerWidth() || button.width(), + height = button[0] && button[0].offsetHeight || button.outerHeight() || button.height(), + pos = button.offset(); + + width && height && shimContainer.css({ + bottom: 'auto', + right: 'auto', + width: width + 'px', + height: height + 'px' + }).offset( pos ); + }, + + enable: function() { + var btn = this.options.button; + + btn.removeClass('webuploader-pick-disable'); + this.refresh(); + }, + + disable: function() { + var btn = this.options.button; + + this.getRuntime().getContainer().css({ + top: '-99999px' + }); + + btn.addClass('webuploader-pick-disable'); + }, + + destroy: function() { + var btn = this.options.button; + $( window ).off( 'resize', this._resizeHandler ); + btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' + + 'webuploader-pick'); + } + }); + + return FilePicker; + }); + + /** + * @fileOverview 文件选择相关 + */ + define('widgets/filepicker',[ + 'base', + 'uploader', + 'lib/filepicker', + 'widgets/widget' + ], function( Base, Uploader, FilePicker ) { + var $ = Base.$; + + $.extend( Uploader.options, { + + /** + * @property {Selector | Object} [pick=undefined] + * @namespace options + * @for Uploader + * @description 指定选择文件的按钮容器,不指定则不创建按钮。 + * + * * `id` {Seletor|dom} 指定选择文件的按钮容器,不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。 + * * `label` {String} 请采用 `innerHTML` 代替 + * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。 + * * `multiple` {Boolean} 是否开起同时选择多个文件能力。 + */ + pick: null, + + /** + * @property {Array} [accept=null] + * @namespace options + * @for Uploader + * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表,所以这里需要分开指定。 + * + * * `title` {String} 文字描述 + * * `extensions` {String} 允许的文件后缀,不带点,多个用逗号分割。 + * * `mimeTypes` {String} 多个用逗号分割。 + * + * 如: + * + * ``` + * { + * title: 'Images', + * extensions: 'gif,jpg,jpeg,bmp,png', + * mimeTypes: 'image/*' + * } + * ``` + */ + accept: null/*{ + title: 'Images', + extensions: 'gif,jpg,jpeg,bmp,png', + mimeTypes: 'image/*' + }*/ + }); + + return Uploader.register({ + name: 'picker', + + init: function( opts ) { + this.pickers = []; + return opts.pick && this.addBtn( opts.pick ); + }, + + refresh: function() { + $.each( this.pickers, function() { + this.refresh(); + }); + }, + + /** + * @method addButton + * @for Uploader + * @grammar addButton( pick ) => Promise + * @description + * 添加文件选择按钮,如果一个按钮不够,需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。 + * @example + * uploader.addButton({ + * id: '#btnContainer', + * innerHTML: '选择文件' + * }); + */ + addBtn: function( pick ) { + var me = this, + opts = me.options, + accept = opts.accept, + promises = []; + + if ( !pick ) { + return; + } + + $.isPlainObject( pick ) || (pick = { + id: pick + }); + + $( pick.id ).each(function() { + var options, picker, deferred; + + deferred = Base.Deferred(); + + options = $.extend({}, pick, { + accept: $.isPlainObject( accept ) ? [ accept ] : accept, + swf: opts.swf, + runtimeOrder: opts.runtimeOrder, + id: this + }); + + picker = new FilePicker( options ); + + picker.once( 'ready', deferred.resolve ); + picker.on( 'select', function( files ) { + me.owner.request( 'add-file', [ files ]); + }); + picker.on('dialogopen', function() { + me.owner.trigger('dialogOpen', picker.button); + }); + picker.init(); + + me.pickers.push( picker ); + + promises.push( deferred.promise() ); + }); + + return Base.when.apply( Base, promises ); + }, + + disable: function() { + $.each( this.pickers, function() { + this.disable(); + }); + }, + + enable: function() { + $.each( this.pickers, function() { + this.enable(); + }); + }, + + destroy: function() { + $.each( this.pickers, function() { + this.destroy(); + }); + this.pickers = null; + } + }); + }); + /** + * @fileOverview Image + */ + define('lib/image',[ + 'base', + 'runtime/client', + 'lib/blob' + ], function( Base, RuntimeClient, Blob ) { + var $ = Base.$; + + // 构造器。 + function Image( opts ) { + this.options = $.extend({}, Image.options, opts ); + RuntimeClient.call( this, 'Image' ); + + this.on( 'load', function() { + this._info = this.exec('info'); + this._meta = this.exec('meta'); + }); + } + + // 默认选项。 + Image.options = { + + // 默认的图片处理质量 + quality: 90, + + // 是否裁剪 + crop: false, + + // 是否保留头部信息 + preserveHeaders: false, + + // 是否允许放大。 + allowMagnify: false + }; + + // 继承RuntimeClient. + Base.inherits( RuntimeClient, { + constructor: Image, + + info: function( val ) { + + // setter + if ( val ) { + this._info = val; + return this; + } + + // getter + return this._info; + }, + + meta: function( val ) { + + // setter + if ( val ) { + this._meta = val; + return this; + } + + // getter + return this._meta; + }, + + loadFromBlob: function( blob ) { + var me = this, + ruid = blob.getRuid(); + + this.connectRuntime( ruid, function() { + me.exec( 'init', me.options ); + me.exec( 'loadFromBlob', blob ); + }); + }, + + resize: function() { + var args = Base.slice( arguments ); + return this.exec.apply( this, [ 'resize' ].concat( args ) ); + }, + + crop: function() { + var args = Base.slice( arguments ); + return this.exec.apply( this, [ 'crop' ].concat( args ) ); + }, + + getAsDataUrl: function( type ) { + return this.exec( 'getAsDataUrl', type ); + }, + + getAsBlob: function( type ) { + var blob = this.exec( 'getAsBlob', type ); + + return new Blob( this.getRuid(), blob ); + } + }); + + return Image; + }); + /** + * Browser Image Compression + * v2.0.2 + * by Donald + * https://github.com/Donaldcwl/browser-image-compression + */ + define('lib/browser-image-compression',[], function () { + + var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var _a; + + function _mergeNamespaces(e, t) { + return t.forEach((function (t) { + t && "string" != typeof t && !Array.isArray(t) && Object.keys(t).forEach((function (r) { + if ("default" !== r && !(r in e)) { + var i = Object.getOwnPropertyDescriptor(t, r); + Object.defineProperty(e, r, i.get ? i : { + enumerable: !0, get: function () { + return t[r]; + } + }); + } + })); + })), Object.freeze(e); + } + + function copyExifWithoutOrientation(e, t) { + return new Promise((function (r, i) { + var o; + return getApp1Segment(e).then((function (e) { + try { + return o = e, r(new window.Blob([t.slice(0, 2), o, t.slice(2)], {type: "image/jpeg"})); + } catch (e) { + return i(e); + } + }), i); + })); + } + + var getApp1Segment = function (e) { + return new Promise((function (t, r) { + var i = new FileReader; + i.addEventListener("load", (function (_a) { + var e = _a.target.result; + var i = new DataView(e); + var o = 0; + if (65496 !== i.getUint16(o)) + return r("not a valid JPEG"); + for (o += 2; ;) { + var a_1 = i.getUint16(o); + if (65498 === a_1) + break; + var s_1 = i.getUint16(o + 2); + if (65505 === a_1 && 1165519206 === i.getUint32(o + 4)) { + var a_2 = o + 10; + var f_1 = void 0; + switch (i.getUint16(a_2)) { + case 18761: + f_1 = !0; + break; + case 19789: + f_1 = !1; + break; + default: + return r("TIFF header contains invalid endian"); + } + if (42 !== i.getUint16(a_2 + 2, f_1)) + return r("TIFF header contains invalid version"); + var l_1 = i.getUint32(a_2 + 4, f_1), c = a_2 + l_1 + 2 + 12 * i.getUint16(a_2 + l_1, f_1); + for (var e_1 = a_2 + l_1 + 2; e_1 < c; e_1 += 12) { + if (274 == i.getUint16(e_1, f_1)) { + if (3 !== i.getUint16(e_1 + 2, f_1)) + return r("Orientation data type is invalid"); + if (1 !== i.getUint32(e_1 + 4, f_1)) + return r("Orientation data count is invalid"); + i.setUint16(e_1 + 8, 1, f_1); + break; + } + } + return t(e.slice(o, o + 2 + s_1)); + } + o += 2 + s_1; + } + return t(new window.Blob); + })), i.readAsArrayBuffer(e); + })); + }; + var e = {}; + !function (e) { + var t, r, UZIP = {}; + e.exports = UZIP, UZIP.parse = function (e, t) { + for (var r = UZIP.bin.readUshort, i = UZIP.bin.readUint, o = 0, a = {}, s = new Uint8Array(e), f = s.length - 4; 101010256 != i(s, f);) + f--; + o = f; + o += 4; + var l = r(s, o += 4); + r(s, o += 2); + var c = i(s, o += 2), u = i(s, o += 4); + o += 4, o = u; + for (var h = 0; h < l; h++) { + i(s, o), o += 4, o += 4, o += 4, i(s, o += 4); + c = i(s, o += 4); + var d = i(s, o += 4), A = r(s, o += 4), g = r(s, o + 2), p = r(s, o + 4); + o += 6; + var m = i(s, o += 8); + o += 4, o += A + g + p, UZIP._readLocal(s, m, a, c, d, t); + } + return a; + }, UZIP._readLocal = function (e, t, r, i, o, a) { + var s = UZIP.bin.readUshort, f = UZIP.bin.readUint; + f(e, t), s(e, t += 4), s(e, t += 2); + var l = s(e, t += 2); + f(e, t += 2), f(e, t += 4), t += 4; + var c = s(e, t += 8), u = s(e, t += 2); + t += 2; + var h = UZIP.bin.readUTF8(e, t, c); + if (t += c, t += u, a) + r[h] = {size: o, csize: i}; + else { + var d = new Uint8Array(e.buffer, t); + if (0 == l) + r[h] = new Uint8Array(d.buffer.slice(t, t + i)); + else { + if (8 != l) + throw "unknown compression method: " + l; + var A = new Uint8Array(o); + UZIP.inflateRaw(d, A), r[h] = A; + } + } + }, UZIP.inflateRaw = function (e, t) { + return UZIP.F.inflate(e, t); + }, UZIP.inflate = function (e, t) { + return e[0], e[1], UZIP.inflateRaw(new Uint8Array(e.buffer, e.byteOffset + 2, e.length - 6), t); + }, UZIP.deflate = function (e, t) { + null == t && (t = {level: 6}); + var r = 0, i = new Uint8Array(50 + Math.floor(1.1 * e.length)); + i[r] = 120, i[r + 1] = 156, r += 2, r = UZIP.F.deflateRaw(e, i, r, t.level); + var o = UZIP.adler(e, 0, e.length); + return i[r + 0] = o >>> 24 & 255, i[r + 1] = o >>> 16 & 255, i[r + 2] = o >>> 8 & 255, i[r + 3] = o >>> 0 & 255, new Uint8Array(i.buffer, 0, r + 4); + }, UZIP.deflateRaw = function (e, t) { + null == t && (t = {level: 6}); + var r = new Uint8Array(50 + Math.floor(1.1 * e.length)), i = UZIP.F.deflateRaw(e, r, i, t.level); + return new Uint8Array(r.buffer, 0, i); + }, UZIP.encode = function (e, t) { + null == t && (t = !1); + var r = 0, i = UZIP.bin.writeUint, o = UZIP.bin.writeUshort, a = {}; + for (var s in e) { + var f = !UZIP._noNeed(s) && !t, l = e[s], c = UZIP.crc.crc(l, 0, l.length); + a[s] = {cpr: f, usize: l.length, crc: c, file: f ? UZIP.deflateRaw(l) : l}; + } + for (var s in a) + r += a[s].file.length + 30 + 46 + 2 * UZIP.bin.sizeUTF8(s); + r += 22; + var u = new Uint8Array(r), h = 0, d = []; + for (var s in a) { + var A = a[s]; + d.push(h), h = UZIP._writeHeader(u, h, s, A, 0); + } + var g = 0, p = h; + for (var s in a) { + A = a[s]; + d.push(h), h = UZIP._writeHeader(u, h, s, A, 1, d[g++]); + } + var m = h - p; + return i(u, h, 101010256), h += 4, o(u, h += 4, g), o(u, h += 2, g), i(u, h += 2, m), i(u, h += 4, p), h += 4, h += 2, u.buffer; + }, UZIP._noNeed = function (e) { + var t = e.split(".").pop().toLowerCase(); + return -1 != "png,jpg,jpeg,zip".indexOf(t); + }, UZIP._writeHeader = function (e, t, r, i, o, a) { + var s = UZIP.bin.writeUint, f = UZIP.bin.writeUshort, l = i.file; + return s(e, t, 0 == o ? 67324752 : 33639248), t += 4, 1 == o && (t += 2), f(e, t, 20), f(e, t += 2, 0), f(e, t += 2, i.cpr ? 8 : 0), s(e, t += 2, 0), s(e, t += 4, i.crc), s(e, t += 4, l.length), s(e, t += 4, i.usize), f(e, t += 4, UZIP.bin.sizeUTF8(r)), f(e, t += 2, 0), t += 2, 1 == o && (t += 2, t += 2, s(e, t += 6, a), t += 4), t += UZIP.bin.writeUTF8(e, t, r), 0 == o && (e.set(l, t), t += l.length), t; + }, UZIP.crc = { + table: function () { + for (var e = new Uint32Array(256), t = 0; t < 256; t++) { + for (var r = t, i = 0; i < 8; i++) + 1 & r ? r = 3988292384 ^ r >>> 1 : r >>>= 1; + e[t] = r; + } + return e; + }(), update: function (e, t, r, i) { + for (var o = 0; o < i; o++) + e = UZIP.crc.table[255 & (e ^ t[r + o])] ^ e >>> 8; + return e; + }, crc: function (e, t, r) { + return 4294967295 ^ UZIP.crc.update(4294967295, e, t, r); + } + }, UZIP.adler = function (e, t, r) { + for (var i = 1, o = 0, a = t, s = t + r; a < s;) { + for (var f = Math.min(a + 5552, s); a < f;) + o += i += e[a++]; + i %= 65521, o %= 65521; + } + return o << 16 | i; + }, UZIP.bin = { + readUshort: function (e, t) { + return e[t] | e[t + 1] << 8; + }, writeUshort: function (e, t, r) { + e[t] = 255 & r, e[t + 1] = r >> 8 & 255; + }, readUint: function (e, t) { + return 16777216 * e[t + 3] + (e[t + 2] << 16 | e[t + 1] << 8 | e[t]); + }, writeUint: function (e, t, r) { + e[t] = 255 & r, e[t + 1] = r >> 8 & 255, e[t + 2] = r >> 16 & 255, e[t + 3] = r >> 24 & 255; + }, readASCII: function (e, t, r) { + for (var i = "", o = 0; o < r; o++) + i += String.fromCharCode(e[t + o]); + return i; + }, writeASCII: function (e, t, r) { + for (var i = 0; i < r.length; i++) + e[t + i] = r.charCodeAt(i); + }, pad: function (e) { + return e.length < 2 ? "0" + e : e; + }, readUTF8: function (e, t, r) { + for (var i, o = "", a = 0; a < r; a++) + o += "%" + UZIP.bin.pad(e[t + a].toString(16)); + try { + i = decodeURIComponent(o); + } catch (i) { + return UZIP.bin.readASCII(e, t, r); + } + return i; + }, writeUTF8: function (e, t, r) { + for (var i = r.length, o = 0, a = 0; a < i; a++) { + var s = r.charCodeAt(a); + if (0 == (4294967168 & s)) + e[t + o] = s, o++; + else if (0 == (4294965248 & s)) + e[t + o] = 192 | s >> 6, e[t + o + 1] = 128 | s >> 0 & 63, o += 2; + else if (0 == (4294901760 & s)) + e[t + o] = 224 | s >> 12, e[t + o + 1] = 128 | s >> 6 & 63, e[t + o + 2] = 128 | s >> 0 & 63, o += 3; + else { + if (0 != (4292870144 & s)) + throw "e"; + e[t + o] = 240 | s >> 18, e[t + o + 1] = 128 | s >> 12 & 63, e[t + o + 2] = 128 | s >> 6 & 63, e[t + o + 3] = 128 | s >> 0 & 63, o += 4; + } + } + return o; + }, sizeUTF8: function (e) { + for (var t = e.length, r = 0, i = 0; i < t; i++) { + var o = e.charCodeAt(i); + if (0 == (4294967168 & o)) + r++; + else if (0 == (4294965248 & o)) + r += 2; + else if (0 == (4294901760 & o)) + r += 3; + else { + if (0 != (4292870144 & o)) + throw "e"; + r += 4; + } + } + return r; + } + }, UZIP.F = {}, UZIP.F.deflateRaw = function (e, t, r, i) { + var o = [[0, 0, 0, 0, 0], [4, 4, 8, 4, 0], [4, 5, 16, 8, 0], [4, 6, 16, 16, 0], [4, 10, 16, 32, 0], [8, 16, 32, 32, 0], [8, 16, 128, 128, 0], [8, 32, 128, 256, 0], [32, 128, 258, 1024, 1], [32, 258, 258, 4096, 1]][i], + a = UZIP.F.U, s = UZIP.F._goodIndex; + UZIP.F._hash; + var f = UZIP.F._putsE, l = 0, c = r << 3, u = 0, h = e.length; + if (0 == i) { + for (; l < h;) { + f(t, c, l + (_ = Math.min(65535, h - l)) == h ? 1 : 0), c = UZIP.F._copyExact(e, l, _, t, c + 8), l += _; + } + return c >>> 3; + } + var d = a.lits, A = a.strt, g = a.prev, p = 0, m = 0, w = 0, v = 0, b = 0, y = 0; + for (h > 2 && (A[y = UZIP.F._hash(e, 0)] = 0), l = 0; l < h; l++) { + if (b = y, l + 1 < h - 2) { + y = UZIP.F._hash(e, l + 1); + var E = l + 1 & 32767; + g[E] = A[y], A[y] = E; + } + if (u <= l) { + (p > 14e3 || m > 26697) && h - l > 100 && (u < l && (d[p] = l - u, p += 2, u = l), c = UZIP.F._writeBlock(l == h - 1 || u == h ? 1 : 0, d, p, v, e, w, l - w, t, c), p = m = v = 0, w = l); + var F = 0; + l < h - 2 && (F = UZIP.F._bestMatch(e, l, g, b, Math.min(o[2], h - l), o[3])); + var _ = F >>> 16, B = 65535 & F; + if (0 != F) { + B = 65535 & F; + var U = s(_ = F >>> 16, a.of0); + a.lhst[257 + U]++; + var C = s(B, a.df0); + a.dhst[C]++, v += a.exb[U] + a.dxb[C], d[p] = _ << 23 | l - u, d[p + 1] = B << 16 | U << 8 | C, p += 2, u = l + _; + } else + a.lhst[e[l]]++; + m++; + } + } + for (w == l && 0 != e.length || (u < l && (d[p] = l - u, p += 2, u = l), c = UZIP.F._writeBlock(1, d, p, v, e, w, l - w, t, c), p = 0, m = 0, p = m = v = 0, w = l); 0 != (7 & c);) + c++; + return c >>> 3; + }, UZIP.F._bestMatch = function (e, t, r, i, o, a) { + var s = 32767 & t, f = r[s], l = s - f + 32768 & 32767; + if (f == s || i != UZIP.F._hash(e, t - l)) + return 0; + for (var c = 0, u = 0, h = Math.min(32767, t); l <= h && 0 != --a && f != s;) { + if (0 == c || e[t + c] == e[t + c - l]) { + var d = UZIP.F._howLong(e, t, l); + if (d > c) { + if (u = l, (c = d) >= o) + break; + l + 2 < d && (d = l + 2); + for (var A = 0, g = 0; g < d - 2; g++) { + var p = t - l + g + 32768 & 32767, m = p - r[p] + 32768 & 32767; + m > A && (A = m, f = p); + } + } + } + l += (s = f) - (f = r[s]) + 32768 & 32767; + } + return c << 16 | u; + }, UZIP.F._howLong = function (e, t, r) { + if (e[t] != e[t - r] || e[t + 1] != e[t + 1 - r] || e[t + 2] != e[t + 2 - r]) + return 0; + var i = t, o = Math.min(e.length, t + 258); + for (t += 3; t < o && e[t] == e[t - r];) + t++; + return t - i; + }, UZIP.F._hash = function (e, t) { + return (e[t] << 8 | e[t + 1]) + (e[t + 2] << 4) & 65535; + }, UZIP.saved = 0, UZIP.F._writeBlock = function (e, t, r, i, o, a, s, f, l) { + var c, u, h, d, A, g, p, m, w, v = UZIP.F.U, b = UZIP.F._putsF, y = UZIP.F._putsE; + v.lhst[256]++, u = (c = UZIP.F.getTrees())[0], h = c[1], d = c[2], A = c[3], g = c[4], p = c[5], m = c[6], w = c[7]; + var E = 32 + (0 == (l + 3 & 7) ? 0 : 8 - (l + 3 & 7)) + (s << 3), + F = i + UZIP.F.contSize(v.fltree, v.lhst) + UZIP.F.contSize(v.fdtree, v.dhst), + _ = i + UZIP.F.contSize(v.ltree, v.lhst) + UZIP.F.contSize(v.dtree, v.dhst); + _ += 14 + 3 * p + UZIP.F.contSize(v.itree, v.ihst) + (2 * v.ihst[16] + 3 * v.ihst[17] + 7 * v.ihst[18]); + for (var B = 0; B < 286; B++) + v.lhst[B] = 0; + for (B = 0; B < 30; B++) + v.dhst[B] = 0; + for (B = 0; B < 19; B++) + v.ihst[B] = 0; + var U = E < F && E < _ ? 0 : F < _ ? 1 : 2; + if (b(f, l, e), b(f, l + 1, U), l += 3, 0 == U) { + for (; 0 != (7 & l);) + l++; + l = UZIP.F._copyExact(o, a, s, f, l); + } else { + var C, I; + if (1 == U && (C = v.fltree, I = v.fdtree), 2 == U) { + UZIP.F.makeCodes(v.ltree, u), UZIP.F.revCodes(v.ltree, u), UZIP.F.makeCodes(v.dtree, h), UZIP.F.revCodes(v.dtree, h), UZIP.F.makeCodes(v.itree, d), UZIP.F.revCodes(v.itree, d), C = v.ltree, I = v.dtree, y(f, l, A - 257), y(f, l += 5, g - 1), y(f, l += 5, p - 4), l += 4; + for (var Q = 0; Q < p; Q++) + y(f, l + 3 * Q, v.itree[1 + (v.ordr[Q] << 1)]); + l += 3 * p, l = UZIP.F._codeTiny(m, v.itree, f, l), l = UZIP.F._codeTiny(w, v.itree, f, l); + } + for (var M = a, x = 0; x < r; x += 2) { + for (var T = t[x], S = T >>> 23, R = M + (8388607 & T); M < R;) + l = UZIP.F._writeLit(o[M++], C, f, l); + if (0 != S) { + var O = t[x + 1], P = O >> 16, H = O >> 8 & 255, L = 255 & O; + y(f, l = UZIP.F._writeLit(257 + H, C, f, l), S - v.of0[H]), l += v.exb[H], b(f, l = UZIP.F._writeLit(L, I, f, l), P - v.df0[L]), l += v.dxb[L], M += S; + } + } + l = UZIP.F._writeLit(256, C, f, l); + } + return l; + }, UZIP.F._copyExact = function (e, t, r, i, o) { + var a = o >>> 3; + return i[a] = r, i[a + 1] = r >>> 8, i[a + 2] = 255 - i[a], i[a + 3] = 255 - i[a + 1], a += 4, i.set(new Uint8Array(e.buffer, t, r), a), o + (r + 4 << 3); + }, UZIP.F.getTrees = function () { + for (var e = UZIP.F.U, t = UZIP.F._hufTree(e.lhst, e.ltree, 15), r = UZIP.F._hufTree(e.dhst, e.dtree, 15), i = [], o = UZIP.F._lenCodes(e.ltree, i), a = [], s = UZIP.F._lenCodes(e.dtree, a), f = 0; f < i.length; f += 2) + e.ihst[i[f]]++; + for (f = 0; f < a.length; f += 2) + e.ihst[a[f]]++; + for (var l = UZIP.F._hufTree(e.ihst, e.itree, 7), c = 19; c > 4 && 0 == e.itree[1 + (e.ordr[c - 1] << 1)];) + c--; + return [t, r, l, o, s, c, i, a]; + }, UZIP.F.getSecond = function (e) { + for (var t = [], r = 0; r < e.length; r += 2) + t.push(e[r + 1]); + return t; + }, UZIP.F.nonZero = function (e) { + for (var t = "", r = 0; r < e.length; r += 2) + 0 != e[r + 1] && (t += (r >> 1) + ","); + return t; + }, UZIP.F.contSize = function (e, t) { + for (var r = 0, i = 0; i < t.length; i++) + r += t[i] * e[1 + (i << 1)]; + return r; + }, UZIP.F._codeTiny = function (e, t, r, i) { + for (var o = 0; o < e.length; o += 2) { + var a = e[o], s = e[o + 1]; + i = UZIP.F._writeLit(a, t, r, i); + var f = 16 == a ? 2 : 17 == a ? 3 : 7; + a > 15 && (UZIP.F._putsE(r, i, s, f), i += f); + } + return i; + }, UZIP.F._lenCodes = function (e, t) { + for (var r = e.length; 2 != r && 0 == e[r - 1];) + r -= 2; + for (var i = 0; i < r; i += 2) { + var o = e[i + 1], a = i + 3 < r ? e[i + 3] : -1, s = i + 5 < r ? e[i + 5] : -1, + f = 0 == i ? -1 : e[i - 1]; + if (0 == o && a == o && s == o) { + for (var l = i + 5; l + 2 < r && e[l + 2] == o;) + l += 2; + (c = Math.min(l + 1 - i >>> 1, 138)) < 11 ? t.push(17, c - 3) : t.push(18, c - 11), i += 2 * c - 2; + } else if (o == f && a == o && s == o) { + for (l = i + 5; l + 2 < r && e[l + 2] == o;) + l += 2; + var c = Math.min(l + 1 - i >>> 1, 6); + t.push(16, c - 3), i += 2 * c - 2; + } else + t.push(o, 0); + } + return r >>> 1; + }, UZIP.F._hufTree = function (e, t, r) { + var i = [], o = e.length, a = t.length, s = 0; + for (s = 0; s < a; s += 2) + t[s] = 0, t[s + 1] = 0; + for (s = 0; s < o; s++) + 0 != e[s] && i.push({lit: s, f: e[s]}); + var f = i.length, l = i.slice(0); + if (0 == f) + return 0; + if (1 == f) { + var c = i[0].lit; + l = 0 == c ? 1 : 0; + return t[1 + (c << 1)] = 1, t[1 + (l << 1)] = 1, 1; + } + i.sort((function (e, t) { + return e.f - t.f; + })); + var u = i[0], h = i[1], d = 0, A = 1, g = 2; + for (i[0] = { + lit: -1, + f: u.f + h.f, + l: u, + r: h, + d: 0 + }; A != f - 1;) + u = d != A && (g == f || i[d].f < i[g].f) ? i[d++] : i[g++], h = d != A && (g == f || i[d].f < i[g].f) ? i[d++] : i[g++], i[A++] = { + lit: -1, + f: u.f + h.f, + l: u, + r: h + }; + var p = UZIP.F.setDepth(i[A - 1], 0); + for (p > r && (UZIP.F.restrictDepth(l, r, p), p = r), s = 0; s < f; s++) + t[1 + (l[s].lit << 1)] = l[s].d; + return p; + }, UZIP.F.setDepth = function (e, t) { + return -1 != e.lit ? (e.d = t, t) : Math.max(UZIP.F.setDepth(e.l, t + 1), UZIP.F.setDepth(e.r, t + 1)); + }, UZIP.F.restrictDepth = function (e, t, r) { + var i = 0, o = 1 << r - t, a = 0; + for (e.sort((function (e, t) { + return t.d == e.d ? e.f - t.f : t.d - e.d; + })), i = 0; i < e.length && e[i].d > t; i++) { + var s = e[i].d; + e[i].d = t, a += o - (1 << r - s); + } + for (a >>>= r - t; a > 0;) { + (s = e[i].d) < t ? (e[i].d++, a -= 1 << t - s - 1) : i++; + } + for (; i >= 0; i--) + e[i].d == t && a < 0 && (e[i].d--, a++); + 0 != a && console.log("debt left"); + }, UZIP.F._goodIndex = function (e, t) { + var r = 0; + return t[16 | r] <= e && (r |= 16), t[8 | r] <= e && (r |= 8), t[4 | r] <= e && (r |= 4), t[2 | r] <= e && (r |= 2), t[1 | r] <= e && (r |= 1), r; + }, UZIP.F._writeLit = function (e, t, r, i) { + return UZIP.F._putsF(r, i, t[e << 1]), i + t[1 + (e << 1)]; + }, UZIP.F.inflate = function (e, t) { + var r = Uint8Array; + if (3 == e[0] && 0 == e[1]) + return t || new r(0); + var i = UZIP.F, o = i._bitsF, a = i._bitsE, s = i._decodeTiny, f = i.makeCodes, l = i.codes2map, + c = i._get17, u = i.U, h = null == t; + h && (t = new r(e.length >>> 2 << 3)); + for (var d, A, g = 0, p = 0, m = 0, w = 0, v = 0, b = 0, y = 0, E = 0, F = 0; 0 == g;) + if (g = o(e, F, 1), p = o(e, F + 1, 2), F += 3, 0 != p) { + if (h && (t = UZIP.F._check(t, E + (1 << 17))), 1 == p && (d = u.flmap, A = u.fdmap, b = 511, y = 31), 2 == p) { + m = a(e, F, 5) + 257, w = a(e, F + 5, 5) + 1, v = a(e, F + 10, 4) + 4, F += 14; + for (var _ = 0; _ < 38; _ += 2) + u.itree[_] = 0, u.itree[_ + 1] = 0; + var B = 1; + for (_ = 0; _ < v; _++) { + var U = a(e, F + 3 * _, 3); + u.itree[1 + (u.ordr[_] << 1)] = U, U > B && (B = U); + } + F += 3 * v, f(u.itree, B), l(u.itree, B, u.imap), d = u.lmap, A = u.dmap, F = s(u.imap, (1 << B) - 1, m + w, e, F, u.ttree); + var C = i._copyOut(u.ttree, 0, m, u.ltree); + b = (1 << C) - 1; + var I = i._copyOut(u.ttree, m, w, u.dtree); + y = (1 << I) - 1, f(u.ltree, C), l(u.ltree, C, d), f(u.dtree, I), l(u.dtree, I, A); + } + for (; ;) { + var Q = d[c(e, F) & b]; + F += 15 & Q; + var M = Q >>> 4; + if (M >>> 8 == 0) + t[E++] = M; + else { + if (256 == M) + break; + var x = E + M - 254; + if (M > 264) { + var T = u.ldef[M - 257]; + x = E + (T >>> 3) + a(e, F, 7 & T), F += 7 & T; + } + var S = A[c(e, F) & y]; + F += 15 & S; + var R = S >>> 4, O = u.ddef[R], P = (O >>> 4) + o(e, F, 15 & O); + for (F += 15 & O, h && (t = UZIP.F._check(t, E + (1 << 17))); E < x;) + t[E] = t[E++ - P], t[E] = t[E++ - P], t[E] = t[E++ - P], t[E] = t[E++ - P]; + E = x; + } + } + } else { + 0 != (7 & F) && (F += 8 - (7 & F)); + var H = 4 + (F >>> 3), L = e[H - 4] | e[H - 3] << 8; + h && (t = UZIP.F._check(t, E + L)), t.set(new r(e.buffer, e.byteOffset + H, L), E), F = H + L << 3, E += L; + } + return t.length == E ? t : t.slice(0, E); + }, UZIP.F._check = function (e, t) { + var r = e.length; + if (t <= r) + return e; + var i = new Uint8Array(Math.max(r << 1, t)); + return i.set(e, 0), i; + }, UZIP.F._decodeTiny = function (e, t, r, i, o, a) { + for (var s = UZIP.F._bitsE, f = UZIP.F._get17, l = 0; l < r;) { + var c = e[f(i, o) & t]; + o += 15 & c; + var u = c >>> 4; + if (u <= 15) + a[l] = u, l++; + else { + var h = 0, d = 0; + 16 == u ? (d = 3 + s(i, o, 2), o += 2, h = a[l - 1]) : 17 == u ? (d = 3 + s(i, o, 3), o += 3) : 18 == u && (d = 11 + s(i, o, 7), o += 7); + for (var A = l + d; l < A;) + a[l] = h, l++; + } + } + return o; + }, UZIP.F._copyOut = function (e, t, r, i) { + for (var o = 0, a = 0, s = i.length >>> 1; a < r;) { + var f = e[a + t]; + i[a << 1] = 0, i[1 + (a << 1)] = f, f > o && (o = f), a++; + } + for (; a < s;) + i[a << 1] = 0, i[1 + (a << 1)] = 0, a++; + return o; + }, UZIP.F.makeCodes = function (e, t) { + for (var r, i, o, a, s = UZIP.F.U, f = e.length, l = s.bl_count, c = 0; c <= t; c++) + l[c] = 0; + for (c = 1; c < f; c += 2) + l[e[c]]++; + var u = s.next_code; + for (r = 0, l[0] = 0, i = 1; i <= t; i++) + r = r + l[i - 1] << 1, u[i] = r; + for (o = 0; o < f; o += 2) + 0 != (a = e[o + 1]) && (e[o] = u[a], u[a]++); + }, UZIP.F.codes2map = function (e, t, r) { + for (var i = e.length, o = UZIP.F.U.rev15, a = 0; a < i; a += 2) + if (0 != e[a + 1]) + for (var s = a >> 1, f = e[a + 1], l = s << 4 | f, c = t - f, u = e[a] << c, h = u + (1 << c); u != h;) { + r[o[u] >>> 15 - t] = l, u++; + } + }, UZIP.F.revCodes = function (e, t) { + for (var r = UZIP.F.U.rev15, i = 15 - t, o = 0; o < e.length; o += 2) { + var a = e[o] << t - e[o + 1]; + e[o] = r[a] >>> i; + } + }, UZIP.F._putsE = function (e, t, r) { + r <<= 7 & t; + var i = t >>> 3; + e[i] |= r, e[i + 1] |= r >>> 8; + }, UZIP.F._putsF = function (e, t, r) { + r <<= 7 & t; + var i = t >>> 3; + e[i] |= r, e[i + 1] |= r >>> 8, e[i + 2] |= r >>> 16; + }, UZIP.F._bitsE = function (e, t, r) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8) >>> (7 & t) & (1 << r) - 1; + }, UZIP.F._bitsF = function (e, t, r) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t) & (1 << r) - 1; + }, UZIP.F._get17 = function (e, t) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t); + }, UZIP.F._get25 = function (e, t) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16 | e[3 + (t >>> 3)] << 24) >>> (7 & t); + }, UZIP.F.U = (t = Uint16Array, r = Uint32Array, { + next_code: new t(16), + bl_count: new t(16), + ordr: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], + of0: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999], + exb: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0], + ldef: new t(32), + df0: [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535], + dxb: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0], + ddef: new r(32), + flmap: new t(512), + fltree: [], + fdmap: new t(32), + fdtree: [], + lmap: new t(32768), + ltree: [], + ttree: [], + dmap: new t(32768), + dtree: [], + imap: new t(512), + itree: [], + rev15: new t(32768), + lhst: new r(286), + dhst: new r(30), + ihst: new r(19), + lits: new r(15e3), + strt: new t(65536), + prev: new t(32768) + }), function () { + for (var e = UZIP.F.U, t = 0; t < 32768; t++) { + var r = t; + r = (4278255360 & (r = (4042322160 & (r = (3435973836 & (r = (2863311530 & r) >>> 1 | (1431655765 & r) << 1)) >>> 2 | (858993459 & r) << 2)) >>> 4 | (252645135 & r) << 4)) >>> 8 | (16711935 & r) << 8, e.rev15[t] = (r >>> 16 | r << 16) >>> 17; + } + + function pushV(e, t, r) { + for (; 0 != t--;) + e.push(0, r); + } + + for (t = 0; t < 32; t++) + e.ldef[t] = e.of0[t] << 3 | e.exb[t], e.ddef[t] = e.df0[t] << 4 | e.dxb[t]; + pushV(e.fltree, 144, 8), pushV(e.fltree, 112, 9), pushV(e.fltree, 24, 7), pushV(e.fltree, 8, 8), UZIP.F.makeCodes(e.fltree, 9), UZIP.F.codes2map(e.fltree, 9, e.flmap), UZIP.F.revCodes(e.fltree, 9), pushV(e.fdtree, 32, 5), UZIP.F.makeCodes(e.fdtree, 5), UZIP.F.codes2map(e.fdtree, 5, e.fdmap), UZIP.F.revCodes(e.fdtree, 5), pushV(e.itree, 19, 0), pushV(e.ltree, 286, 0), pushV(e.dtree, 30, 0), pushV(e.ttree, 320, 0); + }(); + }({ + get exports() { + return e; + }, set exports(t) { + e = t; + } + }); + var UZIP = _mergeNamespaces({__proto__: null, default: e}, [e]); + var UPNG = function () { + var e = { + nextZero: function (e, t) { + for (; 0 != e[t];) + t++; + return t; + }, + readUshort: function (e, t) { + return e[t] << 8 | e[t + 1]; + }, + writeUshort: function (e, t, r) { + e[t] = r >> 8 & 255, e[t + 1] = 255 & r; + }, + readUint: function (e, t) { + return 16777216 * e[t] + (e[t + 1] << 16 | e[t + 2] << 8 | e[t + 3]); + }, + writeUint: function (e, t, r) { + e[t] = r >> 24 & 255, e[t + 1] = r >> 16 & 255, e[t + 2] = r >> 8 & 255, e[t + 3] = 255 & r; + }, + readASCII: function (e, t, r) { + var i = ""; + for (var o_1 = 0; o_1 < r; o_1++) + i += String.fromCharCode(e[t + o_1]); + return i; + }, + writeASCII: function (e, t, r) { + for (var i_1 = 0; i_1 < r.length; i_1++) + e[t + i_1] = r.charCodeAt(i_1); + }, + readBytes: function (e, t, r) { + var i = []; + for (var o_2 = 0; o_2 < r; o_2++) + i.push(e[t + o_2]); + return i; + }, + pad: function (e) { + return e.length < 2 ? "0".concat(e) : e; + }, + readUTF8: function (t, r, i) { + var o, a = ""; + for (var o_3 = 0; o_3 < i; o_3++) + a += "%".concat(e.pad(t[r + o_3].toString(16))); + try { + o = decodeURIComponent(a); + } catch (o) { + return e.readASCII(t, r, i); + } + return o; + } + }; + + function decodeImage(t, r, i, o) { + var a = r * i, s = _getBPP(o), f = Math.ceil(r * s / 8), l = new Uint8Array(4 * a), + c = new Uint32Array(l.buffer), u = o.ctype, h = o.depth, d = e.readUshort; + if (6 == u) { + var e_2 = a << 2; + if (8 == h) + for (var A = 0; A < e_2; A += 4) + l[A] = t[A], l[A + 1] = t[A + 1], l[A + 2] = t[A + 2], l[A + 3] = t[A + 3]; + if (16 == h) + for (A = 0; A < e_2; A++) + l[A] = t[A << 1]; + } else if (2 == u) { + var e_3 = o.tabs.tRNS; + if (null == e_3) { + if (8 == h) + for (A = 0; A < a; A++) { + var g = 3 * A; + c[A] = 255 << 24 | t[g + 2] << 16 | t[g + 1] << 8 | t[g]; + } + if (16 == h) + for (A = 0; A < a; A++) { + g = 6 * A; + c[A] = 255 << 24 | t[g + 4] << 16 | t[g + 2] << 8 | t[g]; + } + } else { + var p = e_3[0]; + var r_1 = e_3[1], i_2 = e_3[2]; + if (8 == h) + for (A = 0; A < a; A++) { + var m = A << 2; + g = 3 * A; + c[A] = 255 << 24 | t[g + 2] << 16 | t[g + 1] << 8 | t[g], t[g] == p && t[g + 1] == r_1 && t[g + 2] == i_2 && (l[m + 3] = 0); + } + if (16 == h) + for (A = 0; A < a; A++) { + m = A << 2, g = 6 * A; + c[A] = 255 << 24 | t[g + 4] << 16 | t[g + 2] << 8 | t[g], d(t, g) == p && d(t, g + 2) == r_1 && d(t, g + 4) == i_2 && (l[m + 3] = 0); + } + } + } else if (3 == u) { + var e_4 = o.tabs.PLTE, s_2 = o.tabs.tRNS, c_1 = s_2 ? s_2.length : 0; + if (1 == h) + for (var w = 0; w < i; w++) { + var v = w * f, b = w * r; + for (A = 0; A < r; A++) { + m = b + A << 2; + var y = 3 * (E = t[v + (A >> 3)] >> 7 - ((7 & A) << 0) & 1); + l[m] = e_4[y], l[m + 1] = e_4[y + 1], l[m + 2] = e_4[y + 2], l[m + 3] = E < c_1 ? s_2[E] : 255; + } + } + if (2 == h) + for (w = 0; w < i; w++) + for (v = w * f, b = w * r, A = 0; A < r; A++) { + m = b + A << 2, y = 3 * (E = t[v + (A >> 2)] >> 6 - ((3 & A) << 1) & 3); + l[m] = e_4[y], l[m + 1] = e_4[y + 1], l[m + 2] = e_4[y + 2], l[m + 3] = E < c_1 ? s_2[E] : 255; + } + if (4 == h) + for (w = 0; w < i; w++) + for (v = w * f, b = w * r, A = 0; A < r; A++) { + m = b + A << 2, y = 3 * (E = t[v + (A >> 1)] >> 4 - ((1 & A) << 2) & 15); + l[m] = e_4[y], l[m + 1] = e_4[y + 1], l[m + 2] = e_4[y + 2], l[m + 3] = E < c_1 ? s_2[E] : 255; + } + if (8 == h) + for (A = 0; A < a; A++) { + var E; + m = A << 2, y = 3 * (E = t[A]); + l[m] = e_4[y], l[m + 1] = e_4[y + 1], l[m + 2] = e_4[y + 2], l[m + 3] = E < c_1 ? s_2[E] : 255; + } + } else if (4 == u) { + if (8 == h) + for (A = 0; A < a; A++) { + m = A << 2; + var F = t[_ = A << 1]; + l[m] = F, l[m + 1] = F, l[m + 2] = F, l[m + 3] = t[_ + 1]; + } + if (16 == h) + for (A = 0; A < a; A++) { + var _; + m = A << 2, F = t[_ = A << 2]; + l[m] = F, l[m + 1] = F, l[m + 2] = F, l[m + 3] = t[_ + 2]; + } + } else if (0 == u) + for (p = o.tabs.tRNS ? o.tabs.tRNS : -1, w = 0; w < i; w++) { + var e_5 = w * f, i_3 = w * r; + if (1 == h) + for (var B = 0; B < r; B++) { + var U = (F = 255 * (t[e_5 + (B >>> 3)] >>> 7 - (7 & B) & 1)) == 255 * p ? 0 : 255; + c[i_3 + B] = U << 24 | F << 16 | F << 8 | F; + } + else if (2 == h) + for (B = 0; B < r; B++) { + U = (F = 85 * (t[e_5 + (B >>> 2)] >>> 6 - ((3 & B) << 1) & 3)) == 85 * p ? 0 : 255; + c[i_3 + B] = U << 24 | F << 16 | F << 8 | F; + } + else if (4 == h) + for (B = 0; B < r; B++) { + U = (F = 17 * (t[e_5 + (B >>> 1)] >>> 4 - ((1 & B) << 2) & 15)) == 17 * p ? 0 : 255; + c[i_3 + B] = U << 24 | F << 16 | F << 8 | F; + } + else if (8 == h) + for (B = 0; B < r; B++) { + U = (F = t[e_5 + B]) == p ? 0 : 255; + c[i_3 + B] = U << 24 | F << 16 | F << 8 | F; + } + else if (16 == h) + for (B = 0; B < r; B++) { + F = t[e_5 + (B << 1)], U = d(t, e_5 + (B << 1)) == p ? 0 : 255; + c[i_3 + B] = U << 24 | F << 16 | F << 8 | F; + } + } + return l; + } + + function _decompress(e, r, i, o) { + var a = _getBPP(e), s = Math.ceil(i * a / 8), f = new Uint8Array((s + 1 + e.interlace) * o); + return r = e.tabs.CgBI ? t(r, f) : _inflate(r, f), 0 == e.interlace ? r = _filterZero(r, e, 0, i, o) : 1 == e.interlace && (r = function _readInterlace(e, t) { + var r = t.width, i = t.height, o = _getBPP(t), a = o >> 3, s = Math.ceil(r * o / 8), + f = new Uint8Array(i * s); + var l = 0; + var c = [0, 0, 4, 0, 2, 0, 1], u = [0, 4, 0, 2, 0, 1, 0], h = [8, 8, 8, 4, 4, 2, 2], + d = [8, 8, 4, 4, 2, 2, 1]; + var A = 0; + for (; A < 7;) { + var p = h[A], m = d[A]; + var w = 0, v = 0, b = c[A]; + for (; b < i;) + b += p, v++; + var y = u[A]; + for (; y < r;) + y += m, w++; + var E = Math.ceil(w * o / 8); + _filterZero(e, t, l, w, v); + var F = 0, _ = c[A]; + for (; _ < i;) { + var t_1 = u[A], i_4 = l + F * E << 3; + for (; t_1 < r;) { + var g; + if (1 == o) + g = (g = e[i_4 >> 3]) >> 7 - (7 & i_4) & 1, f[_ * s + (t_1 >> 3)] |= g << 7 - ((7 & t_1) << 0); + if (2 == o) + g = (g = e[i_4 >> 3]) >> 6 - (7 & i_4) & 3, f[_ * s + (t_1 >> 2)] |= g << 6 - ((3 & t_1) << 1); + if (4 == o) + g = (g = e[i_4 >> 3]) >> 4 - (7 & i_4) & 15, f[_ * s + (t_1 >> 1)] |= g << 4 - ((1 & t_1) << 2); + if (o >= 8) { + var r_2 = _ * s + t_1 * a; + for (var t_2 = 0; t_2 < a; t_2++) + f[r_2 + t_2] = e[(i_4 >> 3) + t_2]; + } + i_4 += o, t_1 += m; + } + F++, _ += p; + } + w * v != 0 && (l += v * (1 + E)), A += 1; + } + return f; + }(r, e)), r; + } + + function _inflate(e, r) { + return t(new Uint8Array(e.buffer, 2, e.length - 6), r); + } + + var t = function () { + var e = {H: {}}; + return e.H.N = function (t, r) { + var i = Uint8Array; + var o, a, s = 0, f = 0, l = 0, c = 0, u = 0, h = 0, d = 0, A = 0, g = 0; + if (3 == t[0] && 0 == t[1]) + return r || new i(0); + var p = e.H, m = p.b, w = p.e, v = p.R, b = p.n, y = p.A, E = p.Z, F = p.m, _ = null == r; + for (_ && (r = new i(t.length >>> 2 << 5)); 0 == s;) + if (s = m(t, g, 1), f = m(t, g + 1, 2), g += 3, 0 != f) { + if (_ && (r = e.H.W(r, A + (1 << 17))), 1 == f && (o = F.J, a = F.h, h = 511, d = 31), 2 == f) { + l = w(t, g, 5) + 257, c = w(t, g + 5, 5) + 1, u = w(t, g + 10, 4) + 4, g += 14; + var e_6 = 1; + for (var B = 0; B < 38; B += 2) + F.Q[B] = 0, F.Q[B + 1] = 0; + for (B = 0; B < u; B++) { + var r_3 = w(t, g + 3 * B, 3); + F.Q[1 + (F.X[B] << 1)] = r_3, r_3 > e_6 && (e_6 = r_3); + } + g += 3 * u, b(F.Q, e_6), y(F.Q, e_6, F.u), o = F.w, a = F.d, g = v(F.u, (1 << e_6) - 1, l + c, t, g, F.v); + var r_4 = p.V(F.v, 0, l, F.C); + h = (1 << r_4) - 1; + var i_5 = p.V(F.v, l, c, F.D); + d = (1 << i_5) - 1, b(F.C, r_4), y(F.C, r_4, o), b(F.D, i_5), y(F.D, i_5, a); + } + for (; ;) { + var e_7 = o[E(t, g) & h]; + g += 15 & e_7; + var i_6 = e_7 >>> 4; + if (i_6 >>> 8 == 0) + r[A++] = i_6; + else { + if (256 == i_6) + break; + { + var e_8 = A + i_6 - 254; + if (i_6 > 264) { + var r_5 = F.q[i_6 - 257]; + e_8 = A + (r_5 >>> 3) + w(t, g, 7 & r_5), g += 7 & r_5; + } + var o_4 = a[E(t, g) & d]; + g += 15 & o_4; + var s_3 = o_4 >>> 4, f_2 = F.c[s_3], l_2 = (f_2 >>> 4) + m(t, g, 15 & f_2); + for (g += 15 & f_2; A < e_8;) + r[A] = r[A++ - l_2], r[A] = r[A++ - l_2], r[A] = r[A++ - l_2], r[A] = r[A++ - l_2]; + A = e_8; + } + } + } + } else { + 0 != (7 & g) && (g += 8 - (7 & g)); + var o_5 = 4 + (g >>> 3), a_3 = t[o_5 - 4] | t[o_5 - 3] << 8; + _ && (r = e.H.W(r, A + a_3)), r.set(new i(t.buffer, t.byteOffset + o_5, a_3), A), g = o_5 + a_3 << 3, A += a_3; + } + return r.length == A ? r : r.slice(0, A); + }, e.H.W = function (e, t) { + var r = e.length; + if (t <= r) + return e; + var i = new Uint8Array(r << 1); + return i.set(e, 0), i; + }, e.H.R = function (t, r, i, o, a, s) { + var f = e.H.e, l = e.H.Z; + var c = 0; + for (; c < i;) { + var e_9 = t[l(o, a) & r]; + a += 15 & e_9; + var i_7 = e_9 >>> 4; + if (i_7 <= 15) + s[c] = i_7, c++; + else { + var e_10 = 0, t_3 = 0; + 16 == i_7 ? (t_3 = 3 + f(o, a, 2), a += 2, e_10 = s[c - 1]) : 17 == i_7 ? (t_3 = 3 + f(o, a, 3), a += 3) : 18 == i_7 && (t_3 = 11 + f(o, a, 7), a += 7); + var r_6 = c + t_3; + for (; c < r_6;) + s[c] = e_10, c++; + } + } + return a; + }, e.H.V = function (e, t, r, i) { + var o = 0, a = 0; + var s = i.length >>> 1; + for (; a < r;) { + var r_7 = e[a + t]; + i[a << 1] = 0, i[1 + (a << 1)] = r_7, r_7 > o && (o = r_7), a++; + } + for (; a < s;) + i[a << 1] = 0, i[1 + (a << 1)] = 0, a++; + return o; + }, e.H.n = function (t, r) { + var i = e.H.m, o = t.length; + var a, s, f; + var l; + var c = i.j; + for (var u = 0; u <= r; u++) + c[u] = 0; + for (u = 1; u < o; u += 2) + c[t[u]]++; + var h = i.K; + for (a = 0, c[0] = 0, s = 1; s <= r; s++) + a = a + c[s - 1] << 1, h[s] = a; + for (f = 0; f < o; f += 2) + l = t[f + 1], 0 != l && (t[f] = h[l], h[l]++); + }, e.H.A = function (t, r, i) { + var o = t.length, a = e.H.m.r; + for (var e_11 = 0; e_11 < o; e_11 += 2) + if (0 != t[e_11 + 1]) { + var o_6 = e_11 >> 1, s_4 = t[e_11 + 1], f_3 = o_6 << 4 | s_4, l_3 = r - s_4; + var c = t[e_11] << l_3; + var u = c + (1 << l_3); + for (; c != u;) { + i[a[c] >>> 15 - r] = f_3, c++; + } + } + }, e.H.l = function (t, r) { + var i = e.H.m.r, o = 15 - r; + for (var e_12 = 0; e_12 < t.length; e_12 += 2) { + var a_4 = t[e_12] << r - t[e_12 + 1]; + t[e_12] = i[a_4] >>> o; + } + }, e.H.M = function (e, t, r) { + r <<= 7 & t; + var i = t >>> 3; + e[i] |= r, e[i + 1] |= r >>> 8; + }, e.H.I = function (e, t, r) { + r <<= 7 & t; + var i = t >>> 3; + e[i] |= r, e[i + 1] |= r >>> 8, e[i + 2] |= r >>> 16; + }, e.H.e = function (e, t, r) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8) >>> (7 & t) & (1 << r) - 1; + }, e.H.b = function (e, t, r) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t) & (1 << r) - 1; + }, e.H.Z = function (e, t) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t); + }, e.H.i = function (e, t) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16 | e[3 + (t >>> 3)] << 24) >>> (7 & t); + }, e.H.m = function () { + var e = Uint16Array, t = Uint32Array; + return { + K: new e(16), + j: new e(16), + X: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], + S: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999], + T: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0], + q: new e(32), + p: [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535], + z: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0], + c: new t(32), + J: new e(512), + _: [], + h: new e(32), + $: [], + w: new e(32768), + C: [], + v: [], + d: new e(32768), + D: [], + u: new e(512), + Q: [], + r: new e(32768), + s: new t(286), + Y: new t(30), + a: new t(19), + t: new t(15e3), + k: new e(65536), + g: new e(32768) + }; + }(), function () { + var t = e.H.m; + for (var r = 0; r < 32768; r++) { + var e_13 = r; + e_13 = (2863311530 & e_13) >>> 1 | (1431655765 & e_13) << 1, e_13 = (3435973836 & e_13) >>> 2 | (858993459 & e_13) << 2, e_13 = (4042322160 & e_13) >>> 4 | (252645135 & e_13) << 4, e_13 = (4278255360 & e_13) >>> 8 | (16711935 & e_13) << 8, t.r[r] = (e_13 >>> 16 | e_13 << 16) >>> 17; + } + + function n(e, t, r) { + for (; 0 != t--;) + e.push(0, r); + } + + for (r = 0; r < 32; r++) + t.q[r] = t.S[r] << 3 | t.T[r], t.c[r] = t.p[r] << 4 | t.z[r]; + n(t._, 144, 8), n(t._, 112, 9), n(t._, 24, 7), n(t._, 8, 8), e.H.n(t._, 9), e.H.A(t._, 9, t.J), e.H.l(t._, 9), n(t.$, 32, 5), e.H.n(t.$, 5), e.H.A(t.$, 5, t.h), e.H.l(t.$, 5), n(t.Q, 19, 0), n(t.C, 286, 0), n(t.D, 30, 0), n(t.v, 320, 0); + }(), e.H.N; + }(); + + function _getBPP(e) { + return [1, null, 3, 1, 2, null, 4][e.ctype] * e.depth; + } + + function _filterZero(e, t, r, i, o) { + var a = _getBPP(t); + var s = Math.ceil(i * a / 8); + var f, l; + a = Math.ceil(a / 8); + var c = e[r], u = 0; + if (c > 1 && (e[r] = [0, 0, 1][c - 2]), 3 == c) + for (u = a; u < s; u++) + e[u + 1] = e[u + 1] + (e[u + 1 - a] >>> 1) & 255; + for (var t_4 = 0; t_4 < o; t_4++) + if (f = r + t_4 * s, l = f + t_4 + 1, c = e[l - 1], u = 0, 0 == c) + for (; u < s; u++) + e[f + u] = e[l + u]; + else if (1 == c) { + for (; u < a; u++) + e[f + u] = e[l + u]; + for (; u < s; u++) + e[f + u] = e[l + u] + e[f + u - a]; + } else if (2 == c) + for (; u < s; u++) + e[f + u] = e[l + u] + e[f + u - s]; + else if (3 == c) { + for (; u < a; u++) + e[f + u] = e[l + u] + (e[f + u - s] >>> 1); + for (; u < s; u++) + e[f + u] = e[l + u] + (e[f + u - s] + e[f + u - a] >>> 1); + } else { + for (; u < a; u++) + e[f + u] = e[l + u] + _paeth(0, e[f + u - s], 0); + for (; u < s; u++) + e[f + u] = e[l + u] + _paeth(e[f + u - a], e[f + u - s], e[f + u - a - s]); + } + return e; + } + + function _paeth(e, t, r) { + var i = e + t - r, o = i - e, a = i - t, s = i - r; + return o * o <= a * a && o * o <= s * s ? e : a * a <= s * s ? t : r; + } + + function _IHDR(t, r, i) { + i.width = e.readUint(t, r), r += 4, i.height = e.readUint(t, r), r += 4, i.depth = t[r], r++, i.ctype = t[r], r++, i.compress = t[r], r++, i.filter = t[r], r++, i.interlace = t[r], r++; + } + + function _copyTile(e, t, r, i, o, a, s, f, l) { + var c = Math.min(t, o), u = Math.min(r, a); + var h = 0, d = 0; + for (var r_8 = 0; r_8 < u; r_8++) + for (var a_5 = 0; a_5 < c; a_5++) + if (s >= 0 && f >= 0 ? (h = r_8 * t + a_5 << 2, d = (f + r_8) * o + s + a_5 << 2) : (h = (-f + r_8) * t - s + a_5 << 2, d = r_8 * o + a_5 << 2), 0 == l) + i[d] = e[h], i[d + 1] = e[h + 1], i[d + 2] = e[h + 2], i[d + 3] = e[h + 3]; + else if (1 == l) { + var A = e[h + 3] * (1 / 255), g = e[h] * A, p = e[h + 1] * A, m = e[h + 2] * A, + w = i[d + 3] * (1 / 255), v = i[d] * w, b = i[d + 1] * w, y = i[d + 2] * w; + var t_5 = 1 - A, r_9 = A + w * t_5, o_7 = 0 == r_9 ? 0 : 1 / r_9; + i[d + 3] = 255 * r_9, i[d + 0] = (g + v * t_5) * o_7, i[d + 1] = (p + b * t_5) * o_7, i[d + 2] = (m + y * t_5) * o_7; + } else if (2 == l) { + A = e[h + 3], g = e[h], p = e[h + 1], m = e[h + 2], w = i[d + 3], v = i[d], b = i[d + 1], y = i[d + 2]; + A == w && g == v && p == b && m == y ? (i[d] = 0, i[d + 1] = 0, i[d + 2] = 0, i[d + 3] = 0) : (i[d] = g, i[d + 1] = p, i[d + 2] = m, i[d + 3] = A); + } else if (3 == l) { + A = e[h + 3], g = e[h], p = e[h + 1], m = e[h + 2], w = i[d + 3], v = i[d], b = i[d + 1], y = i[d + 2]; + if (A == w && g == v && p == b && m == y) + continue; + if (A < 220 && w > 20) + return !1; + } + return !0; + } + + return { + decode: function decode(r) { + var i = new Uint8Array(r); + var o = 8; + var a = e, s = a.readUshort, f = a.readUint, l = {tabs: {}, frames: []}, c = new Uint8Array(i.length); + var u, h = 0, d = 0; + var A = [137, 80, 78, 71, 13, 10, 26, 10]; + for (var g = 0; g < 8; g++) + if (i[g] != A[g]) + throw "The input is not a PNG file!"; + for (; o < i.length;) { + var e_14 = a.readUint(i, o); + o += 4; + var r_10 = a.readASCII(i, o, 4); + if (o += 4, "IHDR" == r_10) + _IHDR(i, o, l); + else if ("iCCP" == r_10) { + for (var p = o; 0 != i[p];) + p++; + a.readASCII(i, o, p - o), i[p + 1]; + var s_5 = i.slice(p + 2, o + e_14); + var f_4 = null; + try { + f_4 = _inflate(s_5); + } catch (e) { + f_4 = t(s_5); + } + l.tabs[r_10] = f_4; + } else if ("CgBI" == r_10) + l.tabs[r_10] = i.slice(o, o + 4); + else if ("IDAT" == r_10) { + for (g = 0; g < e_14; g++) + c[h + g] = i[o + g]; + h += e_14; + } else if ("acTL" == r_10) + l.tabs[r_10] = { + num_frames: f(i, o), + num_plays: f(i, o + 4) + }, u = new Uint8Array(i.length); + else if ("fcTL" == r_10) { + if (0 != d) + (E = l.frames[l.frames.length - 1]).data = _decompress(l, u.slice(0, d), E.rect.width, E.rect.height), d = 0; + var e_15 = {x: f(i, o + 12), y: f(i, o + 16), width: f(i, o + 4), height: f(i, o + 8)}; + var t_6 = s(i, o + 22); + t_6 = s(i, o + 20) / (0 == t_6 ? 100 : t_6); + var r_11 = {rect: e_15, delay: Math.round(1e3 * t_6), dispose: i[o + 24], blend: i[o + 25]}; + l.frames.push(r_11); + } else if ("fdAT" == r_10) { + for (g = 0; g < e_14 - 4; g++) + u[d + g] = i[o + g + 4]; + d += e_14 - 4; + } else if ("pHYs" == r_10) + l.tabs[r_10] = [a.readUint(i, o), a.readUint(i, o + 4), i[o + 8]]; + else if ("cHRM" == r_10) { + l.tabs[r_10] = []; + for (g = 0; g < 8; g++) + l.tabs[r_10].push(a.readUint(i, o + 4 * g)); + } else if ("tEXt" == r_10 || "zTXt" == r_10) { + null == l.tabs[r_10] && (l.tabs[r_10] = {}); + var m = a.nextZero(i, o), w = a.readASCII(i, o, m - o), v = o + e_14 - m - 1; + if ("tEXt" == r_10) + y = a.readASCII(i, m + 1, v); + else { + var b = _inflate(i.slice(m + 2, m + 2 + v)); + y = a.readUTF8(b, 0, b.length); + } + l.tabs[r_10][w] = y; + } else if ("iTXt" == r_10) { + null == l.tabs[r_10] && (l.tabs[r_10] = {}); + m = 0, p = o; + m = a.nextZero(i, p); + w = a.readASCII(i, p, m - p); + var t_7 = i[p = m + 1]; + var y; + i[p + 1], p += 2, m = a.nextZero(i, p), a.readASCII(i, p, m - p), p = m + 1, m = a.nextZero(i, p), a.readUTF8(i, p, m - p); + v = e_14 - ((p = m + 1) - o); + if (0 == t_7) + y = a.readUTF8(i, p, v); + else { + b = _inflate(i.slice(p, p + v)); + y = a.readUTF8(b, 0, b.length); + } + l.tabs[r_10][w] = y; + } else if ("PLTE" == r_10) + l.tabs[r_10] = a.readBytes(i, o, e_14); + else if ("hIST" == r_10) { + var e_16 = l.tabs.PLTE.length / 3; + l.tabs[r_10] = []; + for (g = 0; g < e_16; g++) + l.tabs[r_10].push(s(i, o + 2 * g)); + } else if ("tRNS" == r_10) + 3 == l.ctype ? l.tabs[r_10] = a.readBytes(i, o, e_14) : 0 == l.ctype ? l.tabs[r_10] = s(i, o) : 2 == l.ctype && (l.tabs[r_10] = [s(i, o), s(i, o + 2), s(i, o + 4)]); + else if ("gAMA" == r_10) + l.tabs[r_10] = a.readUint(i, o) / 1e5; + else if ("sRGB" == r_10) + l.tabs[r_10] = i[o]; + else if ("bKGD" == r_10) + 0 == l.ctype || 4 == l.ctype ? l.tabs[r_10] = [s(i, o)] : 2 == l.ctype || 6 == l.ctype ? l.tabs[r_10] = [s(i, o), s(i, o + 2), s(i, o + 4)] : 3 == l.ctype && (l.tabs[r_10] = i[o]); + else if ("IEND" == r_10) + break; + o += e_14, a.readUint(i, o), o += 4; + } + var E; + return 0 != d && ((E = l.frames[l.frames.length - 1]).data = _decompress(l, u.slice(0, d), E.rect.width, E.rect.height)), l.data = _decompress(l, c, l.width, l.height), delete l.compress, delete l.interlace, delete l.filter, l; + }, toRGBA8: function toRGBA8(e) { + var t = e.width, r = e.height; + if (null == e.tabs.acTL) + return [decodeImage(e.data, t, r, e).buffer]; + var i = []; + null == e.frames[0].data && (e.frames[0].data = e.data); + var o = t * r * 4, a = new Uint8Array(o), s = new Uint8Array(o), f = new Uint8Array(o); + for (var c = 0; c < e.frames.length; c++) { + var u = e.frames[c], h = u.rect.x, d = u.rect.y, A = u.rect.width, g = u.rect.height, + p = decodeImage(u.data, A, g, e); + if (0 != c) + for (var l = 0; l < o; l++) + f[l] = a[l]; + if (0 == u.blend ? _copyTile(p, A, g, a, t, r, h, d, 0) : 1 == u.blend && _copyTile(p, A, g, a, t, r, h, d, 1), i.push(a.buffer.slice(0)), 0 == u.dispose) + ; + else if (1 == u.dispose) + _copyTile(s, A, g, a, t, r, h, d, 0); + else if (2 == u.dispose) + for (l = 0; l < o; l++) + a[l] = f[l]; + } + return i; + }, _paeth: _paeth, _copyTile: _copyTile, _bin: e + }; + }(); + !function () { + var e = UPNG._copyTile, t = UPNG._bin, r = UPNG._paeth; + var i = { + table: function () { + var e = new Uint32Array(256); + for (var t_8 = 0; t_8 < 256; t_8++) { + var r_12 = t_8; + for (var e_17 = 0; e_17 < 8; e_17++) + 1 & r_12 ? r_12 = 3988292384 ^ r_12 >>> 1 : r_12 >>>= 1; + e[t_8] = r_12; + } + return e; + }(), + update: function (e, t, r, o) { + for (var a_6 = 0; a_6 < o; a_6++) + e = i.table[255 & (e ^ t[r + a_6])] ^ e >>> 8; + return e; + }, + crc: function (e, t, r) { + return 4294967295 ^ i.update(4294967295, e, t, r); + } + }; + + function addErr(e, t, r, i) { + t[r] += e[0] * i >> 4, t[r + 1] += e[1] * i >> 4, t[r + 2] += e[2] * i >> 4, t[r + 3] += e[3] * i >> 4; + } + + function N(e) { + return Math.max(0, Math.min(255, e)); + } + + function D(e, t) { + var r = e[0] - t[0], i = e[1] - t[1], o = e[2] - t[2], a = e[3] - t[3]; + return r * r + i * i + o * o + a * a; + } + + function dither(e, t, r, i, o, a, s) { + null == s && (s = 1); + var f = i.length, l = []; + for (var c = 0; c < f; c++) { + var e_18 = i[c]; + l.push([e_18 >>> 0 & 255, e_18 >>> 8 & 255, e_18 >>> 16 & 255, e_18 >>> 24 & 255]); + } + for (c = 0; c < f; c++) { + var e_19 = 4294967295; + for (var u = 0, h = 0; h < f; h++) { + var d = D(l[c], l[h]); + h != c && d < e_19 && (e_19 = d, u = h); + } + } + var A = new Uint32Array(o.buffer), g = new Int16Array(t * r * 4), + p = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5]; + for (c = 0; c < p.length; c++) + p[c] = 255 * ((p[c] + .5) / 16 - .5); + for (var o_8 = 0; o_8 < r; o_8++) + for (var w = 0; w < t; w++) { + var m; + c = 4 * (o_8 * t + w); + if (2 != s) + m = [N(e[c] + g[c]), N(e[c + 1] + g[c + 1]), N(e[c + 2] + g[c + 2]), N(e[c + 3] + g[c + 3])]; + else { + d = p[4 * (3 & o_8) + (3 & w)]; + m = [N(e[c] + d), N(e[c + 1] + d), N(e[c + 2] + d), N(e[c + 3] + d)]; + } + u = 0; + var v = 16777215; + for (h = 0; h < f; h++) { + var e_20 = D(m, l[h]); + e_20 < v && (v = e_20, u = h); + } + var b = l[u], y = [m[0] - b[0], m[1] - b[1], m[2] - b[2], m[3] - b[3]]; + 1 == s && (w != t - 1 && addErr(y, g, c + 4, 7), o_8 != r - 1 && (0 != w && addErr(y, g, c + 4 * t - 4, 3), addErr(y, g, c + 4 * t, 5), w != t - 1 && addErr(y, g, c + 4 * t + 4, 1))), a[c >> 2] = u, A[c >> 2] = i[u]; + } + } + + function _main(e, r, o, a, s) { + null == s && (s = {}); + var f = i.crc, l = t.writeUint, c = t.writeUshort, u = t.writeASCII; + var h = 8; + var d = e.frames.length > 1; + var A, g = !1, p = 33 + (d ? 20 : 0); + if (null != s.sRGB && (p += 13), null != s.pHYs && (p += 21), null != s.iCCP && (A = pako.deflate(s.iCCP), p += 21 + A.length + 4), 3 == e.ctype) { + for (var m = e.plte.length, w = 0; w < m; w++) + e.plte[w] >>> 24 != 255 && (g = !0); + p += 8 + 3 * m + 4 + (g ? 8 + 1 * m + 4 : 0); + } + for (var v = 0; v < e.frames.length; v++) { + d && (p += 38), p += (F = e.frames[v]).cimg.length + 12, 0 != v && (p += 4); + } + p += 12; + var b = new Uint8Array(p), y = [137, 80, 78, 71, 13, 10, 26, 10]; + for (w = 0; w < 8; w++) + b[w] = y[w]; + if (l(b, h, 13), h += 4, u(b, h, "IHDR"), h += 4, l(b, h, r), h += 4, l(b, h, o), h += 4, b[h] = e.depth, h++, b[h] = e.ctype, h++, b[h] = 0, h++, b[h] = 0, h++, b[h] = 0, h++, l(b, h, f(b, h - 17, 17)), h += 4, null != s.sRGB && (l(b, h, 1), h += 4, u(b, h, "sRGB"), h += 4, b[h] = s.sRGB, h++, l(b, h, f(b, h - 5, 5)), h += 4), null != s.iCCP) { + var e_21 = 13 + A.length; + l(b, h, e_21), h += 4, u(b, h, "iCCP"), h += 4, u(b, h, "ICC profile"), h += 11, h += 2, b.set(A, h), h += A.length, l(b, h, f(b, h - (e_21 + 4), e_21 + 4)), h += 4; + } + if (null != s.pHYs && (l(b, h, 9), h += 4, u(b, h, "pHYs"), h += 4, l(b, h, s.pHYs[0]), h += 4, l(b, h, s.pHYs[1]), h += 4, b[h] = s.pHYs[2], h++, l(b, h, f(b, h - 13, 13)), h += 4), d && (l(b, h, 8), h += 4, u(b, h, "acTL"), h += 4, l(b, h, e.frames.length), h += 4, l(b, h, null != s.loop ? s.loop : 0), h += 4, l(b, h, f(b, h - 12, 12)), h += 4), 3 == e.ctype) { + l(b, h, 3 * (m = e.plte.length)), h += 4, u(b, h, "PLTE"), h += 4; + for (w = 0; w < m; w++) { + var t_9 = 3 * w, r_13 = e.plte[w], i_8 = 255 & r_13, o_9 = r_13 >>> 8 & 255, + a_7 = r_13 >>> 16 & 255; + b[h + t_9 + 0] = i_8, b[h + t_9 + 1] = o_9, b[h + t_9 + 2] = a_7; + } + if (h += 3 * m, l(b, h, f(b, h - 3 * m - 4, 3 * m + 4)), h += 4, g) { + l(b, h, m), h += 4, u(b, h, "tRNS"), h += 4; + for (w = 0; w < m; w++) + b[h + w] = e.plte[w] >>> 24 & 255; + h += m, l(b, h, f(b, h - m - 4, m + 4)), h += 4; + } + } + var E = 0; + for (v = 0; v < e.frames.length; v++) { + var F = e.frames[v]; + d && (l(b, h, 26), h += 4, u(b, h, "fcTL"), h += 4, l(b, h, E++), h += 4, l(b, h, F.rect.width), h += 4, l(b, h, F.rect.height), h += 4, l(b, h, F.rect.x), h += 4, l(b, h, F.rect.y), h += 4, c(b, h, a[v]), h += 2, c(b, h, 1e3), h += 2, b[h] = F.dispose, h++, b[h] = F.blend, h++, l(b, h, f(b, h - 30, 30)), h += 4); + var t_10 = F.cimg; + l(b, h, (m = t_10.length) + (0 == v ? 0 : 4)), h += 4; + var r_14 = h; + u(b, h, 0 == v ? "IDAT" : "fdAT"), h += 4, 0 != v && (l(b, h, E++), h += 4), b.set(t_10, h), h += m, l(b, h, f(b, r_14, h - r_14)), h += 4; + } + return l(b, h, 0), h += 4, u(b, h, "IEND"), h += 4, l(b, h, f(b, h - 4, 4)), h += 4, b.buffer; + } + + function compressPNG(e, t, r) { + for (var i_9 = 0; i_9 < e.frames.length; i_9++) { + var o_10 = e.frames[i_9]; + o_10.rect.width; + var a_8 = o_10.rect.height, s_6 = new Uint8Array(a_8 * o_10.bpl + a_8); + o_10.cimg = _filterZero(o_10.img, a_8, o_10.bpp, o_10.bpl, s_6, t, r); + } + } + + function compress(t, r, i, o, a) { + var s = a[0], f = a[1], l = a[2], c = a[3], u = a[4], h = a[5]; + var d = 6, A = 8, g = 255; + for (var p = 0; p < t.length; p++) { + var e_22 = new Uint8Array(t[p]); + for (var m = e_22.length, w = 0; w < m; w += 4) + g &= e_22[w + 3]; + } + var v = 255 != g, b = function framize(t, r, i, o, a, s) { + var f = []; + for (var l = 0; l < t.length; l++) { + var h_1 = new Uint8Array(t[l]), A_1 = new Uint32Array(h_1.buffer); + var c; + var g_1 = 0, p_1 = 0, m_1 = r, w_1 = i, v_1 = o ? 1 : 0; + if (0 != l) { + var b_1 = s || o || 1 == l || 0 != f[l - 2].dispose ? 1 : 2; + var y_1 = 0, E_1 = 1e9; + for (var e_23 = 0; e_23 < b_1; e_23++) { + var u = new Uint8Array(t[l - 1 - e_23]); + var o_11 = new Uint32Array(t[l - 1 - e_23]); + var s_7 = r, f_5 = i, c_2 = -1, h_2 = -1; + for (var e_24 = 0; e_24 < i; e_24++) + for (var t_11 = 0; t_11 < r; t_11++) { + A_1[d = e_24 * r + t_11] != o_11[d] && (t_11 < s_7 && (s_7 = t_11), t_11 > c_2 && (c_2 = t_11), e_24 < f_5 && (f_5 = e_24), e_24 > h_2 && (h_2 = e_24)); + } + -1 == c_2 && (s_7 = f_5 = c_2 = h_2 = 0), a && (1 == (1 & s_7) && s_7--, 1 == (1 & f_5) && f_5--); + var v_2 = (c_2 - s_7 + 1) * (h_2 - f_5 + 1); + v_2 < E_1 && (E_1 = v_2, y_1 = e_23, g_1 = s_7, p_1 = f_5, m_1 = c_2 - s_7 + 1, w_1 = h_2 - f_5 + 1); + } + u = new Uint8Array(t[l - 1 - y_1]); + 1 == y_1 && (f[l - 1].dispose = 2), c = new Uint8Array(m_1 * w_1 * 4), e(u, r, i, c, m_1, w_1, -g_1, -p_1, 0), v_1 = e(h_1, r, i, c, m_1, w_1, -g_1, -p_1, 3) ? 1 : 0, 1 == v_1 ? _prepareDiff(h_1, r, i, c, { + x: g_1, + y: p_1, + width: m_1, + height: w_1 + }) : e(h_1, r, i, c, m_1, w_1, -g_1, -p_1, 0); + } else + c = h_1.slice(0); + f.push({rect: {x: g_1, y: p_1, width: m_1, height: w_1}, img: c, blend: v_1, dispose: 0}); + } + if (o) + for (l = 0; l < f.length; l++) { + if (1 == (A = f[l]).blend) + continue; + var e_25 = A.rect, o_12 = f[l - 1].rect, s_8 = Math.min(e_25.x, o_12.x), + c_3 = Math.min(e_25.y, o_12.y), u_1 = { + x: s_8, + y: c_3, + width: Math.max(e_25.x + e_25.width, o_12.x + o_12.width) - s_8, + height: Math.max(e_25.y + e_25.height, o_12.y + o_12.height) - c_3 + }; + f[l - 1].dispose = 1, l - 1 != 0 && _updateFrame(t, r, i, f, l - 1, u_1, a), _updateFrame(t, r, i, f, l, u_1, a); + } + var h = 0; + if (1 != t.length) + for (var d = 0; d < f.length; d++) { + var A; + h += (A = f[d]).rect.width * A.rect.height; + } + return f; + }(t, r, i, s, f, l), y = {}, E = [], F = []; + if (0 != o) { + var e_26 = []; + for (w = 0; w < b.length; w++) + e_26.push(b[w].img.buffer); + var t_12 = function concatRGBA(e) { + var t = 0; + for (var r = 0; r < e.length; r++) + t += e[r].byteLength; + var i = new Uint8Array(t); + var o = 0; + for (r = 0; r < e.length; r++) { + var t_13 = new Uint8Array(e[r]), a_9 = t_13.length; + for (var e_27 = 0; e_27 < a_9; e_27 += 4) { + var r_15 = t_13[e_27], a_10 = t_13[e_27 + 1], s_9 = t_13[e_27 + 2]; + var f_6 = t_13[e_27 + 3]; + 0 == f_6 && (r_15 = a_10 = s_9 = 0), i[o + e_27] = r_15, i[o + e_27 + 1] = a_10, i[o + e_27 + 2] = s_9, i[o + e_27 + 3] = f_6; + } + o += a_9; + } + return i.buffer; + }(e_26), r_16 = quantize(t_12, o); + for (w = 0; w < r_16.plte.length; w++) + E.push(r_16.plte[w].est.rgba); + var i_10 = 0; + for (w = 0; w < b.length; w++) { + var e_28 = (B = b[w]).img.length; + var _ = new Uint8Array(r_16.inds.buffer, i_10 >> 2, e_28 >> 2); + F.push(_); + var t_14 = new Uint8Array(r_16.abuf, i_10, e_28); + h && dither(B.img, B.rect.width, B.rect.height, E, t_14, _), B.img.set(t_14), i_10 += e_28; + } + } else + for (p = 0; p < b.length; p++) { + var B = b[p]; + var e_29 = new Uint32Array(B.img.buffer); + var U = B.rect.width; + m = e_29.length, _ = new Uint8Array(m); + F.push(_); + for (w = 0; w < m; w++) { + var t_15 = e_29[w]; + if (0 != w && t_15 == e_29[w - 1]) + _[w] = _[w - 1]; + else if (w > U && t_15 == e_29[w - U]) + _[w] = _[w - U]; + else { + var e_30 = y[t_15]; + if (null == e_30 && (y[t_15] = e_30 = E.length, E.push(t_15), E.length >= 300)) + break; + _[w] = e_30; + } + } + } + var C = E.length; + C <= 256 && 0 == u && (A = C <= 2 ? 1 : C <= 4 ? 2 : C <= 16 ? 4 : 8, A = Math.max(A, c)); + for (p = 0; p < b.length; p++) { + (B = b[p]).rect.x, B.rect.y; + U = B.rect.width; + var e_31 = B.rect.height; + var t_16 = B.img; + new Uint32Array(t_16.buffer); + var r_17 = 4 * U, i_11 = 4; + if (C <= 256 && 0 == u) { + r_17 = Math.ceil(A * U / 8); + var I = new Uint8Array(r_17 * e_31); + var o_13 = F[p]; + for (var t_17 = 0; t_17 < e_31; t_17++) { + w = t_17 * r_17; + var e_32 = t_17 * U; + if (8 == A) + for (var Q = 0; Q < U; Q++) + I[w + Q] = o_13[e_32 + Q]; + else if (4 == A) + for (Q = 0; Q < U; Q++) + I[w + (Q >> 1)] |= o_13[e_32 + Q] << 4 - 4 * (1 & Q); + else if (2 == A) + for (Q = 0; Q < U; Q++) + I[w + (Q >> 2)] |= o_13[e_32 + Q] << 6 - 2 * (3 & Q); + else if (1 == A) + for (Q = 0; Q < U; Q++) + I[w + (Q >> 3)] |= o_13[e_32 + Q] << 7 - 1 * (7 & Q); + } + t_16 = I, d = 3, i_11 = 1; + } else if (0 == v && 1 == b.length) { + I = new Uint8Array(U * e_31 * 3); + var o_14 = U * e_31; + for (w = 0; w < o_14; w++) { + var e_33 = 3 * w, r_18 = 4 * w; + I[e_33] = t_16[r_18], I[e_33 + 1] = t_16[r_18 + 1], I[e_33 + 2] = t_16[r_18 + 2]; + } + t_16 = I, d = 2, i_11 = 3, r_17 = 3 * U; + } + B.img = t_16, B.bpl = r_17, B.bpp = i_11; + } + return {ctype: d, depth: A, plte: E, frames: b}; + } + + function _updateFrame(t, r, i, o, a, s, f) { + var l = Uint8Array, c = Uint32Array, u = new l(t[a - 1]), h = new c(t[a - 1]), + d = a + 1 < t.length ? new l(t[a + 1]) : null, A = new l(t[a]), g = new c(A.buffer); + var p = r, m = i, w = -1, v = -1; + for (var e_34 = 0; e_34 < s.height; e_34++) + for (var t_18 = 0; t_18 < s.width; t_18++) { + var i_12 = s.x + t_18, f_7 = s.y + e_34, l_4 = f_7 * r + i_12, c_4 = g[l_4]; + 0 == c_4 || 0 == o[a - 1].dispose && h[l_4] == c_4 && (null == d || 0 != d[4 * l_4 + 3]) || (i_12 < p && (p = i_12), i_12 > w && (w = i_12), f_7 < m && (m = f_7), f_7 > v && (v = f_7)); + } + -1 == w && (p = m = w = v = 0), f && (1 == (1 & p) && p--, 1 == (1 & m) && m--), s = { + x: p, + y: m, + width: w - p + 1, + height: v - m + 1 + }; + var b = o[a]; + b.rect = s, b.blend = 1, b.img = new Uint8Array(s.width * s.height * 4), 0 == o[a - 1].dispose ? (e(u, r, i, b.img, s.width, s.height, -s.x, -s.y, 0), _prepareDiff(A, r, i, b.img, s)) : e(A, r, i, b.img, s.width, s.height, -s.x, -s.y, 0); + } + + function _prepareDiff(t, r, i, o, a) { + e(t, r, i, o, a.width, a.height, -a.x, -a.y, 2); + } + + function _filterZero(e, t, r, i, o, a, s) { + var f = []; + var l, c = [0, 1, 2, 3, 4]; + -1 != a ? c = [a] : (t * i > 5e5 || 1 == r) && (c = [0]), s && (l = {level: 0}); + var u = UZIP; + for (var h = 0; h < c.length; h++) { + for (var a_11 = 0; a_11 < t; a_11++) + _filterLine(o, e, a_11, i, r, c[h]); + f.push(u.deflate(o, l)); + } + var d, A = 1e9; + for (h = 0; h < f.length; h++) + f[h].length < A && (d = h, A = f[h].length); + return f[d]; + } + + function _filterLine(e, t, i, o, a, s) { + var f = i * o; + var l = f + i; + if (e[l] = s, l++, 0 == s) + if (o < 500) + for (var c = 0; c < o; c++) + e[l + c] = t[f + c]; + else + e.set(new Uint8Array(t.buffer, f, o), l); + else if (1 == s) { + for (c = 0; c < a; c++) + e[l + c] = t[f + c]; + for (c = a; c < o; c++) + e[l + c] = t[f + c] - t[f + c - a] + 256 & 255; + } else if (0 == i) { + for (c = 0; c < a; c++) + e[l + c] = t[f + c]; + if (2 == s) + for (c = a; c < o; c++) + e[l + c] = t[f + c]; + if (3 == s) + for (c = a; c < o; c++) + e[l + c] = t[f + c] - (t[f + c - a] >> 1) + 256 & 255; + if (4 == s) + for (c = a; c < o; c++) + e[l + c] = t[f + c] - r(t[f + c - a], 0, 0) + 256 & 255; + } else { + if (2 == s) + for (c = 0; c < o; c++) + e[l + c] = t[f + c] + 256 - t[f + c - o] & 255; + if (3 == s) { + for (c = 0; c < a; c++) + e[l + c] = t[f + c] + 256 - (t[f + c - o] >> 1) & 255; + for (c = a; c < o; c++) + e[l + c] = t[f + c] + 256 - (t[f + c - o] + t[f + c - a] >> 1) & 255; + } + if (4 == s) { + for (c = 0; c < a; c++) + e[l + c] = t[f + c] + 256 - r(0, t[f + c - o], 0) & 255; + for (c = a; c < o; c++) + e[l + c] = t[f + c] + 256 - r(t[f + c - a], t[f + c - o], t[f + c - a - o]) & 255; + } + } + } + + function quantize(e, t) { + var r = new Uint8Array(e), i = r.slice(0), o = new Uint32Array(i.buffer), a = getKDtree(i, t), s = a[0], + f = a[1], l = r.length, c = new Uint8Array(l >> 2); + var u; + if (r.length < 2e7) + for (var h = 0; h < l; h += 4) { + u = getNearest(s, d = r[h] * (1 / 255), A = r[h + 1] * (1 / 255), g = r[h + 2] * (1 / 255), p = r[h + 3] * (1 / 255)), c[h >> 2] = u.ind, o[h >> 2] = u.est.rgba; + } + else + for (h = 0; h < l; h += 4) { + var d = r[h] * (1 / 255), A = r[h + 1] * (1 / 255), g = r[h + 2] * (1 / 255), + p = r[h + 3] * (1 / 255); + for (u = s; u.left;) + u = planeDst(u.est, d, A, g, p) <= 0 ? u.left : u.right; + c[h >> 2] = u.ind, o[h >> 2] = u.est.rgba; + } + return {abuf: i.buffer, inds: c, plte: f}; + } + + function getKDtree(e, t, r) { + null == r && (r = 1e-4); + var i = new Uint32Array(e.buffer), + o = {i0: 0, i1: e.length, bst: null, est: null, tdst: 0, left: null, right: null}; + o.bst = stats(e, o.i0, o.i1), o.est = estats(o.bst); + var a = [o]; + for (; a.length < t;) { + var t_19 = 0, o_15 = 0; + for (var s = 0; s < a.length; s++) + a[s].est.L > t_19 && (t_19 = a[s].est.L, o_15 = s); + if (t_19 < r) + break; + var f_8 = a[o_15], l_5 = splitPixels(e, i, f_8.i0, f_8.i1, f_8.est.e, f_8.est.eMq255); + if (f_8.i0 >= l_5 || f_8.i1 <= l_5) { + f_8.est.L = 0; + continue; + } + var c = {i0: f_8.i0, i1: l_5, bst: null, est: null, tdst: 0, left: null, right: null}; + c.bst = stats(e, c.i0, c.i1), c.est = estats(c.bst); + var u = {i0: l_5, i1: f_8.i1, bst: null, est: null, tdst: 0, left: null, right: null}; + u.bst = {R: [], m: [], N: f_8.bst.N - c.bst.N}; + for (s = 0; s < 16; s++) + u.bst.R[s] = f_8.bst.R[s] - c.bst.R[s]; + for (s = 0; s < 4; s++) + u.bst.m[s] = f_8.bst.m[s] - c.bst.m[s]; + u.est = estats(u.bst), f_8.left = c, f_8.right = u, a[o_15] = c, a.push(u); + } + a.sort((function (e, t) { + return t.bst.N - e.bst.N; + })); + for (s = 0; s < a.length; s++) + a[s].ind = s; + return [o, a]; + } + + function getNearest(e, t, r, i, o) { + if (null == e.left) + return e.tdst = function dist(e, t, r, i, o) { + var a = t - e[0], s = r - e[1], f = i - e[2], l = o - e[3]; + return a * a + s * s + f * f + l * l; + }(e.est.q, t, r, i, o), e; + var a = planeDst(e.est, t, r, i, o); + var s = e.left, f = e.right; + a > 0 && (s = e.right, f = e.left); + var l = getNearest(s, t, r, i, o); + if (l.tdst <= a * a) + return l; + var c = getNearest(f, t, r, i, o); + return c.tdst < l.tdst ? c : l; + } + + function planeDst(e, t, r, i, o) { + var a = e.e; + return a[0] * t + a[1] * r + a[2] * i + a[3] * o - e.eMq; + } + + function splitPixels(e, t, r, i, o, a) { + for (i -= 4; r < i;) { + for (; vecDot(e, r, o) <= a;) + r += 4; + for (; vecDot(e, i, o) > a;) + i -= 4; + if (r >= i) + break; + var s_10 = t[r >> 2]; + t[r >> 2] = t[i >> 2], t[i >> 2] = s_10, r += 4, i -= 4; + } + for (; vecDot(e, r, o) > a;) + r -= 4; + return r + 4; + } + + function vecDot(e, t, r) { + return e[t] * r[0] + e[t + 1] * r[1] + e[t + 2] * r[2] + e[t + 3] * r[3]; + } + + function stats(e, t, r) { + var i = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], o = [0, 0, 0, 0], a = r - t >> 2; + for (var a_12 = t; a_12 < r; a_12 += 4) { + var t_20 = e[a_12] * (1 / 255), r_19 = e[a_12 + 1] * (1 / 255), s_11 = e[a_12 + 2] * (1 / 255), + f_9 = e[a_12 + 3] * (1 / 255); + o[0] += t_20, o[1] += r_19, o[2] += s_11, o[3] += f_9, i[0] += t_20 * t_20, i[1] += t_20 * r_19, i[2] += t_20 * s_11, i[3] += t_20 * f_9, i[5] += r_19 * r_19, i[6] += r_19 * s_11, i[7] += r_19 * f_9, i[10] += s_11 * s_11, i[11] += s_11 * f_9, i[15] += f_9 * f_9; + } + return i[4] = i[1], i[8] = i[2], i[9] = i[6], i[12] = i[3], i[13] = i[7], i[14] = i[11], { + R: i, + m: o, + N: a + }; + } + + function estats(e) { + var t = e.R, r = e.m, i = e.N, a = r[0], s = r[1], f = r[2], l = r[3], c = 0 == i ? 0 : 1 / i, + u = [t[0] - a * a * c, t[1] - a * s * c, t[2] - a * f * c, t[3] - a * l * c, t[4] - s * a * c, t[5] - s * s * c, t[6] - s * f * c, t[7] - s * l * c, t[8] - f * a * c, t[9] - f * s * c, t[10] - f * f * c, t[11] - f * l * c, t[12] - l * a * c, t[13] - l * s * c, t[14] - l * f * c, t[15] - l * l * c], + h = u, d = o; + var A = [Math.random(), Math.random(), Math.random(), Math.random()], g = 0, p = 0; + if (0 != i) + for (var e_35 = 0; e_35 < 16 && (A = d.multVec(h, A), p = Math.sqrt(d.dot(A, A)), A = d.sml(1 / p, A), !(0 != e_35 && Math.abs(p - g) < 1e-9)); e_35++) + g = p; + var m = [a * c, s * c, f * c, l * c]; + return { + Cov: u, + q: m, + e: A, + L: g, + eMq255: d.dot(d.sml(255, m), A), + eMq: d.dot(A, m), + rgba: (Math.round(255 * m[3]) << 24 | Math.round(255 * m[2]) << 16 | Math.round(255 * m[1]) << 8 | Math.round(255 * m[0]) << 0) >>> 0 + }; + } + + var o = { + multVec: function (e, t) { + return [e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3], e[4] * t[0] + e[5] * t[1] + e[6] * t[2] + e[7] * t[3], e[8] * t[0] + e[9] * t[1] + e[10] * t[2] + e[11] * t[3], e[12] * t[0] + e[13] * t[1] + e[14] * t[2] + e[15] * t[3]]; + }, + dot: function (e, t) { + return e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3]; + }, + sml: function (e, t) { + return [e * t[0], e * t[1], e * t[2], e * t[3]]; + } + }; + UPNG.encode = function encode(e, t, r, i, o, a, s) { + null == i && (i = 0), null == s && (s = !1); + var f = compress(e, t, r, i, [!1, !1, !1, 0, s, !1]); + return compressPNG(f, -1), _main(f, t, r, o, a); + }, UPNG.encodeLL = function encodeLL(e, t, r, i, o, a, s, f) { + var l = {ctype: 0 + (1 == i ? 0 : 2) + (0 == o ? 0 : 4), depth: a, frames: []}, c = (i + o) * a, u = c * t; + for (var i_13 = 0; i_13 < e.length; i_13++) + l.frames.push({ + rect: {x: 0, y: 0, width: t, height: r}, + img: new Uint8Array(e[i_13]), + blend: 0, + dispose: 1, + bpp: Math.ceil(c / 8), + bpl: Math.ceil(u / 8) + }); + return compressPNG(l, 0, !0), _main(l, t, r, s, f); + }, UPNG.encode.compress = compress, UPNG.encode.dither = dither, UPNG.quantize = quantize, UPNG.quantize.getKDtree = getKDtree, UPNG.quantize.getNearest = getNearest; + }(); + var t = { + toArrayBuffer: function (e, r) { + var i = e.width, o = e.height, a = i << 2, s = e.getContext("2d").getImageData(0, 0, i, o), + f = new Uint32Array(s.data.buffer), l = (32 * i + 31) / 32 << 2, c = l * o, u = 122 + c, + h = new ArrayBuffer(u), d = new DataView(h), A = 1 << 20; + var g, p, m, w, v = A, b = 0, y = 0, E = 0; + + function set16(e) { + d.setUint16(y, e, !0), y += 2; + } + + function set32(e) { + d.setUint32(y, e, !0), y += 4; + } + + function seek(e) { + y += e; + } + + set16(19778), set32(u), seek(4), set32(122), set32(108), set32(i), set32(-o >>> 0), set16(1), set16(32), set32(3), set32(c), set32(2835), set32(2835), seek(8), set32(16711680), set32(65280), set32(255), set32(4278190080), set32(1466527264), function convert() { + for (; b < o && v > 0;) { + for (w = 122 + b * l, g = 0; g < a;) + v--, p = f[E++], m = p >>> 24, d.setUint32(w + g, p << 8 | m), g += 4; + b++; + } + E < f.length ? (v = A, setTimeout(convert, t._dly)) : r(h); + }(); + }, + toBlob: function (e, t) { + this.toArrayBuffer(e, (function (e) { + t(new window.Blob([e], {type: "image/bmp"})); + })); + }, + _dly: 9 + }; + var r = { + CHROME: "CHROME", + FIREFOX: "FIREFOX", + DESKTOP_SAFARI: "DESKTOP_SAFARI", + IE: "IE", + IOS: "IOS", + ETC: "ETC" + }, i = (_a = {}, + _a[r.CHROME] = 16384, + _a[r.FIREFOX] = 11180, + _a[r.DESKTOP_SAFARI] = 16384, + _a[r.IE] = 8192, + _a[r.IOS] = 4096, + _a[r.ETC] = 8192, + _a); + var o = "undefined" != typeof window, + a = "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope, + s = o && window.cordova && window.cordova.require && window.cordova.require("cordova/modulemapper"), + CustomFile = (o || a) && (s && s.getOriginalSymbol(window, "File") || "undefined" != typeof File && File), + CustomFileReader = (o || a) && (s && s.getOriginalSymbol(window, "FileReader") || "undefined" != typeof FileReader && FileReader); + + function getFilefromDataUrl(e, t, r) { + if (r === void 0) { + r = Date.now(); + } + return new Promise((function (i) { + var o = e.split(","), a = o[0].match(/:(.*?);/)[1], s = globalThis.atob(o[1]); + var f = s.length; + var l = new Uint8Array(f); + for (; f--;) + l[f] = s.charCodeAt(f); + var c = new window.Blob([l], {type: a}); + c.name = t, c.lastModified = r, i(c); + })); + } + + function getDataUrlFromFile(e) { + return new Promise((function (t, r) { + var i = new CustomFileReader; + i.onload = function () { + return t(i.result); + }, i.onerror = function (e) { + return r(e); + }, i.readAsDataURL(e); + })); + } + + function loadImage(e) { + return new Promise((function (t, r) { + var i = new Image; + i.onload = function () { + return t(i); + }, i.onerror = function (e) { + return r(e); + }, i.src = e; + })); + } + + function getBrowserName() { + if (void 0 !== getBrowserName.cachedResult) + return getBrowserName.cachedResult; + var e = r.ETC; + var t = navigator.userAgent; + return /Chrom(e|ium)/i.test(t) ? e = r.CHROME : /iP(ad|od|hone)/i.test(t) && /WebKit/i.test(t) ? e = r.IOS : /Safari/i.test(t) ? e = r.DESKTOP_SAFARI : /Firefox/i.test(t) ? e = r.FIREFOX : (/MSIE/i.test(t) || !0 == !!document.documentMode) && (e = r.IE), getBrowserName.cachedResult = e, getBrowserName.cachedResult; + } + + function approximateBelowMaximumCanvasSizeOfBrowser(e, t) { + var r = getBrowserName(), o = i[r]; + var a = e, s = t, f = a * s; + var l = a > s ? s / a : a / s; + for (; f > o * o;) { + var e_36 = (o + a) / 2, t_21 = (o + s) / 2; + e_36 < t_21 ? (s = t_21, a = t_21 * l) : (s = e_36 * l, a = e_36), f = a * s; + } + return {width: a, height: s}; + } + + function getNewCanvasAndCtx(e, t) { + var r, i; + try { + if (r = new OffscreenCanvas(e, t), i = r.getContext("2d"), null === i) + throw new Error("getContext of OffscreenCanvas returns null"); + } catch (e) { + r = document.createElement("canvas"), i = r.getContext("2d"); + } + return r.width = e, r.height = t, [r, i]; + } + + function drawImageInCanvas(e, t) { + var _a = approximateBelowMaximumCanvasSizeOfBrowser(e.width, e.height), r = _a.width, i = _a.height, + _b = getNewCanvasAndCtx(r, i), o = _b[0], a = _b[1]; + return t && /jpe?g/.test(t) && (a.fillStyle = "white", a.fillRect(0, 0, o.width, o.height)), a.drawImage(e, 0, 0, o.width, o.height), o; + } + + function isIOS() { + return void 0 !== isIOS.cachedResult || (isIOS.cachedResult = ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "undefined" != typeof document && "ontouchend" in document), isIOS.cachedResult; + } + + function drawFileInCanvas(e, t) { + if (t === void 0) { + t = {}; + } + return new Promise((function (i, o) { + var a, s; + var $Try_2_Post = function () { + try { + return s = drawImageInCanvas(a, t.fileType || e.type), i([a, s]); + } catch (e) { + return o(e); + } + }, $Try_2_Catch = function (t) { + try { + 0; + var $Try_3_Catch = function (e) { + try { + throw e; + } catch (e) { + return o(e); + } + }; + try { + var t_22; + return getDataUrlFromFile(e).then((function (e) { + try { + return t_22 = e, loadImage(t_22).then((function (e) { + try { + return a = e, function () { + try { + return $Try_2_Post(); + } catch (e) { + return o(e); + } + }(); + } catch (e) { + return $Try_3_Catch(e); + } + }), $Try_3_Catch); + } catch (e) { + return $Try_3_Catch(e); + } + }), $Try_3_Catch); + } catch (e) { + $Try_3_Catch(e); + } + } catch (e) { + return o(e); + } + }; + try { + if (isIOS() || [r.DESKTOP_SAFARI, r.MOBILE_SAFARI].includes(getBrowserName())) + throw new Error("Skip createImageBitmap on IOS and Safari"); + return createImageBitmap(e).then((function (e) { + try { + return a = e, $Try_2_Post(); + } catch (e) { + return $Try_2_Catch(); + } + }), $Try_2_Catch); + } catch (e) { + $Try_2_Catch(); + } + })); + } + + function canvasToFile(e, r, i, o, a) { + if (a === void 0) { + a = 1; + } + return new Promise((function (s, f) { + var l; + if ("image/png" === r) { + var c = void 0, u = void 0, h = void 0; + return c = e.getContext("2d"), (u = c.getImageData(0, 0, e.width, e.height).data), h = UPNG.encode([u.buffer], e.width, e.height, 4096 * a), l = new window.Blob([h], {type: r}), l.name = i, l.lastModified = o, $If_4.call(this); + } + { + if ("image/bmp" === r) + return new Promise((function (r) { + return t.toBlob(e, r); + })).then(function (e) { + try { + return l = e, l.name = i, l.lastModified = o, $If_5.call(this); + } catch (e) { + return f(e); + } + }.bind(this), f); + { + if ("function" == typeof OffscreenCanvas && e instanceof OffscreenCanvas) + return e.convertToBlob({ + type: r, + quality: a + }).then(function (e) { + try { + return l = e, l.name = i, l.lastModified = o, $If_6.call(this); + } catch (e) { + return f(e); + } + }.bind(this), f); + { + var d = void 0; + return d = e.toDataURL(r, a), getFilefromDataUrl(d, i, o).then(function (e) { + try { + return l = e, $If_6.call(this); + } catch (e) { + return f(e); + } + }.bind(this), f); + } + + function $If_6() { + return $If_5.call(this); + } + } + + function $If_5() { + return $If_4.call(this); + } + } + + function $If_4() { + return s(l); + } + })); + } + + function cleanupCanvasMemory(e) { + e.width = 0, e.height = 0; + } + + function isAutoOrientationInBrowser() { + return new Promise((function (e, t) { + var r, i, o, a, s; + return void 0 !== isAutoOrientationInBrowser.cachedResult ? e(isAutoOrientationInBrowser.cachedResult) : (r = "data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==", getFilefromDataUrl("data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==", "test.jpg", Date.now()).then((function (r) { + try { + return i = r, drawFileInCanvas(i).then((function (r) { + try { + return o = r[1], canvasToFile(o, i.type, i.name, i.lastModified).then((function (r) { + try { + return a = r, cleanupCanvasMemory(o), drawFileInCanvas(a).then((function (r) { + try { + return s = r[0], isAutoOrientationInBrowser.cachedResult = 1 === s.width && 2 === s.height, e(isAutoOrientationInBrowser.cachedResult); + } catch (e) { + return t(e); + } + }), t); + } catch (e) { + return t(e); + } + }), t); + } catch (e) { + return t(e); + } + }), t); + } catch (e) { + return t(e); + } + }), t)); + })); + } + + function getExifOrientation(e) { + return new Promise((function (t, r) { + var i = new CustomFileReader; + i.onload = function (e) { + var r = new DataView(e.target.result); + if (65496 != r.getUint16(0, !1)) + return t(-2); + var i = r.byteLength; + var o = 2; + for (; o < i;) { + if (r.getUint16(o + 2, !1) <= 8) + return t(-1); + var e_37 = r.getUint16(o, !1); + if (o += 2, 65505 == e_37) { + if (1165519206 != r.getUint32(o += 2, !1)) + return t(-1); + var e_38 = 18761 == r.getUint16(o += 6, !1); + o += r.getUint32(o + 4, e_38); + var i_14 = r.getUint16(o, e_38); + o += 2; + for (var a_13 = 0; a_13 < i_14; a_13++) + if (274 == r.getUint16(o + 12 * a_13, e_38)) + return t(r.getUint16(o + 12 * a_13 + 8, e_38)); + } else { + if (65280 != (65280 & e_37)) + break; + o += r.getUint16(o, !1); + } + } + return t(-1); + }, i.onerror = function (e) { + return r(e); + }, i.readAsArrayBuffer(e); + })); + } + + function handleMaxWidthOrHeight(e, t) { + var _a; + var r = e.width, i = e.height, o = t.maxWidthOrHeight; + var a, s = e; + return isFinite(o) && (r > o || i > o) && (_a = getNewCanvasAndCtx(r, i), s = _a[0], a = _a[1], r > i ? (s.width = o, s.height = i / r * o) : (s.width = r / i * o, s.height = o), a.drawImage(e, 0, 0, s.width, s.height), cleanupCanvasMemory(e)), s; + } + + function followExifOrientation(e, t) { + var r = e.width, i = e.height, _a = getNewCanvasAndCtx(r, i), o = _a[0], a = _a[1]; + switch (t > 4 && t < 9 ? (o.width = i, o.height = r) : (o.width = r, o.height = i), t) { + case 2: + a.transform(-1, 0, 0, 1, r, 0); + break; + case 3: + a.transform(-1, 0, 0, -1, r, i); + break; + case 4: + a.transform(1, 0, 0, -1, 0, i); + break; + case 5: + a.transform(0, 1, 1, 0, 0, 0); + break; + case 6: + a.transform(0, 1, -1, 0, i, 0); + break; + case 7: + a.transform(0, -1, -1, 0, i, r); + break; + case 8: + a.transform(0, -1, 1, 0, 0, r); + } + return a.drawImage(e, 0, 0, r, i), cleanupCanvasMemory(e), o; + } + + function compress(e, t, r) { + if (r === void 0) { + r = 0; + } + return new Promise((function (i, o) { + var a, s, f, l, c, u, h, d, A, g, p, m, w, v, b, y, E, F, _, B; + + function incProgress(e) { + if (e === void 0) { + e = 5; + } + if (t.signal && t.signal.aborted) + throw t.signal.reason; + a += e, t.onProgress(Math.min(a, 100)); + } + + function setProgress(e) { + if (t.signal && t.signal.aborted) + throw t.signal.reason; + a = Math.min(Math.max(e, a), 100), t.onProgress(a); + } + + return a = r, s = t.maxIteration || 10, f = 1024 * t.maxSizeMB * 1024, incProgress(), drawFileInCanvas(e, t).then(function (r) { + try { + return l = r[1], incProgress(), c = handleMaxWidthOrHeight(l, t), incProgress(), new Promise((function (r, i) { + var o; + if (!(o = t.exifOrientation)) + return getExifOrientation(e).then(function (e) { + try { + return o = e, $If_2.call(this); + } catch (e) { + return i(e); + } + }.bind(this), i); + + function $If_2() { + return r(o); + } + + return $If_2.call(this); + })).then(function (r) { + try { + return u = r, incProgress(), isAutoOrientationInBrowser().then(function (r) { + try { + return h = r ? c : followExifOrientation(c, u), incProgress(), d = t.initialQuality || 1, A = t.fileType || e.type, canvasToFile(h, A, e.name, e.lastModified, d).then(function (r) { + try { + { + if (g = r, incProgress(), p = g.size > f, m = g.size > e.size, !p && !m) + return setProgress(100), i(g); + var a; + + function $Loop_3() { + var _a; + if (s-- && (b > f || b > w)) { + var t_23, r_20; + return t_23 = B ? .95 * _.width : _.width, r_20 = B ? .95 * _.height : _.height, _a = getNewCanvasAndCtx(t_23, r_20), E = _a[0], F = _a[1], F.drawImage(_, 0, 0, t_23, r_20), d *= "image/png" === A ? .85 : .95, canvasToFile(E, A, e.name, e.lastModified, d).then((function (e) { + try { + return y = e, cleanupCanvasMemory(_), _ = E, b = y.size, setProgress(Math.min(99, Math.floor((v - b) / (v - f) * 100))), $Loop_3; + } catch (e) { + return o(e); + } + }), o); + } + return [1]; + } + + return w = e.size, v = g.size, b = v, _ = h, B = !t.alwaysKeepResolution && p, (a = function (e) { + for (; e;) { + if (e.then) + return void e.then(a, o); + try { + if (e.pop) { + if (e.length) + return e.pop() ? $Loop_3_exit.call(this) : e; + e = $Loop_3; + } else + e = e.call(this); + } catch (e) { + return o(e); + } + } + }.bind(this))($Loop_3); + + function $Loop_3_exit() { + return cleanupCanvasMemory(_), cleanupCanvasMemory(E), cleanupCanvasMemory(c), cleanupCanvasMemory(h), cleanupCanvasMemory(l), setProgress(100), i(y); + } + } + } catch (u) { + return o(u); + } + }.bind(this), o); + } catch (e) { + return o(e); + } + }.bind(this), o); + } catch (e) { + return o(e); + } + }.bind(this), o); + } catch (e) { + return o(e); + } + }.bind(this), o); + })); + } + + var f = "\nlet scriptImported = false\nself.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n options.onProgress = (progress) => self.postMessage({ progress, id })\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n self.importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message + '\\n' + e.stack, id })\n }\n})\n"; + var l; + + function compressOnWebWorker(e, t) { + return new Promise((function (r, i) { + l || (l = function createWorkerScriptURL(e) { + var t = []; + return "function" == typeof e ? t.push("(".concat(e, ")()")) : t.push(e), URL.createObjectURL(new window.Blob(t)); + }(f)); + var o = new Worker(l); + o.addEventListener("message", (function handler(e) { + if (t.signal && t.signal.aborted) + o.terminate(); + else if (void 0 === e.data.progress) { + if (e.data.error) + return i(new Error(e.data.error)), void o.terminate(); + r(e.data.file), o.terminate(); + } else + t.onProgress(e.data.progress); + })), o.addEventListener("error", i), t.signal && t.signal.addEventListener("abort", (function () { + i(t.signal.reason), o.terminate(); + })), o.postMessage({ + file: e, + imageCompressionLibUrl: t.libURL, + options: __assign(__assign({}, t), {onProgress: void 0, signal: void 0}) + }); + })); + } + + function imageCompression(e, t) { + return new Promise((function (r, i) { + var o, a, s, f, l, c; + if (o = __assign({}, t), s = 0, (f = o.onProgress), o.maxSizeMB = o.maxSizeMB || Number.POSITIVE_INFINITY, l = "boolean" != typeof o.useWebWorker || o.useWebWorker, delete o.useWebWorker, o.onProgress = function (e) { + s = e, "function" == typeof f && f(s); + }, !(e instanceof window.Blob || e instanceof CustomFile)) + return i(new Error("The file given is not an instance of Blob or File")); + if (!/^image/.test(e.type)) + return i(new Error("The file given is not an image")); + if (c = "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope, !l || "function" != typeof Worker || c) + return compress(e, o).then(function (e) { + try { + return a = e, $If_4.call(this); + } catch (e) { + return i(e); + } + }.bind(this), i); + var u = function () { + try { + return $If_4.call(this); + } catch (e) { + return i(e); + } + }.bind(this), $Try_1_Catch = function (t) { + try { + return compress(e, o).then((function (e) { + try { + return a = e, u(); + } catch (e) { + return i(e); + } + }), i); + } catch (e) { + return i(e); + } + }; + try { + return o.libURL = o.libURL || "https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js", compressOnWebWorker(e, o).then((function (e) { + try { + return a = e, u(); + } catch (e) { + return $Try_1_Catch(); + } + }), $Try_1_Catch); + } catch (e) { + $Try_1_Catch(); + } + + function $If_4() { + try { + a.name = e.name, a.lastModified = e.lastModified; + } catch (e) { + } + try { + o.preserveExif && "image/jpeg" === e.type && (!o.fileType || o.fileType && o.fileType === e.type) && (a = copyExifWithoutOrientation(e, a)); + } catch (e) { + } + return r(a); + } + })); + } + + return imageCompression.getDataUrlFromFile = getDataUrlFromFile, imageCompression.getFilefromDataUrl = getFilefromDataUrl, imageCompression.loadImage = loadImage, imageCompression.drawImageInCanvas = drawImageInCanvas, imageCompression.drawFileInCanvas = drawFileInCanvas, imageCompression.canvasToFile = canvasToFile, imageCompression.getExifOrientation = getExifOrientation, imageCompression.handleMaxWidthOrHeight = handleMaxWidthOrHeight, imageCompression.followExifOrientation = followExifOrientation, imageCompression.cleanupCanvasMemory = cleanupCanvasMemory, imageCompression.isAutoOrientationInBrowser = isAutoOrientationInBrowser, imageCompression.approximateBelowMaximumCanvasSizeOfBrowser = approximateBelowMaximumCanvasSizeOfBrowser, imageCompression.copyExifWithoutOrientation = copyExifWithoutOrientation, imageCompression.getBrowserName = getBrowserName, imageCompression.version = "2.0.2", imageCompression; + }); + + /** + * @fileOverview 图片操作, 负责预览图片和上传前压缩图片 + */ + define('widgets/image',[ + 'base', + 'uploader', + 'lib/image', + 'lib/browser-image-compression', + 'widgets/widget' + ], function( Base, Uploader, Image, imageCompression ) { + + var $ = Base.$, + throttle; + + // 根据要处理的文件大小来节流,一次不能处理太多,会卡。 + throttle = (function( max ) { + var occupied = 0, + waiting = [], + tick = function() { + var item; + + while ( waiting.length && occupied < max ) { + item = waiting.shift(); + occupied += item[ 0 ]; + item[ 1 ](); + } + }; + + return function( emiter, size, cb ) { + waiting.push([ size, cb ]); + emiter.once( 'destroy', function() { + occupied -= size; + setTimeout( tick, 1 ); + }); + setTimeout( tick, 1 ); + }; + })( 5 * 1024 * 1024 ); + + $.extend( Uploader.options, { + + /** + * @property {Object} [thumb] + * @namespace options + * @for Uploader + * @description 配置生成缩略图的选项。 + * + * 默认为: + * + * ```javascript + * { + * width: 110, + * height: 110, + * + * // 图片质量,只有type为`image/jpeg`的时候才有效。 + * quality: 70, + * + * // 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false. + * allowMagnify: true, + * + * // 是否允许裁剪。 + * crop: true, + * + * // 为空的话则保留原有图片格式。 + * // 否则强制转换成指定的类型。 + * type: 'image/jpeg' + * } + * ``` + */ + thumb: { + width: 110, + height: 110, + quality: 70, + allowMagnify: true, + crop: true, + preserveHeaders: false, + + // 为空的话则保留原有图片格式。 + // 否则强制转换成指定的类型。 + // IE 8下面 base64 大小不能超过 32K 否则预览失败,而非 jpeg 编码的图片很可 + // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg + type: 'image/jpeg' + }, + compress: { + // 是否开启 + enable: false, + // 压缩最大宽度或高度 + maxWidthOrHeight: 4000, + // 压缩的最大大小 + maxSize: 10*1024*1024, + } + }); + + return Uploader.register({ + + name: 'image', + + + /** + * 生成缩略图,此过程为异步,所以需要传入`callback`。 + * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。 + * + * 当 width 或者 height 的值介于 0 - 1 时,被当成百分比使用。 + * + * `callback`中可以接收到两个参数。 + * * 第一个为error,如果生成缩略图有错误,此error将为真。 + * * 第二个为ret, 缩略图的Data URL值。 + * + * **注意** + * Date URL在IE6/7中不支持,所以不用调用此方法了,直接显示一张暂不支持预览图片好了。 + * 也可以借助服务端,将 base64 数据传给服务端,生成一个临时文件供预览。 + * + * @method makeThumb + * @grammar makeThumb( file, callback ) => undefined + * @grammar makeThumb( file, callback, width, height ) => undefined + * @for Uploader + * @example + * + * uploader.on( 'fileQueued', function( file ) { + * var $li = ...; + * + * uploader.makeThumb( file, function( error, ret ) { + * if ( error ) { + * $li.text('预览错误'); + * } else { + * $li.append(''); + * } + * }); + * + * }); + */ + makeThumb: function( file, cb, width, height ) { + var opts, image; + + file = this.request( 'get-file', file ); + + // 只预览图片格式。 + if ( !file.type.match( /^image/ ) ) { + cb( true ); + return; + } + + opts = $.extend({}, this.options.thumb ); + + // 如果传入的是object. + if ( $.isPlainObject( width ) ) { + opts = $.extend( opts, width ); + width = null; + } + + width = width || opts.width; + height = height || opts.height; + + image = new Image( opts ); + + image.once( 'load', function() { + file._info = file._info || image.info(); + file._meta = file._meta || image.meta(); + + // 如果 width 的值介于 0 - 1 + // 说明设置的是百分比。 + if ( width <= 1 && width > 0 ) { + width = file._info.width * width; + } + + // 同样的规则应用于 height + if ( height <= 1 && height > 0 ) { + height = file._info.height * height; + } + + image.resize( width, height ); + }); + + // 当 resize 完后 + image.once( 'complete', function() { + cb( false, image.getAsDataUrl( opts.type ) ); + image.destroy(); + }); + + image.once( 'error', function( reason ) { + cb( reason || true ); + image.destroy(); + }); + + throttle( image, file.source.size, function() { + file._info && image.info( file._info ); + file._meta && image.meta( file._meta ); + image.loadFromBlob( file.source ); + }); + }, + + beforeSendFile: function( file ) { + var opts = this.options.compress, image, me=this, deferred; + + // console.log('image.beforeSendFile',opts, file) + + file = this.request( 'get-file', file ); + + if(file._widgetImageData){ + return; + } + + var data = { + processed: false, + success: false, + originalSize: file.size, + }; + + if ( !opts || !opts.enable || !~'image/jpeg,image/jpg,image/png'.indexOf( file.type ) ) { + file._widgetImageData = data; + return; + } + + opts = $.extend({}, opts ); + deferred = Base.Deferred(); + + me.owner.trigger( 'fileProcessStart', 'imageCompress', file); + + imageCompression(file.source.source,{ + maxSizeMB: opts.maxSize/1024/1024, + maxWidthOrHeight: opts.maxWidthOrHeight, + }).then(function (compressedBlob) { + me.owner.trigger( 'fileProcessEnd', 'imageCompress', file); + if(opts.debug){ + console.log('webuploader.compress.output', (compressedBlob.size / file.size * 100).toFixed(2) + '%'); + } + var oldSize = file.size; + file.source.source = compressedBlob; + file.source.size = compressedBlob.size; + file.size = compressedBlob.size; + file.trigger( 'resize', compressedBlob.size, oldSize ); + data.processed = true; + data.success = true; + file._widgetImageData = data; + deferred.resolve(); + }).catch(function (error) { + console.warn('webuploader.compress.error',error); + me.owner.trigger( 'fileProcessEnd', 'imageCompress', file); + data.processed = true; + file._widgetImageData = data; + deferred.resolve(); + }); + + // image = new Image( opts ); + // + // deferred.always(function() { + // image.destroy(); + // image = null; + // }); + // image.once( 'error', deferred.reject ); + // image.once( 'load', function() { + // var width = opts.width, + // height = opts.height; + // + // file._info = file._info || image.info(); + // file._meta = file._meta || image.meta(); + // + // // 如果 width 的值介于 0 - 1 + // // 说明设置的是百分比。 + // if ( width <= 1 && width > 0 ) { + // width = file._info.width * width; + // } + // + // // 同样的规则应用于 height + // if ( height <= 1 && height > 0 ) { + // height = file._info.height * height; + // } + // + // image.resize( width, height ); + // }); + // + // image.once( 'complete', function() { + // var blob, size; + // + // // 移动端 UC / qq 浏览器的无图模式下 + // // ctx.getImageData 处理大图的时候会报 Exception + // // INDEX_SIZE_ERR: DOM Exception 1 + // try { + // blob = image.getAsBlob( opts.type ); + // + // size = file.size; + // + // // 如果压缩后,比原来还大则不用压缩后的。 + // if ( !noCompressIfLarger || blob.size < size ) { + // // file.source.destroy && file.source.destroy(); + // file.source = blob; + // file.size = blob.size; + // + // file.trigger( 'resize', blob.size, size ); + // } + // + // // 标记,避免重复压缩。 + // file._compressed = true; + // deferred.resolve(); + // } catch ( e ) { + // // 出错了直接继续,让其上传原始图片 + // deferred.resolve(); + // } + // }); + // + // file._info && image.info( file._info ); + // file._meta && image.meta( file._meta ); + // + // image.loadFromBlob( file.source ); + return deferred.promise(); + } + }); + }); + + /** + * @fileOverview 文件属性封装 + */ + define('file',[ + 'base', + 'mediator' + ], function( Base, Mediator ) { + + var $ = Base.$, + idPrefix = 'WU_FILE_', + idSuffix = 0, + rExt = /\.([^.]+)$/, + statusMap = {}; + + function gid() { + return idPrefix + idSuffix++; + } + + /** + * 文件类 + * @class File + * @constructor 构造函数 + * @grammar new File( source ) => File + * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。 + */ + function WUFile( source ) { + + /** + * 文件名,包括扩展名(后缀) + * @property name + * @type {string} + */ + this.name = source.name || 'Untitled'; + + /** + * 文件体积(字节) + * @property size + * @type {uint} + * @default 0 + */ + this.size = source.size || 0; + + /** + * 文件MIMETYPE类型,与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny) + * @property type + * @type {string} + * @default 'application/octet-stream' + */ + this.type = source.type || 'application/octet-stream'; + + /** + * 文件最后修改日期 + * @property lastModifiedDate + * @type {int} + * @default 当前时间戳 + */ + this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1); + + /** + * 文件ID,每个对象具有唯一ID,与文件名无关 + * @property id + * @type {string} + */ + this.id = gid(); + + /** + * 文件扩展名,通过文件名获取,例如test.png的扩展名为png + * @property ext + * @type {string} + */ + this.ext = rExt.exec( this.name ) ? RegExp.$1 : ''; + + + /** + * 状态文字说明。在不同的status语境下有不同的用途。 + * @property statusText + * @type {string} + */ + this.statusText = ''; + + // 存储文件状态,防止通过属性直接修改 + statusMap[ this.id ] = WUFile.Status.INITED; + + this.source = source; + this.loaded = 0; + + this.on( 'error', function( msg ) { + this.setStatus( WUFile.Status.ERROR, msg ); + }); + } + + $.extend( WUFile.prototype, { + + /** + * 设置状态,状态变化时会触发`change`事件。 + * @method setStatus + * @grammar setStatus( status[, statusText] ); + * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status) + * @param {String} [statusText=''] 状态说明,常在error时使用,用http, abort,server等来标记是由于什么原因导致文件错误。 + */ + setStatus: function( status, text ) { + + var prevStatus = statusMap[ this.id ]; + + typeof text !== 'undefined' && (this.statusText = text); + + if ( status !== prevStatus ) { + statusMap[ this.id ] = status; + /** + * 文件状态变化 + * @event statuschange + */ + this.trigger( 'statuschange', status, prevStatus ); + } + + }, + + /** + * 获取文件状态 + * @return {File.Status} + * @example + 文件状态具体包括以下几种类型: + { + // 初始化 + INITED: 0, + // 已入队列 + QUEUED: 1, + // 正在上传 + PROGRESS: 2, + // 上传出错 + ERROR: 3, + // 上传成功 + COMPLETE: 4, + // 上传取消 + CANCELLED: 5 + } + */ + getStatus: function() { + return statusMap[ this.id ]; + }, + + /** + * 获取文件原始信息。 + * @return {*} + */ + getSource: function() { + return this.source; + }, + + destroy: function() { + this.off(); + delete statusMap[ this.id ]; + } + }); + + Mediator.installTo( WUFile.prototype ); + + /** + * 文件状态值,具体包括以下几种类型: + * * `inited` 初始状态 + * * `queued` 已经进入队列, 等待上传 + * * `progress` 上传中 + * * `complete` 上传完成。 + * * `error` 上传出错,可重试 + * * `interrupt` 上传中断,可续传。 + * * `invalid` 文件不合格,不能重试上传。会自动从队列中移除。 + * * `cancelled` 文件被移除。 + * @property {Object} Status + * @namespace File + * @class File + * @static + */ + WUFile.Status = { + INITED: 'inited', // 初始状态 + QUEUED: 'queued', // 已经进入队列, 等待上传 + PROGRESS: 'progress', // 上传中 + ERROR: 'error', // 上传出错,可重试 + COMPLETE: 'complete', // 上传完成。 + CANCELLED: 'cancelled', // 上传取消。 + INTERRUPT: 'interrupt', // 上传中断,可续传。 + INVALID: 'invalid' // 文件不合格,不能重试上传。 + }; + + return WUFile; + }); + + /** + * @fileOverview 文件队列 + */ + define('queue',[ + 'base', + 'mediator', + 'file' + ], function( Base, Mediator, WUFile ) { + + var $ = Base.$, + STATUS = WUFile.Status; + + /** + * 文件队列, 用来存储各个状态中的文件。 + * @class Queue + * @extends Mediator + */ + function Queue() { + + /** + * 统计文件数。 + * * `numOfQueue` 队列中的文件数。 + * * `numOfSuccess` 上传成功的文件数 + * * `numOfCancel` 被取消的文件数 + * * `numOfProgress` 正在上传中的文件数 + * * `numOfUploadFailed` 上传错误的文件数。 + * * `numOfInvalid` 无效的文件数。 + * * `numOfDeleted` 被移除的文件数。 + * * `numOfInterrupt` 被中断的文件数。 + * @property {Object} stats + */ + this.stats = { + numOfQueue: 0, + numOfSuccess: 0, + numOfCancel: 0, + numOfProgress: 0, + numOfUploadFailed: 0, + numOfInvalid: 0, + numOfDeleted: 0, + numOfInterrupt: 0 + }; + + // 上传队列,仅包括等待上传的文件 + this._queue = []; + + // 存储所有文件 + this._map = {}; + } + + $.extend( Queue.prototype, { + + /** + * 将新文件加入对队列尾部 + * + * @method append + * @param {File} file 文件对象 + */ + append: function( file ) { + this._queue.push( file ); + this._fileAdded( file ); + return this; + }, + + /** + * 将新文件加入对队列头部 + * + * @method prepend + * @param {File} file 文件对象 + */ + prepend: function( file ) { + this._queue.unshift( file ); + this._fileAdded( file ); + return this; + }, + + /** + * 获取文件对象 + * + * @method getFile + * @param {String} fileId 文件ID + * @return {File} + */ + getFile: function( fileId ) { + if ( typeof fileId !== 'string' ) { + return fileId; + } + return this._map[ fileId ]; + }, + + /** + * 从队列中取出一个指定状态的文件。 + * @grammar fetch( status ) => File + * @method fetch + * @param {String} status [文件状态值](#WebUploader:File:File.Status) + * @return {File} [File](#WebUploader:File) + */ + fetch: function( status ) { + var len = this._queue.length, + i, file; + + status = status || STATUS.QUEUED; + + for ( i = 0; i < len; i++ ) { + file = this._queue[ i ]; + + if ( status === file.getStatus() ) { + return file; + } + } + + return null; + }, + + /** + * 对队列进行排序,能够控制文件上传顺序。 + * @grammar sort( fn ) => undefined + * @method sort + * @param {Function} fn 排序方法 + */ + sort: function( fn ) { + if ( typeof fn === 'function' ) { + this._queue.sort( fn ); + } + }, + + /** + * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。 + * @grammar getFiles( [status1[, status2 ...]] ) => Array + * @method getFiles + * @param {String} [status] [文件状态值](#WebUploader:File:File.Status) + */ + getFiles: function() { + var sts = [].slice.call( arguments, 0 ), + ret = [], + i = 0, + len = this._queue.length, + file; + + for ( ; i < len; i++ ) { + file = this._queue[ i ]; + + if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) { + continue; + } + + ret.push( file ); + } + + return ret; + }, + + /** + * 在队列中删除文件。 + * @grammar removeFile( file ) => Array + * @method removeFile + * @param {File} 文件对象。 + */ + removeFile: function( file ) { + var me = this, + existing = this._map[ file.id ]; + + if ( existing ) { + delete this._map[ file.id ]; + this._delFile(file); + file.destroy(); + this.stats.numOfDeleted++; + + } + }, + + _fileAdded: function( file ) { + var me = this, + existing = this._map[ file.id ]; + + if ( !existing ) { + this._map[ file.id ] = file; + + file.on( 'statuschange', function( cur, pre ) { + me._onFileStatusChange( cur, pre ); + }); + } + + file.setStatus( STATUS.QUEUED ); + }, + + _delFile : function(file){ + for(var i = this._queue.length - 1 ; i >= 0 ; i-- ){ + if(this._queue[i] == file){ + this._queue.splice(i,1); + break; + } + } + }, + + _onFileStatusChange: function( curStatus, preStatus ) { + var stats = this.stats; + + switch ( preStatus ) { + case STATUS.PROGRESS: + stats.numOfProgress--; + break; + + case STATUS.QUEUED: + stats.numOfQueue --; + break; + + case STATUS.ERROR: + stats.numOfUploadFailed--; + break; + + case STATUS.INVALID: + stats.numOfInvalid--; + break; + + case STATUS.INTERRUPT: + stats.numOfInterrupt--; + break; + } + + switch ( curStatus ) { + case STATUS.QUEUED: + stats.numOfQueue++; + break; + + case STATUS.PROGRESS: + stats.numOfProgress++; + break; + + case STATUS.ERROR: + stats.numOfUploadFailed++; + break; + + case STATUS.COMPLETE: + stats.numOfSuccess++; + break; + + case STATUS.CANCELLED: + stats.numOfCancel++; + break; + + + case STATUS.INVALID: + stats.numOfInvalid++; + break; + + case STATUS.INTERRUPT: + stats.numOfInterrupt++; + break; + } + } + + }); + + Mediator.installTo( Queue.prototype ); + + return Queue; + }); + + /** + * @fileOverview 队列 + */ + define('widgets/queue',[ + 'base', + 'uploader', + 'queue', + 'file', + 'lib/file', + 'runtime/client', + 'widgets/widget' + ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) { + + var $ = Base.$, + rExt = /\.\w+$/, + Status = WUFile.Status; + + return Uploader.register({ + name: 'queue', + + init: function( opts ) { + var me = this, + deferred, len, i, item, arr, accept, runtime; + + if ( $.isPlainObject( opts.accept ) ) { + opts.accept = [ opts.accept ]; + } + + // accept中的中生成匹配正则。 + if ( opts.accept ) { + arr = []; + + for ( i = 0, len = opts.accept.length; i < len; i++ ) { + item = opts.accept[ i ].extensions; + item && arr.push( item ); + } + + if ( arr.length ) { + accept = '\\.' + arr.join(',') + .replace( /,/g, '$|\\.' ) + .replace( /\*/g, '.*' ) + '$'; + } + + me.accept = new RegExp( accept, 'i' ); + } + + me.queue = new Queue(); + me.stats = me.queue.stats; + + // 如果当前不是html5运行时,那就算了。 + // 不执行后续操作 + if ( this.request('predict-runtime-type') !== 'html5' ) { + return; + } + + // 创建一个 html5 运行时的 placeholder + // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。 + deferred = Base.Deferred(); + this.placeholder = runtime = new RuntimeClient('Placeholder'); + runtime.connectRuntime({ + runtimeOrder: 'html5' + }, function() { + me._ruid = runtime.getRuid(); + deferred.resolve(); + }); + return deferred.promise(); + }, + + + // 为了支持外部直接添加一个原生File对象。 + _wrapFile: function( file ) { + if ( !(file instanceof WUFile) ) { + + if ( !(file instanceof File) ) { + if ( !this._ruid ) { + throw new Error('Can\'t add external files.'); + } + file = new File( this._ruid, file ); + } + + file = new WUFile( file ); + } + + return file; + }, + + // 判断文件是否可以被加入队列 + acceptFile: function( file ) { + var invalid = !file || !file.size || this.accept && + + // 如果名字中有后缀,才做后缀白名单处理。 + rExt.exec( file.name ) && !this.accept.test( file.name ); + + return !invalid; + }, + + + /** + * @event beforeFileQueued + * @param {File} file File对象 + * @description 当文件被加入队列之前触发。如果此事件handler的返回值为`false`,则此文件不会被添加进入队列。 + * @for Uploader + */ + + /** + * @event fileQueued + * @param {File} file File对象 + * @description 当文件被加入队列以后触发。 + * @for Uploader + */ + + _addFile: function( file ) { + var me = this; + + file = me._wrapFile( file ); + + // 不过类型判断允许不允许,先派送 `beforeFileQueued` + if ( !me.owner.trigger( 'beforeFileQueued', file ) ) { + return; + } + + // 类型不匹配,则派送错误事件,并返回。 + if ( !me.acceptFile( file ) ) { + me.owner.trigger( 'error', 'Q_TYPE_DENIED', file ); + return; + } + + me.queue.append( file ); + me.owner.trigger( 'fileQueued', file ); + return file; + }, + + getFile: function( fileId ) { + return this.queue.getFile( fileId ); + }, + + /** + * @event filesQueued + * @param {File} files 数组,内容为原始File(lib/File)对象。 + * @description 当一批文件添加进队列以后触发。 + * @for Uploader + */ + + /** + * @property {Boolean} [auto=false] + * @namespace options + * @for Uploader + * @description 设置为 true 后,不需要手动调用上传,有文件选择即开始上传。 + * + */ + + /** + * @method addFiles + * @grammar addFiles( file ) => undefined + * @grammar addFiles( [file1, file2 ...] ) => undefined + * @param {Array of File or File} [files] Files 对象 数组 + * @description 添加文件到队列 + * @for Uploader + */ + addFile: function( files ) { + var me = this; + + if ( !files.length ) { + files = [ files ]; + } + + files = $.map( files, function( file ) { + return me._addFile( file ); + }); + + if ( files.length ) { + + me.owner.trigger( 'filesQueued', files ); + + if ( me.options.auto ) { + setTimeout(function() { + me.request('start-upload'); + }, 20 ); + } + } + }, + + getStats: function() { + return this.stats; + }, + + /** + * @event fileDequeued + * @param {File} file File对象 + * @description 当文件被移除队列后触发。 + * @for Uploader + */ + + /** + * @method removeFile + * @grammar removeFile( file ) => undefined + * @grammar removeFile( id ) => undefined + * @grammar removeFile( file, true ) => undefined + * @grammar removeFile( id, true ) => undefined + * @param {File|id} file File对象或这File对象的id + * @description 移除某一文件, 默认只会标记文件状态为已取消,如果第二个参数为 `true` 则会从 queue 中移除。 + * @for Uploader + * @example + * + * $li.on('click', '.remove-this', function() { + * uploader.removeFile( file ); + * }) + */ + removeFile: function( file, remove ) { + var me = this; + + file = file.id ? file : me.queue.getFile( file ); + + this.request( 'cancel-file', file ); + + if ( remove ) { + this.queue.removeFile( file ); + } + }, + + /** + * @method getFiles + * @grammar getFiles() => Array + * @grammar getFiles( status1, status2, status... ) => Array + * @description 返回指定状态的文件集合,不传参数将返回所有状态的文件。 + * @for Uploader + * @example + * console.log( uploader.getFiles() ); // => all files + * console.log( uploader.getFiles('error') ) // => all error files. + */ + getFiles: function() { + return this.queue.getFiles.apply( this.queue, arguments ); + }, + + fetchFile: function() { + return this.queue.fetch.apply( this.queue, arguments ); + }, + + /** + * @method retry + * @grammar retry() => undefined + * @grammar retry( file ) => undefined + * @description 重试上传,重试指定文件,或者从出错的文件开始重新上传。 + * @for Uploader + * @example + * function retry() { + * uploader.retry(); + * } + */ + retry: function( file, noForceStart ) { + var me = this, + files, i, len; + + if ( file ) { + file = file.id ? file : me.queue.getFile( file ); + file.setStatus( Status.QUEUED ); + noForceStart || me.request('start-upload'); + return; + } + + files = me.queue.getFiles( Status.ERROR ); + i = 0; + len = files.length; + + for ( ; i < len; i++ ) { + file = files[ i ]; + file.setStatus( Status.QUEUED ); + } + + me.request('start-upload'); + }, + + /** + * @method sort + * @grammar sort( fn ) => undefined + * @description 排序队列中的文件,在上传之前调整可以控制上传顺序。 + * @for Uploader + */ + sortFiles: function() { + return this.queue.sort.apply( this.queue, arguments ); + }, + + /** + * @event reset + * @description 当 uploader 被重置的时候触发。 + * @for Uploader + */ + + /** + * @method reset + * @grammar reset() => undefined + * @description 重置uploader。目前只重置了队列。 + * @for Uploader + * @example + * uploader.reset(); + */ + reset: function() { + this.owner.trigger('reset'); + this.queue = new Queue(); + this.stats = this.queue.stats; + }, + + destroy: function() { + this.reset(); + this.placeholder && this.placeholder.destroy(); + } + }); + + }); + /** + * @fileOverview 添加获取Runtime相关信息的方法。 + */ + define('widgets/runtime',[ + 'uploader', + 'runtime/runtime', + 'widgets/widget' + ], function( Uploader, Runtime ) { + + Uploader.support = function() { + return Runtime.hasRuntime.apply( Runtime, arguments ); + }; + + /** + * @property {Object} [runtimeOrder=html5,flash] + * @namespace options + * @for Uploader + * @description 指定运行时启动顺序。默认会先尝试 html5 是否支持,如果支持则使用 html5, 否则使用 flash. + * + * 可以将此值设置成 `flash`,来强制使用 flash 运行时。 + */ + + return Uploader.register({ + name: 'runtime', + + init: function() { + if ( !this.predictRuntimeType() ) { + throw Error('Runtime Error'); + } + }, + + /** + * 预测Uploader将采用哪个`Runtime` + * @grammar predictRuntimeType() => String + * @method predictRuntimeType + * @for Uploader + */ + predictRuntimeType: function() { + var orders = this.options.runtimeOrder || Runtime.orders, + type = this.type, + i, len; + + if ( !type ) { + orders = orders.split( /\s*,\s*/g ); + + for ( i = 0, len = orders.length; i < len; i++ ) { + if ( Runtime.hasRuntime( orders[ i ] ) ) { + this.type = type = orders[ i ]; + break; + } + } + } + + return type; + } + }); + }); + /** + * @fileOverview Transport + */ + define('lib/transport',[ + 'base', + 'runtime/client', + 'mediator' + ], function( Base, RuntimeClient, Mediator ) { + + var $ = Base.$; + + function Transport( opts ) { + var me = this; + + opts = me.options = $.extend( true, {}, Transport.options, opts || {} ); + RuntimeClient.call( this, 'Transport' ); + + this._block = null; + this._blob = null; + this._formData = opts.formData || {}; + this._headers = opts.headers || {}; + + this.on( 'progress', this._timeout ); + this.on( 'load error', function() { + me.trigger( 'progress', 1 ); + clearTimeout( me._timer ); + }); + } + + Transport.options = { + server: '', + method: 'POST', + + // 跨域时,是否允许携带cookie, 只有html5 runtime才有效 + withCredentials: false, + fileVal: 'file', + timeout: 2 * 60 * 1000, // 2分钟 + formData: {}, + headers: {}, + sendAsBinary: false, + + customUploadResponse: null, + }; + + $.extend( Transport.prototype, { + + // 添加Blob, 只能添加一次,最后一次有效。 + appendBlob: function( key, blob, filename, block) { + var me = this, + opts = me.options; + + if ( me.getRuid() ) { + me.disconnectRuntime(); + } + + // 连接到blob归属的同一个runtime. + me.connectRuntime( blob.ruid, function() { + me.exec('init'); + }); + + me._block = block; + me._blob = blob; + opts.fileVal = key || opts.fileVal; + opts.filename = filename || opts.filename; + }, + + // 添加其他字段 + append: function( key, value ) { + if ( typeof key === 'object' ) { + $.extend( this._formData, key ); + } else { + this._formData[ key ] = value; + } + }, + + setRequestHeader: function( key, value ) { + if ( typeof key === 'object' ) { + $.extend( this._headers, key ); + } else { + this._headers[ key ] = value; + } + }, + + send: function( method ) { + var me = this, + opts = me.options; + if( opts.customUpload ){ + opts.customUpload(me._block, { + onProgress: function (file, percentage) { + me.trigger('progress', percentage); + }, + onSuccess: function (file, res) { + me.customUploadResponse = res; + me.trigger('load'); + }, + onError: function (file, error) { + me.trigger('error', error, true); + } + }); + }else{ + this.exec( 'send', method ); + this._timeout(); + } + }, + + abort: function() { + clearTimeout( this._timer ); + return this.exec('abort'); + }, + + destroy: function() { + this.trigger('destroy'); + this.off(); + this.exec('destroy'); + this.disconnectRuntime(); + }, + + getResponseHeaders: function() { + return this.exec('getResponseHeaders'); + }, + + getResponse: function() { + return this.exec('getResponse'); + }, + + getResponseAsJson: function() { + return this.exec('getResponseAsJson'); + }, + + getStatus: function() { + return this.exec('getStatus'); + }, + + _timeout: function() { + var me = this, + duration = me.options.timeout; + + if ( !duration ) { + return; + } + + clearTimeout( me._timer ); + me._timer = setTimeout(function() { + me.abort(); + me.trigger( 'error', 'timeout' ); + }, duration ); + } + + }); + + // 让Transport具备事件功能。 + Mediator.installTo( Transport.prototype ); + + return Transport; + }); + + /** + * @fileOverview 负责文件上传相关。 + */ + define('widgets/upload',[ + 'base', + 'uploader', + 'file', + 'lib/transport', + 'widgets/widget' + ], function( Base, Uploader, WUFile, Transport ) { + + var $ = Base.$, + isPromise = Base.isPromise, + Status = WUFile.Status; + + // 添加默认配置项 + $.extend( Uploader.options, { + + + /** + * @property {Boolean} [prepareNextFile=false] + * @namespace options + * @for Uploader + * @description 是否允许在文件传输时提前把下一个文件准备好。 + * 某些文件的准备工作比较耗时,比如图片压缩,md5序列化。 + * 如果能提前在当前文件传输期处理,可以节省总体耗时。 + */ + prepareNextFile: false, + + /** + * @property {Boolean} [chunked=false] + * @namespace options + * @for Uploader + * @description 是否要分片处理大文件上传。 + */ + chunked: false, + + /** + * @property {Boolean} [chunkSize=5242880] + * @namespace options + * @for Uploader + * @description 如果要分片,分多大一片? 默认大小为5M. + */ + chunkSize: 5 * 1024 * 1024, + + /** + * @property {Boolean} [chunkRetry=2] + * @namespace options + * @for Uploader + * @description 如果某个分片由于网络问题出错,允许自动重传多少次? + */ + chunkRetry: 2, + + /** + * @property {Number} [chunkRetryDelay=1000] + * @namespace options + * @for Uploader + * @description 开启重试后,设置重试延时时间, 单位毫秒。默认1000毫秒,即1秒. + */ + chunkRetryDelay: 1000, + + /** + * @property {Boolean} [threads=3] + * @namespace options + * @for Uploader + * @description 上传并发数。允许同时最大上传进程数。 + */ + threads: 1, + + + /** + * @property {Object} [formData={}] + * @namespace options + * @for Uploader + * @description 文件上传请求的参数表,每次发送都会发送此对象中的参数。 + */ + formData: {} + + /** + * @property {Object} [fileVal='file'] + * @namespace options + * @for Uploader + * @description 设置文件上传域的name。 + */ + + /** + * @property {Object} [method=POST] + * @namespace options + * @for Uploader + * @description 文件上传方式,`POST` 或者 `GET`。 + */ + + /** + * @property {Object} [sendAsBinary=false] + * @namespace options + * @for Uploader + * @description 是否已二进制的流的方式发送文件,这样整个上传内容`php://input`都为文件内容, + * 其他参数在$_GET数组中。 + */ + }); + + // 负责将文件切片。 + function CuteFile( file, chunkSize ) { + var pending = [], + blob = file.source, + total = blob.size, + chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1, + start = 0, + index = 0, + len, api; + + api = { + file: file, + + has: function() { + return !!pending.length; + }, + + shift: function() { + return pending.shift(); + }, + + unshift: function( block ) { + pending.unshift( block ); + } + }; + + while ( index < chunks ) { + len = Math.min( chunkSize, total - start ); + + pending.push({ + file: file, + start: start, + end: chunkSize ? (start + len) : total, + total: total, + chunks: chunks, + chunk: index++, + cuted: api + }); + start += len; + } + + file.blocks = pending.concat(); + file.remaning = pending.length; + + return api; + } + + Uploader.register({ + name: 'upload', + + init: function() { + var owner = this.owner, + me = this; + + this.runing = false; + this.progress = false; + + owner + .on( 'startUpload', function() { + me.progress = true; + }) + .on( 'uploadFinished', function() { + me.progress = false; + }); + + // 记录当前正在传的数据,跟threads相关 + this.pool = []; + + // 缓存分好片的文件。 + this.stack = []; + + // 缓存即将上传的文件。 + this.pending = []; + + // 跟踪还有多少分片在上传中但是没有完成上传。 + this.remaning = 0; + this.__tick = Base.bindFn( this._tick, this ); + + // 销毁上传相关的属性。 + owner.on( 'uploadComplete', function( file ) { + + // 把其他块取消了。 + file.blocks && $.each( file.blocks, function( _, v ) { + v.transport && (v.transport.abort(), v.transport.destroy()); + delete v.transport; + }); + + delete file.blocks; + delete file.remaning; + }); + }, + + reset: function() { + this.request( 'stop-upload', true ); + this.runing = false; + this.pool = []; + this.stack = []; + this.pending = []; + this.remaning = 0; + this._trigged = false; + this._promise = null; + }, + + /** + * @event startUpload + * @description 当开始上传流程时触发。 + * @for Uploader + */ + + /** + * 开始上传。此方法可以从初始状态调用开始上传流程,也可以从暂停状态调用,继续上传流程。 + * + * 可以指定开始某一个文件。 + * @grammar upload() => undefined + * @grammar upload( file | fileId) => undefined + * @method upload + * @for Uploader + */ + startUpload: function(file) { + var me = this; + + // 移出invalid的文件 + $.each( me.request( 'get-files', Status.INVALID ), function() { + me.request( 'remove-file', this ); + }); + + // 如果指定了开始某个文件,则只开始指定的文件。 + if ( file ) { + file = file.id ? file : me.request( 'get-file', file ); + + if (file.getStatus() === Status.INTERRUPT) { + file.setStatus( Status.QUEUED ); + + $.each( me.pool, function( _, v ) { + + // 之前暂停过。 + if (v.file !== file) { + return; + } + + v.transport && v.transport.send(); + file.setStatus( Status.PROGRESS ); + }); + + + } else if (file.getStatus() !== Status.PROGRESS) { + file.setStatus( Status.QUEUED ); + } + } else { + $.each( me.request( 'get-files', [ Status.INITED ] ), function() { + this.setStatus( Status.QUEUED ); + }); + } + + if ( me.runing ) { + me.owner.trigger('startUpload', file);// 开始上传或暂停恢复的,trigger event + return Base.nextTick( me.__tick ); + } + + me.runing = true; + var files = []; + + // 如果有暂停的,则续传 + file || $.each( me.pool, function( _, v ) { + var file = v.file; + + if ( file.getStatus() === Status.INTERRUPT ) { + me._trigged = false; + files.push(file); + + if (v.waiting) { + return; + } + + // 文件 prepare 完后,如果暂停了,这个时候只会把文件插入 pool, 而不会创建 tranport, + v.transport ? v.transport.send() : me._doSend(v); + } + }); + + $.each(files, function() { + this.setStatus( Status.PROGRESS ); + }); + + file || $.each( me.request( 'get-files', + Status.INTERRUPT ), function() { + this.setStatus( Status.PROGRESS ); + }); + + me._trigged = false; + Base.nextTick( me.__tick ); + me.owner.trigger('startUpload'); + }, + + /** + * @event stopUpload + * @description 当开始上传流程暂停时触发。 + * @for Uploader + */ + + /** + * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。 + * + * 如果第一个参数是文件,则只暂停指定文件。 + * @grammar stop() => undefined + * @grammar stop( true ) => undefined + * @grammar stop( file ) => undefined + * @method stop + * @for Uploader + */ + stopUpload: function( file, interrupt ) { + var me = this; + + if (file === true) { + interrupt = file; + file = null; + } + + if ( me.runing === false ) { + return; + } + + // 如果只是暂停某个文件。 + if ( file ) { + file = file.id ? file : me.request( 'get-file', file ); + + if ( file.getStatus() !== Status.PROGRESS && + file.getStatus() !== Status.QUEUED ) { + return; + } + + file.setStatus( Status.INTERRUPT ); + + + $.each( me.pool, function( _, v ) { + + // 只 abort 指定的文件,每一个分片。 + if (v.file === file) { + v.transport && v.transport.abort(); + + if (interrupt) { + me._putback(v); + me._popBlock(v); + } + } + }); + + me.owner.trigger('stopUpload', file);// 暂停,trigger event + + return Base.nextTick( me.__tick ); + } + + me.runing = false; + + // 正在准备中的文件。 + if (this._promise && this._promise.file) { + this._promise.file.setStatus( Status.INTERRUPT ); + } + + interrupt && $.each( me.pool, function( _, v ) { + v.transport && v.transport.abort(); + v.file.setStatus( Status.INTERRUPT ); + }); + + me.owner.trigger('stopUpload'); + }, + + /** + * @method cancelFile + * @grammar cancelFile( file ) => undefined + * @grammar cancelFile( id ) => undefined + * @param {File|id} file File对象或这File对象的id + * @description 标记文件状态为已取消, 同时将中断文件传输。 + * @for Uploader + * @example + * + * $li.on('click', '.remove-this', function() { + * uploader.cancelFile( file ); + * }) + */ + cancelFile: function( file ) { + file = file.id ? file : this.request( 'get-file', file ); + + // 如果正在上传。 + file.blocks && $.each( file.blocks, function( _, v ) { + var _tr = v.transport; + + if ( _tr ) { + _tr.abort(); + _tr.destroy(); + delete v.transport; + } + }); + + file.setStatus( Status.CANCELLED ); + this.owner.trigger( 'fileDequeued', file ); + }, + + /** + * 判断`Uploader`是否正在上传中。 + * @grammar isInProgress() => Boolean + * @method isInProgress + * @for Uploader + */ + isInProgress: function() { + return !!this.progress; + }, + + _getStats: function() { + return this.request('get-stats'); + }, + + /** + * 跳过一个文件上传,直接标记指定文件为已上传状态。 + * @grammar skipFile( file ) => undefined + * @method skipFile + * @for Uploader + */ + skipFile: function( file, status ) { + file = file.id ? file : this.request( 'get-file', file ); + + file.setStatus( status || Status.COMPLETE ); + file.skipped = true; + + // 如果正在上传。 + file.blocks && $.each( file.blocks, function( _, v ) { + var _tr = v.transport; + + if ( _tr ) { + _tr.abort(); + _tr.destroy(); + delete v.transport; + } + }); + + this.owner.trigger( 'uploadSkip', file ); + }, + + /** + * @event uploadFinished + * @description 当所有文件上传结束时触发。 + * @for Uploader + */ + _tick: function() { + var me = this, + opts = me.options, + fn, val; + + // 上一个promise还没有结束,则等待完成后再执行。 + if ( me._promise ) { + return me._promise.always( me.__tick ); + } + + // 还有位置,且还有文件要处理的话。 + if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) { + me._trigged = false; + + fn = function( val ) { + me._promise = null; + + // 有可能是reject过来的,所以要检测val的类型。 + val && val.file && me._startSend( val ); + Base.nextTick( me.__tick ); + }; + + me._promise = isPromise( val ) ? val.always( fn ) : fn( val ); + + // 没有要上传的了,且没有正在传输的了。 + } else if ( !me.remaning && !me._getStats().numOfQueue && + !me._getStats().numOfInterrupt ) { + me.runing = false; + + me._trigged || Base.nextTick(function() { + me.owner.trigger('uploadFinished'); + }); + me._trigged = true; + } + }, + + _putback: function(block) { + var idx; + + block.cuted.unshift(block); + idx = this.stack.indexOf(block.cuted); + + if (!~idx) { + // 如果不在里面,说明移除过,需要把计数还原回去。 + this.remaning++; + block.file.remaning++; + this.stack.unshift(block.cuted); + } + }, + + _getStack: function() { + var i = 0, + act; + + while ( (act = this.stack[ i++ ]) ) { + if ( act.has() && act.file.getStatus() === Status.PROGRESS ) { + return act; + } else if (!act.has() || + act.file.getStatus() !== Status.PROGRESS && + act.file.getStatus() !== Status.INTERRUPT ) { + + // 把已经处理完了的,或者,状态为非 progress(上传中)、 + // interupt(暂停中) 的移除。 + this.stack.splice( --i, 1 ); + } + } + + return null; + }, + + _nextBlock: function() { + var me = this, + opts = me.options, + act, next, done, preparing; + + // 如果当前文件还有没有需要传输的,则直接返回剩下的。 + if ( (act = this._getStack()) ) { + + // 是否提前准备下一个文件 + if ( opts.prepareNextFile && !me.pending.length ) { + me._prepareNextFile(); + } + + return act.shift(); + + // 否则,如果正在运行,则准备下一个文件,并等待完成后返回下个分片。 + } else if ( me.runing ) { + + // 如果缓存中有,则直接在缓存中取,没有则去queue中取。 + if ( !me.pending.length && me._getStats().numOfQueue ) { + me._prepareNextFile(); + } + + next = me.pending.shift(); + done = function( file ) { + if ( !file ) { + return null; + } + + if (opts.customUpload) { + act = CuteFile(file, 0); + } else { + act = CuteFile(file, opts.chunked ? opts.chunkSize : 0); + } + me.stack.push(act); + return act.shift(); + }; + + // 文件可能还在prepare中,也有可能已经完全准备好了。 + if ( isPromise( next) ) { + preparing = next.file; + next = next[ next.pipe ? 'pipe' : 'then' ]( done ); + next.file = preparing; + return next; + } + + return done( next ); + } + }, + + + /** + * @event uploadStart + * @param {File} file File对象 + * @description 某个文件开始上传前触发,一个文件只会触发一次。 + * @for Uploader + */ + _prepareNextFile: function() { + var me = this, + file = me.request('fetch-file'), + pending = me.pending, + promise; + + if ( file ) { + promise = me.request( 'before-send-file', file, function() { + + // 有可能文件被skip掉了。文件被skip掉后,状态坑定不是Queued. + if ( file.getStatus() === Status.PROGRESS || + file.getStatus() === Status.INTERRUPT ) { + return file; + } + + return me._finishFile( file ); + }); + + me.owner.trigger( 'uploadStart', file ); + file.setStatus( Status.PROGRESS ); + + promise.file = file; + + // 如果还在pending中,则替换成文件本身。 + promise.done(function() { + var idx = $.inArray( promise, pending ); + + ~idx && pending.splice( idx, 1, file ); + }); + + // befeore-send-file的钩子就有错误发生。 + promise.fail(function( reason ) { + file.setStatus( Status.ERROR, reason ); + me.owner.trigger( 'uploadError', file, reason ); + me.owner.trigger( 'uploadComplete', file ); + }); + + pending.push( promise ); + } + }, + + // 让出位置了,可以让其他分片开始上传 + _popBlock: function( block ) { + var idx = $.inArray( block, this.pool ); + + this.pool.splice( idx, 1 ); + block.file.remaning--; + this.remaning--; + }, + + // 开始上传,可以被掉过。如果promise被reject了,则表示跳过此分片。 + _startSend: function( block ) { + var me = this, + file = block.file, + promise; + + // 有可能在 before-send-file 的 promise 期间改变了文件状态。 + // 如:暂停,取消 + // 我们不能中断 promise, 但是可以在 promise 完后,不做上传操作。 + if ( file.getStatus() !== Status.PROGRESS ) { + + // 如果是中断,则还需要放回去。 + if (file.getStatus() === Status.INTERRUPT) { + me._putback(block); + } + + return; + } + + me.pool.push( block ); + me.remaning++; + + // 如果没有分片,则直接使用原始的。 + // 不会丢失content-type信息。 + block.blob = block.chunks === 1 ? file.source : + file.source.slice( block.start, block.end ); + + // hook, 每个分片发送之前可能要做些异步的事情。 + block.waiting = promise = me.request( 'before-send', block, function() { + delete block.waiting; + + // 有可能文件已经上传出错了,所以不需要再传输了。 + if ( file.getStatus() === Status.PROGRESS ) { + me._doSend( block ); + } else if (block.file.getStatus() !== Status.INTERRUPT) { + me._popBlock(block); + } + + Base.nextTick(me.__tick); + }); + + // 如果为fail了,则跳过此分片。 + promise.fail(function() { + delete block.waiting; + + if ( file.remaning === 1 ) { + me._finishFile( file ).always(function() { + block.percentage = 1; + me._popBlock( block ); + me.owner.trigger( 'uploadComplete', file ); + Base.nextTick( me.__tick ); + }); + } else { + block.percentage = 1; + me.updateFileProgress( file ); + me._popBlock( block ); + Base.nextTick( me.__tick ); + } + }); + }, + + + /** + * @event uploadBeforeSend + * @param {Object} object + * @param {Object} data 默认的上传参数,可以扩展此对象来控制上传参数。 + * @param {Object} headers 可以扩展此对象来控制上传头部。 + * @description 当某个文件的分块在发送前触发,主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次。 + * @for Uploader + */ + + /** + * @event uploadAccept + * @param {Object} object + * @param {Object} ret 服务端的返回数据,json格式,如果服务端不是json格式,从ret._raw中取数据,自行解析。 + * @description 当某个文件上传到服务端响应后,会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。 + * @for Uploader + */ + + /** + * @event uploadProgress + * @param {File} file File对象 + * @param {Number} percentage 上传进度 + * @description 上传过程中触发,携带上传进度。 + * @for Uploader + */ + + + /** + * @event uploadError + * @param {File} file File对象 + * @param {String} reason 出错的code + * @description 当文件上传出错时触发。 + * @for Uploader + */ + + /** + * @event uploadSuccess + * @param {File} file File对象 + * @param {Object} response 服务端返回的数据 + * @description 当文件上传成功时触发。 + * @for Uploader + */ + + /** + * @event uploadComplete + * @param {File} [file] File对象 + * @description 不管成功或者失败,文件上传完成时触发。 + * @for Uploader + */ + + // 做上传操作。 + _doSend: function( block ) { + var me = this, + owner = me.owner, + opts = $.extend({}, me.options, block.options), + file = block.file, + tr = new Transport( opts ), + data = $.extend({}, opts.formData ), + headers = $.extend({}, opts.headers ), + requestAccept, ret; + + block.transport = tr; + + tr.on( 'destroy', function() { + delete block.transport; + me._popBlock( block ); + Base.nextTick( me.__tick ); + }); + + // 广播上传进度。以文件为单位。 + tr.on( 'progress', function( percentage ) { + block.percentage = percentage; + me.updateFileProgress( file ); + }); + + // 用来询问,是否返回的结果是有错误的。 + requestAccept = function( reject ) { + var fn; + + if( opts.customUpload ){ + ret = tr.customUploadResponse; + }else{ + ret = tr.getResponseAsJson() || {}; + ret._raw = tr.getResponse(); + ret._headers = tr.getResponseHeaders(); + } + block.response = ret; + fn = function( value ) { + reject = value; + }; + + // 服务端响应了,不代表成功了,询问是否响应正确。 + if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) { + reject = reject || 'server'; + } + + return reject; + }; + + // 尝试重试,然后广播文件上传出错。 + tr.on( 'error', function( type, flag ) { + // 在 runtime/html5/transport.js 上为 type 加上了状态码,形式:type|status|text(如:http|403|Forbidden) + // 这里把状态码解释出来,并还原后面代码所依赖的 type 变量 + var typeArr = type.split( '|' ), status, statusText; + type = typeArr[0]; + status = parseFloat( typeArr[1] ), + statusText = typeArr[2]; + + block.retried = block.retried || 0; + + // 自动重试 + if ( block.chunks > 1 && ~'http,abort,server'.indexOf( type.replace( /-.*/, '' ) ) && + block.retried < opts.chunkRetry ) { + + block.retried++; + + me.retryTimer = setTimeout(function() { + tr.send(); + }, opts.chunkRetryDelay || 1000); + + } else { + + // http status 500 ~ 600 + if ( !flag && type === 'server' ) { + type = requestAccept( type ); + } + + file.setStatus( Status.ERROR, type ); + owner.trigger( 'uploadError', file, type, status, statusText ); + owner.trigger( 'uploadComplete', file ); + } + }); + + // 上传成功 + tr.on( 'load', function() { + var reason; + + // 如果非预期,转向上传出错。 + if ( (reason = requestAccept()) ) { + tr.trigger( 'error', reason, true ); + return; + } + + // 全部上传完成。 + if ( file.remaning === 1 ) { + me._finishFile( file, ret ); + } else { + tr.destroy(); + } + }); + + // 配置默认的上传字段。 + data = $.extend( data, { + id: file.id, + name: file.name, + type: file.type, + lastModifiedDate: file.lastModifiedDate, + size: file.size + }); + + block.chunks > 1 && $.extend( data, { + chunks: block.chunks, + chunk: block.chunk + }); + + // 在发送之间可以添加字段什么的。。。 + // 如果默认的字段不够使用,可以通过监听此事件来扩展 + owner.trigger( 'uploadBeforeSend', block, data, headers ); + + // 开始发送。 + tr.appendBlob( opts.fileVal, block.blob, file.name, block); + tr.append( data ); + tr.setRequestHeader( headers ); + tr.send(); + }, + + // 完成上传。 + _finishFile: function( file, ret, hds ) { + var owner = this.owner; + + return owner + .request( 'after-send-file', arguments, function() { + file.setStatus( Status.COMPLETE ); + owner.trigger( 'uploadSuccess', file, ret, hds ); + }) + .fail(function( reason ) { + + // 如果外部已经标记为invalid什么的,不再改状态。 + if ( file.getStatus() === Status.PROGRESS ) { + file.setStatus( Status.ERROR, reason ); + } + + owner.trigger( 'uploadError', file, reason ); + }) + .always(function() { + owner.trigger( 'uploadComplete', file ); + }); + }, + + updateFileProgress: function(file) { + var totalPercent = 0, + uploaded = 0; + + if (!file.blocks) { + return; + } + + $.each( file.blocks, function( _, v ) { + uploaded += (v.percentage || 0) * (v.end - v.start); + }); + + totalPercent = uploaded / file.size; + this.owner.trigger( 'uploadProgress', file, totalPercent || 0 ); + }, + + destroy: function() { + clearTimeout(this.retryTimer); + } + + }); + }); + + /** + * @fileOverview 各种验证,包括文件总大小是否超出、单文件是否超出和文件是否重复。 + */ + + define('widgets/validator',[ + 'base', + 'uploader', + 'file', + 'widgets/widget' + ], function( Base, Uploader, WUFile ) { + + var $ = Base.$, + validators = {}, + api; + + /** + * @event error + * @param {String} type 错误类型。 + * @description 当validate不通过时,会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误,目前有以下错误会在特定的情况下派送错来。 + * + * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。 + * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。 + * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。 + * @for Uploader + */ + + // 暴露给外面的api + api = { + + // 添加验证器 + addValidator: function( type, cb ) { + validators[ type ] = cb; + }, + + // 移除验证器 + removeValidator: function( type ) { + delete validators[ type ]; + } + }; + + // 在Uploader初始化的时候启动Validators的初始化 + Uploader.register({ + name: 'validator', + + init: function() { + var me = this; + Base.nextTick(function() { + $.each( validators, function() { + this.call( me.owner ); + }); + }); + } + }); + + /** + * @property {int} [fileNumLimit=undefined] + * @namespace options + * @for Uploader + * @description 验证文件总数量, 超出则不允许加入队列。 + */ + api.addValidator( 'fileNumLimit', function() { + var uploader = this, + opts = uploader.options, + count = 0, + max = parseInt( opts.fileNumLimit, 10 ), + flag = true; + + if ( !max ) { + return; + } + + uploader.on( 'beforeFileQueued', function( file ) { + // 增加beforeFileQueuedCheckfileNumLimit验证,主要为了再次加载时(已存在历史文件)验证数量是否超过设置项 + if (!this.trigger('beforeFileQueuedCheckfileNumLimit', file,count)) { + return false; + } + if ( count >= max && flag ) { + flag = false; + this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file ); + setTimeout(function() { + flag = true; + }, 1 ); + } + + return count >= max ? false : true; + }); + + uploader.on( 'fileQueued', function() { + count++; + }); + + uploader.on( 'fileDequeued', function() { + count--; + }); + + uploader.on( 'reset', function() { + count = 0; + }); + }); + + + /** + * @property {int} [fileSizeLimit=undefined] + * @namespace options + * @for Uploader + * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。 + */ + api.addValidator( 'fileSizeLimit', function() { + var uploader = this, + opts = uploader.options, + count = 0, + max = parseInt( opts.fileSizeLimit, 10 ), + flag = true; + + if ( !max ) { + return; + } + + uploader.on( 'beforeFileQueued', function( file ) { + var invalid = count + file.size > max; + + if ( invalid && flag ) { + flag = false; + this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file ); + setTimeout(function() { + flag = true; + }, 1 ); + } + + return invalid ? false : true; + }); + + uploader.on( 'fileQueued', function( file ) { + count += file.size; + }); + + uploader.on( 'fileDequeued', function( file ) { + count -= file.size; + }); + + uploader.on( 'reset', function() { + count = 0; + }); + }); + + /** + * @property {int} [fileSingleSizeLimit=undefined] + * @namespace options + * @for Uploader + * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。 + */ + api.addValidator( 'fileSingleSizeLimit', function() { + var uploader = this, + opts = uploader.options, + max = opts.fileSingleSizeLimit; + + if ( !max ) { + return; + } + + uploader.on( 'beforeFileQueued', function( file ) { + + if ( file.size > max ) { + file.setStatus( WUFile.Status.INVALID, 'exceed_size' ); + this.trigger( 'error', 'F_EXCEED_SIZE', max, file ); + return false; + } + + }); + + }); + + /** + * @property {Boolean} [duplicate=undefined] + * @namespace options + * @for Uploader + * @description 去重, 根据文件名字、文件大小和最后修改时间来生成hash Key. + */ + api.addValidator( 'duplicate', function() { + var uploader = this, + opts = uploader.options, + mapping = {}; + + if ( opts.duplicate ) { + return; + } + + function hashString( str ) { + var hash = 0, + i = 0, + len = str.length, + _char; + + for ( ; i < len; i++ ) { + _char = str.charCodeAt( i ); + hash = _char + (hash << 6) + (hash << 16) - hash; + } + + return hash; + } + + uploader.on( 'beforeFileQueued', function( file ) { + var hash = file.__hash || (file.__hash = hashString( file.name + + file.size + file.lastModifiedDate )); + + // 已经重复了 + if ( mapping[ hash ] ) { + this.trigger( 'error', 'F_DUPLICATE', file ); + return false; + } + }); + + uploader.on( 'fileQueued', function( file ) { + var hash = file.__hash; + + hash && (mapping[ hash ] = true); + }); + + uploader.on( 'fileDequeued', function( file ) { + var hash = file.__hash; + + hash && (delete mapping[ hash ]); + }); + + uploader.on( 'reset', function() { + mapping = {}; + }); + }); + + return api; + }); + + /** + * @fileOverview Md5 + */ + define('lib/md5',[ + 'runtime/client', + 'mediator' + ], function( RuntimeClient, Mediator ) { + + function Md5() { + RuntimeClient.call( this, 'Md5' ); + } + + // 让 Md5 具备事件功能。 + Mediator.installTo( Md5.prototype ); + + Md5.prototype.loadFromBlob = function( blob ) { + var me = this; + + if ( me.getRuid() ) { + me.disconnectRuntime(); + } + + // 连接到blob归属的同一个runtime. + me.connectRuntime( blob.ruid, function() { + me.exec('init'); + me.exec( 'loadFromBlob', blob ); + }); + }; + + Md5.prototype.getResult = function() { + return this.exec('getResult'); + }; + + return Md5; + }); + /** + * @fileOverview 图片操作, 负责预览图片和上传前压缩图片 + */ + define('widgets/md5',[ + 'base', + 'uploader', + 'lib/md5', + 'lib/blob', + 'widgets/widget' + ], function( Base, Uploader, Md5, Blob ) { + + return Uploader.register({ + name: 'md5', + + + /** + * 计算文件 md5 值,返回一个 promise 对象,可以监听 progress 进度。 + * + * + * @method md5File + * @grammar md5File( file[, start[, end]] ) => promise + * @for Uploader + * @example + * + * uploader.on( 'fileQueued', function( file ) { + * var $li = ...; + * + * uploader.md5File( file ) + * + * // 及时显示进度 + * .progress(function(percentage) { + * console.log('Percentage:', percentage); + * }) + * + * // 完成 + * .then(function(val) { + * console.log('md5 result:', val); + * }); + * + * }); + */ + md5File: function( file, start, end ) { + var md5 = new Md5(), + deferred = Base.Deferred(), + blob = (file instanceof Blob) ? file : + this.request( 'get-file', file ).source; + + md5.on( 'progress load', function( e ) { + e = e || {}; + deferred.notify( e.total ? e.loaded / e.total : 1 ); + }); + + md5.on( 'complete', function() { + deferred.resolve( md5.getResult() ); + }); + + md5.on( 'error', function( reason ) { + deferred.reject( reason ); + }); + + if ( arguments.length > 1 ) { + start = start || 0; + end = end || 0; + start < 0 && (start = blob.size + start); + end < 0 && (end = blob.size + end); + end = Math.min( end, blob.size ); + blob = blob.slice( start, end ); + } + + md5.loadFromBlob( blob ); + + return deferred.promise(); + } + }); + }); + /** + * @fileOverview Runtime管理器,负责Runtime的选择, 连接 + */ + define('runtime/compbase',[],function() { + + function CompBase( owner, runtime ) { + + this.owner = owner; + this.options = owner.options; + + this.getRuntime = function() { + return runtime; + }; + + this.getRuid = function() { + return runtime.uid; + }; + + this.trigger = function() { + return owner.trigger.apply( owner, arguments ); + }; + } + + return CompBase; + }); + /** + * @fileOverview Html5Runtime + */ + define('runtime/html5/runtime',[ + 'base', + 'runtime/runtime', + 'runtime/compbase' + ], function( Base, Runtime, CompBase ) { + + var type = 'html5', + components = {}; + + function Html5Runtime() { + var pool = {}, + me = this, + destroy = this.destroy; + + Runtime.apply( me, arguments ); + me.type = type; + + + // 这个方法的调用者,实际上是RuntimeClient + me.exec = function( comp, fn/*, args...*/) { + var client = this, + uid = client.uid, + args = Base.slice( arguments, 2 ), + instance; + + if ( components[ comp ] ) { + instance = pool[ uid ] = pool[ uid ] || + new components[ comp ]( client, me ); + + if ( instance[ fn ] ) { + return instance[ fn ].apply( instance, args ); + } + } + }; + + me.destroy = function() { + // @todo 删除池子中的所有实例 + return destroy && destroy.apply( this, arguments ); + }; + } + + Base.inherits( Runtime, { + constructor: Html5Runtime, + + // 不需要连接其他程序,直接执行callback + init: function() { + var me = this; + setTimeout(function() { + me.trigger('ready'); + }, 1 ); + } + + }); + + // 注册Components + Html5Runtime.register = function( name, component ) { + var klass = components[ name ] = Base.inherits( CompBase, component ); + return klass; + }; + + // 注册html5运行时。 + // 只有在支持的前提下注册。 + if ( window.Blob && window.FileReader && window.DataView ) { + Runtime.addRuntime( type, Html5Runtime ); + } + + return Html5Runtime; + }); + /** + * @fileOverview Blob Html实现 + */ + define('runtime/html5/blob',[ + 'runtime/html5/runtime', + 'lib/blob' + ], function( Html5Runtime, Blob ) { + + return Html5Runtime.register( 'Blob', { + slice: function( start, end ) { + var blob = this.owner.source, + slice = blob.slice || blob.webkitSlice || blob.mozSlice; + + blob = slice.call( blob, start, end ); + + return new Blob( this.getRuid(), blob ); + } + }); + }); + /** + * @fileOverview FilePaste + */ + define('runtime/html5/dnd',[ + 'base', + 'runtime/html5/runtime', + 'lib/file' + ], function( Base, Html5Runtime, File ) { + + var $ = Base.$, + prefix = 'webuploader-dnd-'; + + return Html5Runtime.register( 'DragAndDrop', { + init: function() { + var elem = this.elem = this.options.container; + + this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this ); + this.dragOverHandler = Base.bindFn( this._dragOverHandler, this ); + this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this ); + this.dropHandler = Base.bindFn( this._dropHandler, this ); + this.dndOver = false; + + elem.on( 'dragenter', this.dragEnterHandler ); + elem.on( 'dragover', this.dragOverHandler ); + elem.on( 'dragleave', this.dragLeaveHandler ); + elem.on( 'drop', this.dropHandler ); + + if ( this.options.disableGlobalDnd ) { + $( document ).on( 'dragover', this.dragOverHandler ); + $( document ).on( 'drop', this.dropHandler ); + } + }, + + _dragEnterHandler: function( e ) { + var me = this, + denied = me._denied || false, + items; + + e = e.originalEvent || e; + + if ( !me.dndOver ) { + me.dndOver = true; + + // 注意只有 chrome 支持。 + items = e.dataTransfer.items; + + if ( items && items.length ) { + me._denied = denied = !me.trigger( 'accept', items ); + } + + me.elem.addClass( prefix + 'over' ); + me.elem[ denied ? 'addClass' : + 'removeClass' ]( prefix + 'denied' ); + } + + e.dataTransfer.dropEffect = denied ? 'none' : 'copy'; + + return false; + }, + + _dragOverHandler: function( e ) { + // 只处理框内的。 + var parentElem = this.elem.parent().get( 0 ); + if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) { + return false; + } + + clearTimeout( this._leaveTimer ); + this._dragEnterHandler.call( this, e ); + + return false; + }, + + _dragLeaveHandler: function() { + var me = this, + handler; + + handler = function() { + me.dndOver = false; + me.elem.removeClass( prefix + 'over ' + prefix + 'denied' ); + }; + + clearTimeout( me._leaveTimer ); + me._leaveTimer = setTimeout( handler, 100 ); + return false; + }, + + _dropHandler: function( e ) { + var me = this, + ruid = me.getRuid(), + parentElem = me.elem.parent().get( 0 ), + dataTransfer, data; + + // 只处理框内的。 + if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) { + return false; + } + + e = e.originalEvent || e; + dataTransfer = e.dataTransfer; + + // 如果是页面内拖拽,还不能处理,不阻止事件。 + // 此处 ie11 下会报参数错误, + try { + data = dataTransfer.getData('text/html'); + } catch( err ) { + } + + me.dndOver = false; + me.elem.removeClass( prefix + 'over' ); + + if ( !dataTransfer || data ) { + return; + } + + me._getTansferFiles( dataTransfer, function( results ) { + me.trigger( 'drop', $.map( results, function( file ) { + return new File( ruid, file ); + }) ); + }); + + return false; + }, + + // 如果传入 callback 则去查看文件夹,否则只管当前文件夹。 + _getTansferFiles: function( dataTransfer, callback ) { + var results = [], + promises = [], + items, files, file, item, i, len, canAccessFolder; + + items = dataTransfer.items; + files = dataTransfer.files; + + canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry); + + for ( i = 0, len = files.length; i < len; i++ ) { + file = files[ i ]; + item = items && items[ i ]; + + if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) { + + promises.push( this._traverseDirectoryTree( + item.webkitGetAsEntry(), results ) ); + } else { + results.push( file ); + } + } + + Base.when.apply( Base, promises ).done(function() { + + if ( !results.length ) { + return; + } + + callback( results ); + }); + }, + + _traverseDirectoryTree: function( entry, results ) { + var deferred = Base.Deferred(), + me = this; + + if ( entry.isFile ) { + entry.file(function( file ) { + results.push( file ); + deferred.resolve(); + }); + } else if ( entry.isDirectory ) { + entry.createReader().readEntries(function( entries ) { + var len = entries.length, + promises = [], + arr = [], // 为了保证顺序。 + i; + + for ( i = 0; i < len; i++ ) { + promises.push( me._traverseDirectoryTree( + entries[ i ], arr ) ); + } + + Base.when.apply( Base, promises ).then(function() { + results.push.apply( results, arr ); + deferred.resolve(); + }, deferred.reject ); + }); + } + + return deferred.promise(); + }, + + destroy: function() { + var elem = this.elem; + + // 还没 init 就调用 destroy + if (!elem) { + return; + } + + elem.off( 'dragenter', this.dragEnterHandler ); + elem.off( 'dragover', this.dragOverHandler ); + elem.off( 'dragleave', this.dragLeaveHandler ); + elem.off( 'drop', this.dropHandler ); + + if ( this.options.disableGlobalDnd ) { + $( document ).off( 'dragover', this.dragOverHandler ); + $( document ).off( 'drop', this.dropHandler ); + } + } + }); + }); + + /** + * @fileOverview FilePaste + */ + define('runtime/html5/filepaste',[ + 'base', + 'runtime/html5/runtime', + 'lib/file' + ], function( Base, Html5Runtime, File ) { + + return Html5Runtime.register( 'FilePaste', { + init: function() { + var opts = this.options, + elem = this.elem = opts.container, + accept = '.*', + arr, i, len, item; + + // accetp的mimeTypes中生成匹配正则。 + if ( opts.accept ) { + arr = []; + + for ( i = 0, len = opts.accept.length; i < len; i++ ) { + item = opts.accept[ i ].mimeTypes; + item && arr.push( item ); + } + + if ( arr.length ) { + accept = arr.join(','); + accept = accept.replace( /,/g, '|' ).replace( /\*/g, '.*' ); + } + } + this.accept = accept = new RegExp( accept, 'i' ); + this.hander = Base.bindFn( this._pasteHander, this ); + elem.on( 'paste', this.hander ); + }, + + _pasteHander: function( e ) { + var allowed = [], + ruid = this.getRuid(), + items, item, blob, i, len; + + e = e.originalEvent || e; + items = e.clipboardData.items; + + for ( i = 0, len = items.length; i < len; i++ ) { + item = items[ i ]; + + if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) { + continue; + } + + allowed.push( new File( ruid, blob ) ); + } + + if ( allowed.length ) { + // 不阻止非文件粘贴(文字粘贴)的事件冒泡 + e.preventDefault(); + e.stopPropagation(); + this.trigger( 'paste', allowed ); + } + }, + + destroy: function() { + this.elem.off( 'paste', this.hander ); + } + }); + }); + + /** + * @fileOverview FilePicker + */ + define('runtime/html5/filepicker',[ + 'base', + 'runtime/html5/runtime' + ], function( Base, Html5Runtime ) { + + var $ = Base.$; + + return Html5Runtime.register( 'FilePicker', { + init: function() { + var container = this.getRuntime().getContainer(), + me = this, + owner = me.owner, + opts = me.options, + label = this.label = $( document.createElement('label') ), + input = this.input = $( document.createElement('input') ), + arr, i, len, mouseHandler, changeHandler; + + input.attr( 'type', 'file' ); + // input.attr( 'capture', 'camera'); + input.attr( 'name', opts.name ); + input.addClass('webuploader-element-invisible'); + + label.on( 'click', function(e) { + input.trigger('click'); + e.stopPropagation(); + owner.trigger('dialogopen'); + }); + + label.css({ + opacity: 0, + width: '100%', + height: '100%', + display: 'block', + cursor: 'pointer', + background: '#ffffff' + }); + + if ( opts.multiple ) { + input.attr( 'multiple', 'multiple' ); + } + + // @todo Firefox不支持单独指定后缀 + if ( opts.accept && opts.accept.length > 0 ) { + arr = []; + + for ( i = 0, len = opts.accept.length; i < len; i++ ) { + arr.push( opts.accept[ i ].mimeTypes ); + } + + input.attr( 'accept', arr.join(',') ); + } + + container.append( input ); + container.append( label ); + + mouseHandler = function( e ) { + owner.trigger( e.type ); + }; + + changeHandler = function( e ) { + var clone; + + // 解决chrome 56 第二次打开文件选择器,然后点击取消,依然会触发change事件的问题 + if (e.target.files.length === 0){ + return false; + } + + // 第一次上传图片后,第二次再点击弹出文件选择器窗,等待 + me.files = e.target.files; + + + // reset input + clone = this.cloneNode( true ); + clone.value = null; + this.parentNode.replaceChild( clone, this ); + + input.off(); + input = $( clone ).on( 'change', changeHandler ) + .on( 'mouseenter mouseleave', mouseHandler ); + + owner.trigger('change'); + } + input.on( 'change', changeHandler); + label.on( 'mouseenter mouseleave', mouseHandler ); + + }, + + + getFiles: function() { + return this.files; + }, + + destroy: function() { + this.input.off(); + this.label.off(); + } + }); + }); + + /** + * Terms: + * + * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer + * @fileOverview Image控件 + */ + define('runtime/html5/util',[ + 'base' + ], function( Base ) { + + var urlAPI = window.createObjectURL && window || + window.URL && URL.revokeObjectURL && URL || + window.webkitURL, + createObjectURL = Base.noop, + revokeObjectURL = createObjectURL; + + if ( urlAPI ) { + + // 更安全的方式调用,比如android里面就能把context改成其他的对象。 + createObjectURL = function() { + return urlAPI.createObjectURL.apply( urlAPI, arguments ); + }; + + revokeObjectURL = function() { + return urlAPI.revokeObjectURL.apply( urlAPI, arguments ); + }; + } + + return { + createObjectURL: createObjectURL, + revokeObjectURL: revokeObjectURL, + + dataURL2Blob: function( dataURI ) { + var byteStr, intArray, ab, i, mimetype, parts; + + parts = dataURI.split(','); + + if ( ~parts[ 0 ].indexOf('base64') ) { + byteStr = atob( parts[ 1 ] ); + } else { + byteStr = decodeURIComponent( parts[ 1 ] ); + } + + ab = new ArrayBuffer( byteStr.length ); + intArray = new Uint8Array( ab ); + + for ( i = 0; i < byteStr.length; i++ ) { + intArray[ i ] = byteStr.charCodeAt( i ); + } + + mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ]; + + return this.arrayBufferToBlob( ab, mimetype ); + }, + + dataURL2ArrayBuffer: function( dataURI ) { + var byteStr, intArray, i, parts; + + parts = dataURI.split(','); + + if ( ~parts[ 0 ].indexOf('base64') ) { + byteStr = atob( parts[ 1 ] ); + } else { + byteStr = decodeURIComponent( parts[ 1 ] ); + } + + intArray = new Uint8Array( byteStr.length ); + + for ( i = 0; i < byteStr.length; i++ ) { + intArray[ i ] = byteStr.charCodeAt( i ); + } + + return intArray.buffer; + }, + + arrayBufferToBlob: function( buffer, type ) { + var builder = window.BlobBuilder || window.WebKitBlobBuilder, + bb; + + // android不支持直接new Blob, 只能借助blobbuilder. + if ( builder ) { + bb = new builder(); + bb.append( buffer ); + return bb.getBlob( type ); + } + + return new Blob([ buffer ], type ? { type: type } : {} ); + }, + + // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg. + // 你得到的结果是png. + canvasToDataUrl: function( canvas, type, quality ) { + return canvas.toDataURL( type, quality / 100 ); + }, + + // imagemeat会复写这个方法,如果用户选择加载那个文件了的话。 + parseMeta: function( blob, callback ) { + callback( false, {}); + }, + + // imagemeat会复写这个方法,如果用户选择加载那个文件了的话。 + updateImageHead: function( data ) { + return data; + } + }; + }); + /** + * Terms: + * + * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer + * @fileOverview Image控件 + */ + define('runtime/html5/imagemeta',[ + 'runtime/html5/util' + ], function( Util ) { + + var api; + + api = { + parsers: { + 0xffe1: [] + }, + + maxMetaDataSize: 262144, + + parse: function( blob, cb ) { + var me = this, + fr = new FileReader(); + + fr.onload = function() { + cb( false, me._parse( this.result ) ); + fr = fr.onload = fr.onerror = null; + }; + + fr.onerror = function( e ) { + cb( e.message ); + fr = fr.onload = fr.onerror = null; + }; + + blob = blob.slice( 0, me.maxMetaDataSize ); + fr.readAsArrayBuffer( blob.getSource() ); + }, + + _parse: function( buffer, noParse ) { + if ( buffer.byteLength < 6 ) { + return; + } + + var dataview = new DataView( buffer ), + offset = 2, + maxOffset = dataview.byteLength - 4, + headLength = offset, + ret = {}, + markerBytes, markerLength, parsers, i; + + if ( dataview.getUint16( 0 ) === 0xffd8 ) { + + while ( offset < maxOffset ) { + markerBytes = dataview.getUint16( offset ); + + if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef || + markerBytes === 0xfffe ) { + + markerLength = dataview.getUint16( offset + 2 ) + 2; + + if ( offset + markerLength > dataview.byteLength ) { + break; + } + + parsers = api.parsers[ markerBytes ]; + + if ( !noParse && parsers ) { + for ( i = 0; i < parsers.length; i += 1 ) { + parsers[ i ].call( api, dataview, offset, + markerLength, ret ); + } + } + + offset += markerLength; + headLength = offset; + } else { + break; + } + } + + if ( headLength > 6 ) { + if ( buffer.slice ) { + ret.imageHead = buffer.slice( 2, headLength ); + } else { + // Workaround for IE10, which does not yet + // support ArrayBuffer.slice: + ret.imageHead = new Uint8Array( buffer ) + .subarray( 2, headLength ); + } + } + } + + return ret; + }, + + updateImageHead: function( buffer, head ) { + var data = this._parse( buffer, true ), + buf1, buf2, bodyoffset; + + + bodyoffset = 2; + if ( data.imageHead ) { + bodyoffset = 2 + data.imageHead.byteLength; + } + + if ( buffer.slice ) { + buf2 = buffer.slice( bodyoffset ); + } else { + buf2 = new Uint8Array( buffer ).subarray( bodyoffset ); + } + + buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength ); + + buf1[ 0 ] = 0xFF; + buf1[ 1 ] = 0xD8; + buf1.set( new Uint8Array( head ), 2 ); + buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 ); + + return buf1.buffer; + } + }; + + Util.parseMeta = function() { + return api.parse.apply( api, arguments ); + }; + + Util.updateImageHead = function() { + return api.updateImageHead.apply( api, arguments ); + }; + + return api; + }); + /** + * 代码来自于:https://github.com/blueimp/JavaScript-Load-Image + * 暂时项目中只用了orientation. + * + * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail. + * @fileOverview EXIF解析 + */ + + // Sample + // ==================================== + // Make : Apple + // Model : iPhone 4S + // Orientation : 1 + // XResolution : 72 [72/1] + // YResolution : 72 [72/1] + // ResolutionUnit : 2 + // Software : QuickTime 7.7.1 + // DateTime : 2013:09:01 22:53:55 + // ExifIFDPointer : 190 + // ExposureTime : 0.058823529411764705 [1/17] + // FNumber : 2.4 [12/5] + // ExposureProgram : Normal program + // ISOSpeedRatings : 800 + // ExifVersion : 0220 + // DateTimeOriginal : 2013:09:01 22:52:51 + // DateTimeDigitized : 2013:09:01 22:52:51 + // ComponentsConfiguration : YCbCr + // ShutterSpeedValue : 4.058893515764426 + // ApertureValue : 2.5260688216892597 [4845/1918] + // BrightnessValue : -0.3126686601998395 + // MeteringMode : Pattern + // Flash : Flash did not fire, compulsory flash mode + // FocalLength : 4.28 [107/25] + // SubjectArea : [4 values] + // FlashpixVersion : 0100 + // ColorSpace : 1 + // PixelXDimension : 2448 + // PixelYDimension : 3264 + // SensingMethod : One-chip color area sensor + // ExposureMode : 0 + // WhiteBalance : Auto white balance + // FocalLengthIn35mmFilm : 35 + // SceneCaptureType : Standard + define('runtime/html5/imagemeta/exif',[ + 'base', + 'runtime/html5/imagemeta' + ], function( Base, ImageMeta ) { + + var EXIF = {}; + + EXIF.ExifMap = function() { + return this; + }; + + EXIF.ExifMap.prototype.map = { + 'Orientation': 0x0112 + }; + + EXIF.ExifMap.prototype.get = function( id ) { + return this[ id ] || this[ this.map[ id ] ]; + }; + + EXIF.exifTagTypes = { + // byte, 8-bit unsigned int: + 1: { + getValue: function( dataView, dataOffset ) { + return dataView.getUint8( dataOffset ); + }, + size: 1 + }, + + // ascii, 8-bit byte: + 2: { + getValue: function( dataView, dataOffset ) { + return String.fromCharCode( dataView.getUint8( dataOffset ) ); + }, + size: 1, + ascii: true + }, + + // short, 16 bit int: + 3: { + getValue: function( dataView, dataOffset, littleEndian ) { + return dataView.getUint16( dataOffset, littleEndian ); + }, + size: 2 + }, + + // long, 32 bit int: + 4: { + getValue: function( dataView, dataOffset, littleEndian ) { + return dataView.getUint32( dataOffset, littleEndian ); + }, + size: 4 + }, + + // rational = two long values, + // first is numerator, second is denominator: + 5: { + getValue: function( dataView, dataOffset, littleEndian ) { + return dataView.getUint32( dataOffset, littleEndian ) / + dataView.getUint32( dataOffset + 4, littleEndian ); + }, + size: 8 + }, + + // slong, 32 bit signed int: + 9: { + getValue: function( dataView, dataOffset, littleEndian ) { + return dataView.getInt32( dataOffset, littleEndian ); + }, + size: 4 + }, + + // srational, two slongs, first is numerator, second is denominator: + 10: { + getValue: function( dataView, dataOffset, littleEndian ) { + return dataView.getInt32( dataOffset, littleEndian ) / + dataView.getInt32( dataOffset + 4, littleEndian ); + }, + size: 8 + } + }; + + // undefined, 8-bit byte, value depending on field: + EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ]; + + EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length, + littleEndian ) { + + var tagType = EXIF.exifTagTypes[ type ], + tagSize, dataOffset, values, i, str, c; + + if ( !tagType ) { + Base.log('Invalid Exif data: Invalid tag type.'); + return; + } + + tagSize = tagType.size * length; + + // Determine if the value is contained in the dataOffset bytes, + // or if the value at the dataOffset is a pointer to the actual data: + dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8, + littleEndian ) : (offset + 8); + + if ( dataOffset + tagSize > dataView.byteLength ) { + Base.log('Invalid Exif data: Invalid data offset.'); + return; + } + + if ( length === 1 ) { + return tagType.getValue( dataView, dataOffset, littleEndian ); + } + + values = []; + + for ( i = 0; i < length; i += 1 ) { + values[ i ] = tagType.getValue( dataView, + dataOffset + i * tagType.size, littleEndian ); + } + + if ( tagType.ascii ) { + str = ''; + + // Concatenate the chars: + for ( i = 0; i < values.length; i += 1 ) { + c = values[ i ]; + + // Ignore the terminating NULL byte(s): + if ( c === '\u0000' ) { + break; + } + str += c; + } + + return str; + } + return values; + }; + + EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian, + data ) { + + var tag = dataView.getUint16( offset, littleEndian ); + data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset, + dataView.getUint16( offset + 2, littleEndian ), // tag type + dataView.getUint32( offset + 4, littleEndian ), // tag length + littleEndian ); + }; + + EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset, + littleEndian, data ) { + + var tagsNumber, dirEndOffset, i; + + if ( dirOffset + 6 > dataView.byteLength ) { + Base.log('Invalid Exif data: Invalid directory offset.'); + return; + } + + tagsNumber = dataView.getUint16( dirOffset, littleEndian ); + dirEndOffset = dirOffset + 2 + 12 * tagsNumber; + + if ( dirEndOffset + 4 > dataView.byteLength ) { + Base.log('Invalid Exif data: Invalid directory size.'); + return; + } + + for ( i = 0; i < tagsNumber; i += 1 ) { + this.parseExifTag( dataView, tiffOffset, + dirOffset + 2 + 12 * i, // tag offset + littleEndian, data ); + } + + // Return the offset to the next directory: + return dataView.getUint32( dirEndOffset, littleEndian ); + }; + + // EXIF.getExifThumbnail = function(dataView, offset, length) { + // var hexData, + // i, + // b; + // if (!length || offset + length > dataView.byteLength) { + // Base.log('Invalid Exif data: Invalid thumbnail data.'); + // return; + // } + // hexData = []; + // for (i = 0; i < length; i += 1) { + // b = dataView.getUint8(offset + i); + // hexData.push((b < 16 ? '0' : '') + b.toString(16)); + // } + // return 'data:image/jpeg,%' + hexData.join('%'); + // }; + + EXIF.parseExifData = function( dataView, offset, length, data ) { + + var tiffOffset = offset + 10, + littleEndian, dirOffset; + + // Check for the ASCII code for "Exif" (0x45786966): + if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) { + // No Exif data, might be XMP data instead + return; + } + if ( tiffOffset + 8 > dataView.byteLength ) { + Base.log('Invalid Exif data: Invalid segment size.'); + return; + } + + // Check for the two null bytes: + if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) { + Base.log('Invalid Exif data: Missing byte alignment offset.'); + return; + } + + // Check the byte alignment: + switch ( dataView.getUint16( tiffOffset ) ) { + case 0x4949: + littleEndian = true; + break; + + case 0x4D4D: + littleEndian = false; + break; + + default: + Base.log('Invalid Exif data: Invalid byte alignment marker.'); + return; + } + + // Check for the TIFF tag marker (0x002A): + if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) { + Base.log('Invalid Exif data: Missing TIFF marker.'); + return; + } + + // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal: + dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian ); + // Create the exif object to store the tags: + data.exif = new EXIF.ExifMap(); + // Parse the tags of the main image directory and retrieve the + // offset to the next directory, usually the thumbnail directory: + dirOffset = EXIF.parseExifTags( dataView, tiffOffset, + tiffOffset + dirOffset, littleEndian, data ); + + // 尝试读取缩略图 + // if ( dirOffset ) { + // thumbnailData = {exif: {}}; + // dirOffset = EXIF.parseExifTags( + // dataView, + // tiffOffset, + // tiffOffset + dirOffset, + // littleEndian, + // thumbnailData + // ); + + // // Check for JPEG Thumbnail offset: + // if (thumbnailData.exif[0x0201]) { + // data.exif.Thumbnail = EXIF.getExifThumbnail( + // dataView, + // tiffOffset + thumbnailData.exif[0x0201], + // thumbnailData.exif[0x0202] // Thumbnail data length + // ); + // } + // } + }; + + ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData ); + return EXIF; + }); + /** + * 这个方式性能不行,但是可以解决android里面的toDataUrl的bug + * android里面toDataUrl('image/jpege')得到的结果却是png. + * + * 所以这里没辙,只能借助这个工具 + * @fileOverview jpeg encoder + */ + define('runtime/html5/jpegencoder',[], function( require, exports, module ) { + + /* + Copyright (c) 2008, Adobe Systems Incorporated + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Adobe Systems Incorporated nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /* + JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009 + + Basic GUI blocking jpeg encoder + */ + + function JPEGEncoder(quality) { + var self = this; + var fround = Math.round; + var ffloor = Math.floor; + var YTable = new Array(64); + var UVTable = new Array(64); + var fdtbl_Y = new Array(64); + var fdtbl_UV = new Array(64); + var YDC_HT; + var UVDC_HT; + var YAC_HT; + var UVAC_HT; + + var bitcode = new Array(65535); + var category = new Array(65535); + var outputfDCTQuant = new Array(64); + var DU = new Array(64); + var byteout = []; + var bytenew = 0; + var bytepos = 7; + + var YDU = new Array(64); + var UDU = new Array(64); + var VDU = new Array(64); + var clt = new Array(256); + var RGB_YUV_TABLE = new Array(2048); + var currentQuality; + + var ZigZag = [ + 0, 1, 5, 6,14,15,27,28, + 2, 4, 7,13,16,26,29,42, + 3, 8,12,17,25,30,41,43, + 9,11,18,24,31,40,44,53, + 10,19,23,32,39,45,52,54, + 20,22,33,38,46,51,55,60, + 21,34,37,47,50,56,59,61, + 35,36,48,49,57,58,62,63 + ]; + + var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0]; + var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11]; + var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d]; + var std_ac_luminance_values = [ + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12, + 0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07, + 0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0, + 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16, + 0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39, + 0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69, + 0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79, + 0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98, + 0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, + 0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5, + 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4, + 0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea, + 0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa + ]; + + var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0]; + var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11]; + var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77]; + var std_ac_chrominance_values = [ + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21, + 0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71, + 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0, + 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34, + 0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38, + 0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48, + 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68, + 0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78, + 0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96, + 0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5, + 0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3, + 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2, + 0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9, + 0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa + ]; + + function initQuantTables(sf){ + var YQT = [ + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68,109,103, 77, + 24, 35, 55, 64, 81,104,113, 92, + 49, 64, 78, 87,103,121,120,101, + 72, 92, 95, 98,112,100,103, 99 + ]; + + for (var i = 0; i < 64; i++) { + var t = ffloor((YQT[i]*sf+50)/100); + if (t < 1) { + t = 1; + } else if (t > 255) { + t = 255; + } + YTable[ZigZag[i]] = t; + } + var UVQT = [ + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + ]; + for (var j = 0; j < 64; j++) { + var u = ffloor((UVQT[j]*sf+50)/100); + if (u < 1) { + u = 1; + } else if (u > 255) { + u = 255; + } + UVTable[ZigZag[j]] = u; + } + var aasf = [ + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + ]; + var k = 0; + for (var row = 0; row < 8; row++) + { + for (var col = 0; col < 8; col++) + { + fdtbl_Y[k] = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0)); + fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0)); + k++; + } + } + } + + function computeHuffmanTbl(nrcodes, std_table){ + var codevalue = 0; + var pos_in_table = 0; + var HT = new Array(); + for (var k = 1; k <= 16; k++) { + for (var j = 1; j <= nrcodes[k]; j++) { + HT[std_table[pos_in_table]] = []; + HT[std_table[pos_in_table]][0] = codevalue; + HT[std_table[pos_in_table]][1] = k; + pos_in_table++; + codevalue++; + } + codevalue*=2; + } + return HT; + } + + function initHuffmanTbl() + { + YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values); + UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values); + YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values); + UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values); + } + + function initCategoryNumber() + { + var nrlower = 1; + var nrupper = 2; + for (var cat = 1; cat <= 15; cat++) { + //Positive numbers + for (var nr = nrlower; nr>0] = 38470 * i; + RGB_YUV_TABLE[(i+ 512)>>0] = 7471 * i + 0x8000; + RGB_YUV_TABLE[(i+ 768)>>0] = -11059 * i; + RGB_YUV_TABLE[(i+1024)>>0] = -21709 * i; + RGB_YUV_TABLE[(i+1280)>>0] = 32768 * i + 0x807FFF; + RGB_YUV_TABLE[(i+1536)>>0] = -27439 * i; + RGB_YUV_TABLE[(i+1792)>>0] = - 5329 * i; + } + } + + // IO functions + function writeBits(bs) + { + var value = bs[0]; + var posval = bs[1]-1; + while ( posval >= 0 ) { + if (value & (1 << posval) ) { + bytenew |= (1 << bytepos); + } + posval--; + bytepos--; + if (bytepos < 0) { + if (bytenew == 0xFF) { + writeByte(0xFF); + writeByte(0); + } + else { + writeByte(bytenew); + } + bytepos=7; + bytenew=0; + } + } + } + + function writeByte(value) + { + byteout.push(clt[value]); // write char directly instead of converting later + } + + function writeWord(value) + { + writeByte((value>>8)&0xFF); + writeByte((value )&0xFF); + } + + // DCT & quantization core + function fDCTQuant(data, fdtbl) + { + var d0, d1, d2, d3, d4, d5, d6, d7; + /* Pass 1: process rows. */ + var dataOff=0; + var i; + var I8 = 8; + var I64 = 64; + for (i=0; i 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0); + //outputfDCTQuant[i] = fround(fDCTQuant); + + } + return outputfDCTQuant; + } + + function writeAPP0() + { + writeWord(0xFFE0); // marker + writeWord(16); // length + writeByte(0x4A); // J + writeByte(0x46); // F + writeByte(0x49); // I + writeByte(0x46); // F + writeByte(0); // = "JFIF",'\0' + writeByte(1); // versionhi + writeByte(1); // versionlo + writeByte(0); // xyunits + writeWord(1); // xdensity + writeWord(1); // ydensity + writeByte(0); // thumbnwidth + writeByte(0); // thumbnheight + } + + function writeSOF0(width, height) + { + writeWord(0xFFC0); // marker + writeWord(17); // length, truecolor YUV JPG + writeByte(8); // precision + writeWord(height); + writeWord(width); + writeByte(3); // nrofcomponents + writeByte(1); // IdY + writeByte(0x11); // HVY + writeByte(0); // QTY + writeByte(2); // IdU + writeByte(0x11); // HVU + writeByte(1); // QTU + writeByte(3); // IdV + writeByte(0x11); // HVV + writeByte(1); // QTV + } + + function writeDQT() + { + writeWord(0xFFDB); // marker + writeWord(132); // length + writeByte(0); + for (var i=0; i<64; i++) { + writeByte(YTable[i]); + } + writeByte(1); + for (var j=0; j<64; j++) { + writeByte(UVTable[j]); + } + } + + function writeDHT() + { + writeWord(0xFFC4); // marker + writeWord(0x01A2); // length + + writeByte(0); // HTYDCinfo + for (var i=0; i<16; i++) { + writeByte(std_dc_luminance_nrcodes[i+1]); + } + for (var j=0; j<=11; j++) { + writeByte(std_dc_luminance_values[j]); + } + + writeByte(0x10); // HTYACinfo + for (var k=0; k<16; k++) { + writeByte(std_ac_luminance_nrcodes[k+1]); + } + for (var l=0; l<=161; l++) { + writeByte(std_ac_luminance_values[l]); + } + + writeByte(1); // HTUDCinfo + for (var m=0; m<16; m++) { + writeByte(std_dc_chrominance_nrcodes[m+1]); + } + for (var n=0; n<=11; n++) { + writeByte(std_dc_chrominance_values[n]); + } + + writeByte(0x11); // HTUACinfo + for (var o=0; o<16; o++) { + writeByte(std_ac_chrominance_nrcodes[o+1]); + } + for (var p=0; p<=161; p++) { + writeByte(std_ac_chrominance_values[p]); + } + } + + function writeSOS() + { + writeWord(0xFFDA); // marker + writeWord(12); // length + writeByte(3); // nrofcomponents + writeByte(1); // IdY + writeByte(0); // HTY + writeByte(2); // IdU + writeByte(0x11); // HTU + writeByte(3); // IdV + writeByte(0x11); // HTV + writeByte(0); // Ss + writeByte(0x3f); // Se + writeByte(0); // Bf + } + + function processDU(CDU, fdtbl, DC, HTDC, HTAC){ + var EOB = HTAC[0x00]; + var M16zeroes = HTAC[0xF0]; + var pos; + var I16 = 16; + var I63 = 63; + var I64 = 64; + var DU_DCT = fDCTQuant(CDU, fdtbl); + //ZigZag reorder + for (var j=0;j0)&&(DU[end0pos]==0); end0pos--) {}; + //end0pos = first element in reverse order !=0 + if ( end0pos == 0) { + writeBits(EOB); + return DC; + } + var i = 1; + var lng; + while ( i <= end0pos ) { + var startpos = i; + for (; (DU[i]==0) && (i<=end0pos); ++i) {} + var nrzeroes = i-startpos; + if ( nrzeroes >= I16 ) { + lng = nrzeroes>>4; + for (var nrmarker=1; nrmarker <= lng; ++nrmarker) + writeBits(M16zeroes); + nrzeroes = nrzeroes&0xF; + } + pos = 32767+DU[i]; + writeBits(HTAC[(nrzeroes<<4)+category[pos]]); + writeBits(bitcode[pos]); + i++; + } + if ( end0pos != I63 ) { + writeBits(EOB); + } + return DC; + } + + function initCharLookupTable(){ + var sfcc = String.fromCharCode; + for(var i=0; i < 256; i++){ ///// ACHTUNG // 255 + clt[i] = sfcc(i); + } + } + + this.encode = function(image,quality) // image data object + { + // var time_start = new Date().getTime(); + + if(quality) setQuality(quality); + + // Initialize bit writer + byteout = new Array(); + bytenew=0; + bytepos=7; + + // Add JPEG headers + writeWord(0xFFD8); // SOI + writeAPP0(); + writeDQT(); + writeSOF0(image.width,image.height); + writeDHT(); + writeSOS(); + + + // Encode 8x8 macroblocks + var DCY=0; + var DCU=0; + var DCV=0; + + bytenew=0; + bytepos=7; + + + this.encode.displayName = "_encode_"; + + var imageData = image.data; + var width = image.width; + var height = image.height; + + var quadWidth = width*4; + var tripleWidth = width*3; + + var x, y = 0; + var r, g, b; + var start,p, col,row,pos; + while(y < height){ + x = 0; + while(x < quadWidth){ + start = quadWidth * y + x; + p = start; + col = -1; + row = 0; + + for(pos=0; pos < 64; pos++){ + row = pos >> 3;// /8 + col = ( pos & 7 ) * 4; // %8 + p = start + ( row * quadWidth ) + col; + + if(y+row >= height){ // padding bottom + p-= (quadWidth*(y+1+row-height)); + } + + if(x+col >= quadWidth){ // padding right + p-= ((x+col) - quadWidth +4) + } + + r = imageData[ p++ ]; + g = imageData[ p++ ]; + b = imageData[ p++ ]; + + + /* // calculate YUV values dynamically + YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80 + UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b)); + VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b)); + */ + + // use lookup table (slightly faster) + YDU[pos] = ((RGB_YUV_TABLE[r] + RGB_YUV_TABLE[(g + 256)>>0] + RGB_YUV_TABLE[(b + 512)>>0]) >> 16)-128; + UDU[pos] = ((RGB_YUV_TABLE[(r + 768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128; + VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128; + + } + + DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + x+=32; + } + y+=8; + } + + + //////////////////////////////////////////////////////////////// + + // Do the bit alignment of the EOI marker + if ( bytepos >= 0 ) { + var fillbits = []; + fillbits[1] = bytepos+1; + fillbits[0] = (1<<(bytepos+1))-1; + writeBits(fillbits); + } + + writeWord(0xFFD9); //EOI + + var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join('')); + + byteout = []; + + // benchmarking + // var duration = new Date().getTime() - time_start; + // console.log('Encoding time: '+ currentQuality + 'ms'); + // + + return jpegDataUri + } + + function setQuality(quality){ + if (quality <= 0) { + quality = 1; + } + if (quality > 100) { + quality = 100; + } + + if(currentQuality == quality) return // don't recalc if unchanged + + var sf = 0; + if (quality < 50) { + sf = Math.floor(5000 / quality); + } else { + sf = Math.floor(200 - quality*2); + } + + initQuantTables(sf); + currentQuality = quality; + // console.log('Quality set to: '+quality +'%'); + } + + function init(){ + // var time_start = new Date().getTime(); + if(!quality) quality = 50; + // Create tables + initCharLookupTable() + initHuffmanTbl(); + initCategoryNumber(); + initRGBYUVTable(); + + setQuality(quality); + // var duration = new Date().getTime() - time_start; + // console.log('Initialization '+ duration + 'ms'); + } + + init(); + + }; + + JPEGEncoder.encode = function( data, quality ) { + var encoder = new JPEGEncoder( quality ); + + return encoder.encode( data ); + } + + return JPEGEncoder; + }); + /** + * @fileOverview Fix android canvas.toDataUrl bug. + */ + define('runtime/html5/androidpatch',[ + 'runtime/html5/util', + 'runtime/html5/jpegencoder', + 'base' + ], function( Util, encoder, Base ) { + var origin = Util.canvasToDataUrl, + supportJpeg; + + Util.canvasToDataUrl = function( canvas, type, quality ) { + var ctx, w, h, fragement, parts; + + // 非android手机直接跳过。 + if ( !Base.os.android ) { + return origin.apply( null, arguments ); + } + + // 检测是否canvas支持jpeg导出,根据数据格式来判断。 + // JPEG 前两位分别是:255, 216 + if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) { + fragement = origin.apply( null, arguments ); + + parts = fragement.split(','); + + if ( ~parts[ 0 ].indexOf('base64') ) { + fragement = atob( parts[ 1 ] ); + } else { + fragement = decodeURIComponent( parts[ 1 ] ); + } + + fragement = fragement.substring( 0, 2 ); + + supportJpeg = fragement.charCodeAt( 0 ) === 255 && + fragement.charCodeAt( 1 ) === 216; + } + + // 只有在android环境下才修复 + if ( type === 'image/jpeg' && !supportJpeg ) { + w = canvas.width; + h = canvas.height; + ctx = canvas.getContext('2d'); + + return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality ); + } + + return origin.apply( null, arguments ); + }; + }); + /** + * @fileOverview Image + */ + define('runtime/html5/image',[ + 'base', + 'runtime/html5/runtime', + 'runtime/html5/util' + ], function( Base, Html5Runtime, Util ) { + + var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D'; + + return Html5Runtime.register( 'Image', { + + // flag: 标记是否被修改过。 + modified: false, + + init: function() { + var me = this, + img = new Image(); + + img.onload = function() { + + me._info = { + type: me.type, + width: this.width, + height: this.height + }; + + //debugger; + + // 读取meta信息。 + if ( !me._metas && 'image/jpeg' === me.type ) { + Util.parseMeta( me._blob, function( error, ret ) { + me._metas = ret; + me.owner.trigger('load'); + }); + } else { + me.owner.trigger('load'); + } + }; + + img.onerror = function() { + me.owner.trigger('error'); + }; + + me._img = img; + }, + + loadFromBlob: function( blob ) { + var me = this, + img = me._img; + + me._blob = blob; + me.type = blob.type; + img.src = Util.createObjectURL( blob.getSource() ); + me.owner.once( 'load', function() { + Util.revokeObjectURL( img.src ); + }); + }, + + resize: function( width, height ) { + var canvas = this._canvas || + (this._canvas = document.createElement('canvas')); + + this._resize( this._img, canvas, width, height ); + this._blob = null; // 没用了,可以删掉了。 + this.modified = true; + this.owner.trigger( 'complete', 'resize' ); + }, + + crop: function( x, y, w, h, s ) { + var cvs = this._canvas || + (this._canvas = document.createElement('canvas')), + opts = this.options, + img = this._img, + iw = img.naturalWidth, + ih = img.naturalHeight, + orientation = this.getOrientation(); + + s = s || 1; + + // todo 解决 orientation 的问题。 + // values that require 90 degree rotation + // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) { + + // switch ( orientation ) { + // case 6: + // tmp = x; + // x = y; + // y = iw * s - tmp - w; + // console.log(ih * s, tmp, w) + // break; + // } + + // (w ^= h, h ^= w, w ^= h); + // } + + cvs.width = w; + cvs.height = h; + + opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation ); + this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s ); + + this._blob = null; // 没用了,可以删掉了。 + this.modified = true; + this.owner.trigger( 'complete', 'crop' ); + }, + + getAsBlob: function( type ) { + var blob = this._blob, + opts = this.options, + canvas; + + type = type || this.type; + + // blob需要重新生成。 + if ( this.modified || this.type !== type ) { + canvas = this._canvas; + + if ( type === 'image/jpeg' ) { + + blob = Util.canvasToDataUrl( canvas, type, opts.quality ); + + if ( opts.preserveHeaders && this._metas && + this._metas.imageHead ) { + + blob = Util.dataURL2ArrayBuffer( blob ); + blob = Util.updateImageHead( blob, + this._metas.imageHead ); + blob = Util.arrayBufferToBlob( blob, type ); + return blob; + } + } else { + blob = Util.canvasToDataUrl( canvas, type ); + } + + blob = Util.dataURL2Blob( blob ); + } + + return blob; + }, + + getAsDataUrl: function( type ) { + var opts = this.options; + + type = type || this.type; + + if ( type === 'image/jpeg' ) { + return Util.canvasToDataUrl( this._canvas, type, opts.quality ); + } else { + return this._canvas.toDataURL( type ); + } + }, + + getOrientation: function() { + return this._metas && this._metas.exif && + this._metas.exif.get('Orientation') || 1; + }, + + info: function( val ) { + + // setter + if ( val ) { + this._info = val; + return this; + } + + // getter + return this._info; + }, + + meta: function( val ) { + + // setter + if ( val ) { + this._metas = val; + return this; + } + + // getter + return this._metas; + }, + + destroy: function() { + var canvas = this._canvas; + this._img.onload = null; + + if ( canvas ) { + canvas.getContext('2d') + .clearRect( 0, 0, canvas.width, canvas.height ); + canvas.width = canvas.height = 0; + this._canvas = null; + } + + // 释放内存。非常重要,否则释放不了image的内存。 + this._img.src = BLANK; + this._img = this._blob = null; + }, + + _resize: function( img, cvs, width, height ) { + var opts = this.options, + naturalWidth = img.width, + naturalHeight = img.height, + orientation = this.getOrientation(), + scale, w, h, x, y; + + // values that require 90 degree rotation + if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) { + + // 交换width, height的值。 + width ^= height; + height ^= width; + width ^= height; + } + + scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth, + height / naturalHeight ); + + // 不允许放大。 + opts.allowMagnify || (scale = Math.min( 1, scale )); + + w = naturalWidth * scale; + h = naturalHeight * scale; + + if ( opts.crop ) { + cvs.width = width; + cvs.height = height; + } else { + cvs.width = w; + cvs.height = h; + } + + x = (cvs.width - w) / 2; + y = (cvs.height - h) / 2; + + opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation ); + + this._renderImageToCanvas( cvs, img, x, y, w, h ); + }, + + _rotate2Orientaion: function( canvas, orientation ) { + var width = canvas.width, + height = canvas.height, + ctx = canvas.getContext('2d'); + + switch ( orientation ) { + case 5: + case 6: + case 7: + case 8: + canvas.width = height; + canvas.height = width; + break; + } + + switch ( orientation ) { + case 2: // horizontal flip + ctx.translate( width, 0 ); + ctx.scale( -1, 1 ); + break; + + case 3: // 180 rotate left + ctx.translate( width, height ); + ctx.rotate( Math.PI ); + break; + + case 4: // vertical flip + ctx.translate( 0, height ); + ctx.scale( 1, -1 ); + break; + + case 5: // vertical flip + 90 rotate right + ctx.rotate( 0.5 * Math.PI ); + ctx.scale( 1, -1 ); + break; + + case 6: // 90 rotate right + ctx.rotate( 0.5 * Math.PI ); + ctx.translate( 0, -height ); + break; + + case 7: // horizontal flip + 90 rotate right + ctx.rotate( 0.5 * Math.PI ); + ctx.translate( width, -height ); + ctx.scale( -1, 1 ); + break; + + case 8: // 90 rotate left + ctx.rotate( -0.5 * Math.PI ); + ctx.translate( -width, 0 ); + break; + } + }, + + // https://github.com/stomita/ios-imagefile-megapixel/ + // blob/master/src/megapix-image.js + _renderImageToCanvas: (function() { + + // 如果不是ios, 不需要这么复杂! + if ( !Base.os.ios ) { + return function( canvas ) { + var args = Base.slice( arguments, 1 ), + ctx = canvas.getContext('2d'); + + ctx.drawImage.apply( ctx, args ); + }; + } + + /** + * Detecting vertical squash in loaded image. + * Fixes a bug which squash image vertically while drawing into + * canvas for some images. + */ + function detectVerticalSquash( img, iw, ih ) { + var canvas = document.createElement('canvas'), + ctx = canvas.getContext('2d'), + sy = 0, + ey = ih, + py = ih, + data, alpha, ratio; + + + canvas.width = 1; + canvas.height = ih; + ctx.drawImage( img, 0, 0 ); + data = ctx.getImageData( 0, 0, 1, ih ).data; + + // search image edge pixel position in case + // it is squashed vertically. + while ( py > sy ) { + alpha = data[ (py - 1) * 4 + 3 ]; + + if ( alpha === 0 ) { + ey = py; + } else { + sy = py; + } + + py = (ey + sy) >> 1; + } + + ratio = (py / ih); + return (ratio === 0) ? 1 : ratio; + } + + // fix ie7 bug + // http://stackoverflow.com/questions/11929099/ + // html5-canvas-drawimage-ratio-bug-ios + if ( Base.os.ios >= 7 ) { + return function( canvas, img, x, y, w, h ) { + var iw = img.naturalWidth, + ih = img.naturalHeight, + vertSquashRatio = detectVerticalSquash( img, iw, ih ); + + return canvas.getContext('2d').drawImage( img, 0, 0, + iw * vertSquashRatio, ih * vertSquashRatio, + x, y, w, h ); + }; + } + + /** + * Detect subsampling in loaded image. + * In iOS, larger images than 2M pixels may be + * subsampled in rendering. + */ + function detectSubsampling( img ) { + var iw = img.naturalWidth, + ih = img.naturalHeight, + canvas, ctx; + + // subsampling may happen overmegapixel image + if ( iw * ih > 1024 * 1024 ) { + canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + ctx = canvas.getContext('2d'); + ctx.drawImage( img, -iw + 1, 0 ); + + // subsampled image becomes half smaller in rendering size. + // check alpha channel value to confirm image is covering + // edge pixel or not. if alpha value is 0 + // image is not covering, hence subsampled. + return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0; + } else { + return false; + } + } + + + return function( canvas, img, x, y, width, height ) { + var iw = img.naturalWidth, + ih = img.naturalHeight, + ctx = canvas.getContext('2d'), + subsampled = detectSubsampling( img ), + doSquash = this.type === 'image/jpeg', + d = 1024, + sy = 0, + dy = 0, + tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx; + + if ( subsampled ) { + iw /= 2; + ih /= 2; + } + + ctx.save(); + tmpCanvas = document.createElement('canvas'); + tmpCanvas.width = tmpCanvas.height = d; + + tmpCtx = tmpCanvas.getContext('2d'); + vertSquashRatio = doSquash ? + detectVerticalSquash( img, iw, ih ) : 1; + + dw = Math.ceil( d * width / iw ); + dh = Math.ceil( d * height / ih / vertSquashRatio ); + + while ( sy < ih ) { + sx = 0; + dx = 0; + while ( sx < iw ) { + tmpCtx.clearRect( 0, 0, d, d ); + tmpCtx.drawImage( img, -sx, -sy ); + ctx.drawImage( tmpCanvas, 0, 0, d, d, + x + dx, y + dy, dw, dh ); + sx += d; + dx += dw; + } + sy += d; + dy += dh; + } + ctx.restore(); + tmpCanvas = tmpCtx = null; + }; + })() + }); + }); + + /** + * @fileOverview Transport + * @todo 支持chunked传输,优势: + * 可以将大文件分成小块,挨个传输,可以提高大文件成功率,当失败的时候,也只需要重传那小部分, + * 而不需要重头再传一次。另外断点续传也需要用chunked方式。 + */ + define('runtime/html5/transport',[ + 'base', + 'runtime/html5/runtime' + ], function( Base, Html5Runtime ) { + + var noop = Base.noop, + $ = Base.$; + + return Html5Runtime.register( 'Transport', { + init: function() { + this._status = 0; + this._response = null; + }, + + send: function() { + var owner = this.owner, + opts = this.options, + xhr = this._initAjax(), + blob = owner._blob, + server = opts.server, + formData, binary, fr; + + if ( opts.sendAsBinary ) { + server += opts.attachInfoToQuery !== false ? ((/\?/.test( server ) ? '&' : '?') + + $.param( owner._formData )) : ''; + + binary = blob.getSource(); + } else { + formData = new FormData(); + $.each( owner._formData, function( k, v ) { + formData.append( k, v ); + }); + + formData.append( opts.fileVal, blob.getSource(), + opts.filename || owner._formData.name || '' ); + } + + if ( opts.withCredentials && 'withCredentials' in xhr ) { + xhr.open( opts.method, server, true ); + xhr.withCredentials = true; + } else { + xhr.open( opts.method, server ); + } + + this._setRequestHeader( xhr, opts.headers ); + + if ( binary ) { + // 强制设置成 content-type 为文件流。 + xhr.overrideMimeType && + xhr.overrideMimeType('application/octet-stream'); + + // android直接发送blob会导致服务端接收到的是空文件。 + // bug详情。 + // https://code.google.com/p/android/issues/detail?id=39882 + // 所以先用fileReader读取出来再通过arraybuffer的方式发送。 + if ( Base.os.android ) { + fr = new FileReader(); + + fr.onload = function() { + xhr.send( this.result ); + fr = fr.onload = null; + }; + + fr.readAsArrayBuffer( binary ); + } else { + xhr.send( binary ); + } + } else { + xhr.send( formData ); + } + }, + + getResponse: function() { + return this._response; + }, + + getResponseAsJson: function() { + return this._parseJson( this._response ); + }, + + getResponseHeaders: function() { + return this._headers; + }, + + getStatus: function() { + return this._status; + }, + + abort: function() { + var xhr = this._xhr; + + if ( xhr ) { + xhr.upload.onprogress = noop; + xhr.onreadystatechange = noop; + xhr.abort(); + + this._xhr = xhr = null; + } + }, + + destroy: function() { + this.abort(); + }, + + _parseHeader: function(raw) { + var ret = {}; + + raw && raw.replace(/^([^\:]+):(.*)$/mg, function(_, key, value) { + ret[key.trim()] = value.trim(); + }); + + return ret; + }, + + _initAjax: function() { + var me = this, + xhr = new XMLHttpRequest(), + opts = this.options; + + if ( opts.withCredentials && !('withCredentials' in xhr) && + typeof XDomainRequest !== 'undefined' ) { + xhr = new XDomainRequest(); + } + + xhr.upload.onprogress = function( e ) { + var percentage = 0; + + if ( e.lengthComputable ) { + percentage = e.loaded / e.total; + } + + return me.trigger( 'progress', percentage ); + }; + + xhr.onreadystatechange = function() { + + if ( xhr.readyState !== 4 ) { + return; + } + + xhr.upload.onprogress = noop; + xhr.onreadystatechange = noop; + me._xhr = null; + me._status = xhr.status; + + var separator = '|', // 分隔符 + // 拼接的状态,在 widgets/upload.js 会有代码用到这个分隔符 + status = separator + xhr.status + + separator + xhr.statusText; + + if ( xhr.status >= 200 && xhr.status < 300 ) { + me._response = xhr.responseText; + me._headers = me._parseHeader(xhr.getAllResponseHeaders()); + return me.trigger('load'); + } else if ( xhr.status >= 500 && xhr.status < 600 ) { + me._response = xhr.responseText; + me._headers = me._parseHeader(xhr.getAllResponseHeaders()); + return me.trigger( 'error', 'server' + status ); + } + + + return me.trigger( 'error', me._status ? 'http' + status : 'abort' ); + }; + + me._xhr = xhr; + return xhr; + }, + + _setRequestHeader: function( xhr, headers ) { + $.each( headers, function( key, val ) { + xhr.setRequestHeader( key, val ); + }); + }, + + _parseJson: function( str ) { + var json; + + try { + json = JSON.parse( str ); + } catch ( ex ) { + json = {}; + } + + return json; + } + }); + }); + + /** + * @fileOverview Transport flash实现 + */ + define('runtime/html5/md5',[ + 'runtime/html5/runtime' + ], function( FlashRuntime ) { + + /* + * Fastest md5 implementation around (JKM md5) + * Credits: Joseph Myers + * + * @see http://www.myersdaily.org/joseph/javascript/md5-text.html + * @see http://jsperf.com/md5-shootout/7 + */ + + /* this function is much faster, + so if possible we use it. Some IEs + are the only ones I know of that + need the idiotic second function, + generated by an if clause. */ + var add32 = function (a, b) { + return (a + b) & 0xFFFFFFFF; + }, + + cmn = function (q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32((a << s) | (a >>> (32 - s)), b); + }, + + ff = function (a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); + }, + + gg = function (a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); + }, + + hh = function (a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); + }, + + ii = function (a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); + }, + + md5cycle = function (x, k) { + var a = x[0], + b = x[1], + c = x[2], + d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); + }, + + /* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ + md5blk = function (s) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + }, + + md5blk_array = function (a) { + var md5blks = [], + i; /* Andy King said do it this way. */ + + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + }, + + md51 = function (s) { + var n = s.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + return state; + }, + + md51_array = function (a) { + var n = a.length, + state = [1732584193, -271733879, -1732584194, 271733878], + i, + length, + tail, + tmp, + lo, + hi; + + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + + // Not sure if it is a bug, however IE10 will always produce a sub array of length 1 + // containing the last element of the parent array if the sub array specified starts + // beyond the length of the parent array - weird. + // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue + a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0); + + length = a.length; + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << ((i % 4) << 3); + } + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Beware that the final length might not fit in 32 bits so we take care of that + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + + md5cycle(state, tail); + + return state; + }, + + hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'], + + rhex = function (n) { + var s = '', + j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; + }, + + hex = function (x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(''); + }, + + md5 = function (s) { + return hex(md51(s)); + }, + + + + //////////////////////////////////////////////////////////////////////////// + + /** + * SparkMD5 OOP implementation. + * + * Use this class to perform an incremental md5, otherwise use the + * static methods instead. + */ + SparkMD5 = function () { + // call reset to init the instance + this.reset(); + }; + + + // In some cases the fast add32 function cannot be used.. + if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') { + add32 = function (x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + }; + } + + + /** + * Appends a string. + * A conversion will be applied if an utf8 string is detected. + * + * @param {String} str The string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.append = function (str) { + // converts the string to utf8 bytes if necessary + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + // then append as binary + this.appendBinary(str); + + return this; + }; + + /** + * Appends a binary string. + * + * @param {String} contents The binary string to be appended + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.appendBinary = function (contents) { + this._buff += contents; + this._length += contents.length; + + var length = this._buff.length, + i; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._state, md5blk(this._buff.substring(i - 64, i))); + } + + this._buff = this._buff.substr(i - 64); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + i, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._state : hex(this._state); + + this.reset(); + + return ret; + }; + + /** + * Finish the final calculation based on the tail. + * + * @param {Array} tail The tail (will be modified) + * @param {Number} length The length of the remaining buffer + */ + SparkMD5.prototype._finish = function (tail, length) { + var i = length, + tmp, + lo, + hi; + + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(this._state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + + // Do the final computation based on the tail and length + // Beware that the final length may not fit in 32 bits so we take care of that + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + + tail[14] = lo; + tail[15] = hi; + md5cycle(this._state, tail); + }; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5} The instance itself + */ + SparkMD5.prototype.reset = function () { + this._buff = ""; + this._length = 0; + this._state = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other aditional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.prototype.destroy = function () { + delete this._state; + delete this._buff; + delete this._length; + }; + + + /** + * Performs the md5 hash on a string. + * A conversion will be applied if utf8 string is detected. + * + * @param {String} str The string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hash = function (str, raw) { + // converts the string to utf8 bytes if necessary + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + + var hash = md51(str); + + return !!raw ? hash : hex(hash); + }; + + /** + * Performs the md5 hash on a binary string. + * + * @param {String} content The binary string + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.hashBinary = function (content, raw) { + var hash = md51(content); + + return !!raw ? hash : hex(hash); + }; + + /** + * SparkMD5 OOP implementation for array buffers. + * + * Use this class to perform an incremental md5 ONLY for array buffers. + */ + SparkMD5.ArrayBuffer = function () { + // call reset to init the instance + this.reset(); + }; + + //////////////////////////////////////////////////////////////////////////// + + /** + * Appends an array buffer. + * + * @param {ArrayBuffer} arr The array to be appended + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.append = function (arr) { + // TODO: we could avoid the concatenation here but the algorithm would be more complex + // if you find yourself needing extra performance, please make a PR. + var buff = this._concatArrayBuffer(this._buff, arr), + length = buff.length, + i; + + this._length += arr.byteLength; + + for (i = 64; i <= length; i += 64) { + md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i))); + } + + // Avoids IE10 weirdness (documented above) + this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0); + + return this; + }; + + /** + * Finishes the incremental computation, reseting the internal state and + * returning the result. + * Use the raw parameter to obtain the raw result instead of the hex one. + * + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.prototype.end = function (raw) { + var buff = this._buff, + length = buff.length, + tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i, + ret; + + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << ((i % 4) << 3); + } + + this._finish(tail, length); + ret = !!raw ? this._state : hex(this._state); + + this.reset(); + + return ret; + }; + + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + + /** + * Resets the internal state of the computation. + * + * @return {SparkMD5.ArrayBuffer} The instance itself + */ + SparkMD5.ArrayBuffer.prototype.reset = function () { + this._buff = new Uint8Array(0); + this._length = 0; + this._state = [1732584193, -271733879, -1732584194, 271733878]; + + return this; + }; + + /** + * Releases memory used by the incremental buffer and other aditional + * resources. If you plan to use the instance again, use reset instead. + */ + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + + /** + * Concats two array buffers, returning a new one. + * + * @param {ArrayBuffer} first The first array buffer + * @param {ArrayBuffer} second The second array buffer + * + * @return {ArrayBuffer} The new array buffer + */ + SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) { + var firstLength = first.length, + result = new Uint8Array(firstLength + second.byteLength); + + result.set(first); + result.set(new Uint8Array(second), firstLength); + + return result; + }; + + /** + * Performs the md5 hash on an array buffer. + * + * @param {ArrayBuffer} arr The array buffer + * @param {Boolean} raw True to get the raw result, false to get the hex result + * + * @return {String|Array} The result + */ + SparkMD5.ArrayBuffer.hash = function (arr, raw) { + var hash = md51_array(new Uint8Array(arr)); + + return !!raw ? hash : hex(hash); + }; + + return FlashRuntime.register( 'Md5', { + init: function() { + // do nothing. + }, + + loadFromBlob: function( file ) { + var blob = file.getSource(), + chunkSize = 2 * 1024 * 1024, + chunks = Math.ceil( blob.size / chunkSize ), + chunk = 0, + owner = this.owner, + spark = new SparkMD5.ArrayBuffer(), + me = this, + blobSlice = blob.mozSlice || blob.webkitSlice || blob.slice, + loadNext, fr; + + fr = new FileReader(); + + loadNext = function() { + var start, end; + + start = chunk * chunkSize; + end = Math.min( start + chunkSize, blob.size ); + + fr.onload = function( e ) { + spark.append( e.target.result ); + owner.trigger( 'progress', { + total: file.size, + loaded: end + }); + }; + + fr.onloadend = function() { + fr.onloadend = fr.onload = null; + + if ( ++chunk < chunks ) { + setTimeout( loadNext, 1 ); + } else { + setTimeout(function(){ + owner.trigger('load'); + me.result = spark.end(); + loadNext = file = blob = spark = null; + owner.trigger('complete'); + }, 50 ); + } + }; + + fr.readAsArrayBuffer( blobSlice.call( blob, start, end ) ); + }; + + loadNext(); + }, + + getResult: function() { + return this.result; + } + }); + }); + /** + * @fileOverview 完全版本。 + */ + define('preset/all',[ + 'base', + + // widgets + 'widgets/filednd', + 'widgets/filepaste', + 'widgets/filepicker', + 'widgets/image', + 'widgets/queue', + 'widgets/runtime', + 'widgets/upload', + 'widgets/validator', + 'widgets/md5', + + // runtimes + // html5 + 'runtime/html5/blob', + 'runtime/html5/dnd', + 'runtime/html5/filepaste', + 'runtime/html5/filepicker', + 'runtime/html5/imagemeta/exif', + 'runtime/html5/androidpatch', + 'runtime/html5/image', + 'runtime/html5/transport', + 'runtime/html5/md5', + + // flash + // 'runtime/flash/filepicker', + // 'runtime/flash/image', + // 'runtime/flash/transport', + // 'runtime/flash/blob', + // 'runtime/flash/md5' + ], function( Base ) { + return Base; + }); + + /** + * @fileOverview 日志组件,主要用来收集错误信息,可以帮助 webuploader 更好的定位问题和发展。 + * + * 如果您不想要启用此功能,请在打包的时候去掉 log 模块。 + * + * 或者可以在初始化的时候通过 options.disableWidgets 属性禁用。 + * + * 如: + * WebUploader.create({ + * ... + * + * disableWidgets: 'log', + * + * ... + * }) + */ + define('widgets/log',[ + 'base', + 'uploader', + 'widgets/widget' + ], function( Base, Uploader ) { + var $ = Base.$, + logUrl = ' http://static.tieba.baidu.com/tb/pms/img/st.gif??', + product = (location.hostname || location.host || 'protected').toLowerCase(), + + // 只针对 baidu 内部产品用户做统计功能。 + enable = product && /baidu/i.exec(product), + base; + + if (!enable) { + return; + } + + base = { + dv: 3, + master: 'webuploader', + online: /test/.exec(product) ? 0 : 1, + module: '', + product: product, + type: 0 + }; + + function send(data) { + var obj = $.extend({}, base, data), + url = logUrl.replace(/^(.*)\?/, '$1' + $.param( obj )), + image = new Image(); + + image.src = url; + } + + return Uploader.register({ + name: 'log', + + init: function() { + var owner = this.owner, + count = 0, + size = 0; + + owner + .on('error', function(code) { + send({ + type: 2, + c_error_code: code + }); + }) + .on('uploadError', function(file, reason) { + send({ + type: 2, + c_error_code: 'UPLOAD_ERROR', + c_reason: '' + reason + }); + }) + .on('uploadComplete', function(file) { + count++; + size += file.size; + }). + on('uploadFinished', function() { + send({ + c_count: count, + c_size: size + }); + count = size = 0; + }); + + send({ + c_usage: 1 + }); + } + }); + }); + /** + * @fileOverview Uploader上传类 + */ + define('webuploader',[ + 'preset/all', + 'widgets/log' + ], function( preset ) { + return preset; + }); + return require('webuploader'); +}); diff --git a/public/static/plugs/ueditor/ueditor.all.js b/public/static/plugs/ueditor/ueditor.all.js index 8c1501b..a0156c6 100644 --- a/public/static/plugs/ueditor/ueditor.all.js +++ b/public/static/plugs/ueditor/ueditor.all.js @@ -5,13280 +5,16550 @@ (function(){ // editor.js -UEDITOR_CONFIG = window.UEDITOR_CONFIG || {}; + UEDITOR_CONFIG = window.UEDITOR_CONFIG || {}; -var baidu = window.baidu || {}; + var baidu = window.baidu || {}; -window.baidu = baidu; + window.baidu = baidu; -window.UE = baidu.editor = { - plugins: {}, - commands: {}, - instants: {}, - I18N: {}, - _customizeUI: {}, - version: "3.5.0" -}; -var dom = (UE.dom = {}); + window.UE = baidu.editor = { + plugins: {}, + commands: {}, + instants: {}, + I18N: {}, + _customizeUI: {}, + version: "4.1.0", + constants: { + STATEFUL: { + DISABLED: -1, + OFF: 0, + ON: 1, + }, + } + }; + var dom = (UE.dom = {}); // core/browser.js -/** - * 浏览器判断模块 - * @file - * @module UE.browser - * @since 1.2.6.1 - */ - -/** - * 提供浏览器检测的模块 - * @unfile - * @module UE.browser - */ -var browser = (UE.browser = (function() { - var agent = navigator.userAgent.toLowerCase(), - opera = window.opera, - browser = { - /** - * @property {boolean} ie 检测当前浏览器是否为IE - * @example - * ```javascript - * if ( UE.browser.ie ) { - * console.log( '当前浏览器是IE' ); - * } - * ``` - */ - ie: /(msie\s|trident.*rv:)([\w.]+)/i.test(agent), - - /** - * @property {boolean} opera 检测当前浏览器是否为Opera - * @example - * ```javascript - * if ( UE.browser.opera ) { - * console.log( '当前浏览器是Opera' ); - * } - * ``` - */ - opera: !!opera && opera.version, - - /** - * @property {boolean} webkit 检测当前浏览器是否是webkit内核的浏览器 - * @example - * ```javascript - * if ( UE.browser.webkit ) { - * console.log( '当前浏览器是webkit内核浏览器' ); - * } - * ``` - */ - webkit: agent.indexOf(" applewebkit/") > -1, - - /** - * @property {boolean} mac 检测当前浏览器是否是运行在mac平台下 - * @example - * ```javascript - * if ( UE.browser.mac ) { - * console.log( '当前浏览器运行在mac平台下' ); - * } - * ``` - */ - mac: agent.indexOf("macintosh") > -1, - - /** - * @property {boolean} quirks 检测当前浏览器是否处于“怪异模式”下 - * @example - * ```javascript - * if ( UE.browser.quirks ) { - * console.log( '当前浏览器运行处于“怪异模式”' ); - * } - * ``` - */ - quirks: document.compatMode == "BackCompat" - }; - - /** - * @property {boolean} gecko 检测当前浏览器内核是否是gecko内核 - * @example - * ```javascript - * if ( UE.browser.gecko ) { - * console.log( '当前浏览器内核是gecko内核' ); - * } - * ``` - */ - browser.gecko = - navigator.product == "Gecko" && - !browser.webkit && - !browser.opera && - !browser.ie; - - var version = 0; - - // Internet Explorer 6.0+ - if (browser.ie) { - var v1 = agent.match(/(?:msie\s([\w.]+))/); - var v2 = agent.match(/(?:trident.*rv:([\w.]+))/); - if (v1 && v2 && v1[1] && v2[1]) { - version = Math.max(v1[1] * 1, v2[1] * 1); - } else if (v1 && v1[1]) { - version = v1[1] * 1; - } else if (v2 && v2[1]) { - version = v2[1] * 1; - } else { - version = 0; - } - - browser.ie11Compat = document.documentMode == 11; /** - * @property { boolean } ie9Compat 检测浏览器模式是否为 IE9 兼容模式 - * @warning 如果浏览器不是IE, 则该值为undefined - * @example - * ```javascript - * if ( UE.browser.ie9Compat ) { - * console.log( '当前浏览器运行在IE9兼容模式下' ); - * } - * ``` - */ - browser.ie9Compat = document.documentMode == 9; - - /** - * @property { boolean } ie8 检测浏览器是否是IE8浏览器 - * @warning 如果浏览器不是IE, 则该值为undefined - * @example - * ```javascript - * if ( UE.browser.ie8 ) { - * console.log( '当前浏览器是IE8浏览器' ); - * } - * ``` - */ - browser.ie8 = !!document.documentMode; - - /** - * @property { boolean } ie8Compat 检测浏览器模式是否为 IE8 兼容模式 - * @warning 如果浏览器不是IE, 则该值为undefined - * @example - * ```javascript - * if ( UE.browser.ie8Compat ) { - * console.log( '当前浏览器运行在IE8兼容模式下' ); - * } - * ``` - */ - browser.ie8Compat = document.documentMode == 8; - - /** - * @property { boolean } ie7Compat 检测浏览器模式是否为 IE7 兼容模式 - * @warning 如果浏览器不是IE, 则该值为undefined - * @example - * ```javascript - * if ( UE.browser.ie7Compat ) { - * console.log( '当前浏览器运行在IE7兼容模式下' ); - * } - * ``` - */ - browser.ie7Compat = - (version == 7 && !document.documentMode) || document.documentMode == 7; - - /** - * @property { boolean } ie6Compat 检测浏览器模式是否为 IE6 模式 或者怪异模式 - * @warning 如果浏览器不是IE, 则该值为undefined - * @example - * ```javascript - * if ( UE.browser.ie6Compat ) { - * console.log( '当前浏览器运行在IE6模式或者怪异模式下' ); - * } - * ``` - */ - browser.ie6Compat = version < 7 || browser.quirks; - - browser.ie9above = version > 8; - - browser.ie9below = version < 9; - - browser.ie11above = version > 10; - - browser.ie11below = version < 11; - } - - // Gecko. - if (browser.gecko) { - var geckoRelease = agent.match(/rv:([\d\.]+)/); - if (geckoRelease) { - geckoRelease = geckoRelease[1].split("."); - version = - geckoRelease[0] * 10000 + - (geckoRelease[1] || 0) * 100 + - (geckoRelease[2] || 0) * 1; - } - } - - /** - * @property { Number } chrome 检测当前浏览器是否为Chrome, 如果是,则返回Chrome的大版本号 - * @warning 如果浏览器不是chrome, 则该值为undefined - * @example - * ```javascript - * if ( UE.browser.chrome ) { - * console.log( '当前浏览器是Chrome' ); - * } - * ``` + * 浏览器判断模块 + * @file + * @module UE.browser + * @since 1.2.6.1 */ - if (/chrome\/(\d+\.\d)/i.test(agent)) { - browser.chrome = +RegExp["\x241"]; - } - /** - * @property { Number } safari 检测当前浏览器是否为Safari, 如果是,则返回Safari的大版本号 - * @warning 如果浏览器不是safari, 则该值为undefined - * @example - * ```javascript - * if ( UE.browser.safari ) { - * console.log( '当前浏览器是Safari' ); - * } - * ``` + /** + * 提供浏览器检测的模块 + * @unfile + * @module UE.browser */ - if ( - /(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && - !/chrome/i.test(agent) - ) { - browser.safari = +(RegExp["\x241"] || RegExp["\x242"]); - } + var browser = (UE.browser = (function () { + var agent = navigator.userAgent.toLowerCase(), + opera = window.opera, + browser = { + /** + * @property {boolean} ie 检测当前浏览器是否为IE + * @example + * ```javascript + * if ( UE.browser.ie ) { + * console.log( '当前浏览器是IE' ); + * } + * ``` + */ + ie: /(msie\s|trident.*rv:)([\w.]+)/i.test(agent), - // Opera 9.50+ - if (browser.opera) version = parseFloat(opera.version()); + /** + * @property {boolean} opera 检测当前浏览器是否为Opera + * @example + * ```javascript + * if ( UE.browser.opera ) { + * console.log( '当前浏览器是Opera' ); + * } + * ``` + */ + opera: !!opera && opera.version, - // WebKit 522+ (Safari 3+) - if (browser.webkit) - version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1]); + /** + * @property {boolean} webkit 检测当前浏览器是否是webkit内核的浏览器 + * @example + * ```javascript + * if ( UE.browser.webkit ) { + * console.log( '当前浏览器是webkit内核浏览器' ); + * } + * ``` + */ + webkit: agent.indexOf(" applewebkit/") > -1, - /** - * @property { Number } version 检测当前浏览器版本号 - * @remind - *
    - *
  • IE系列返回值为5,6,7,8,9,10等
  • - *
  • gecko系列会返回10900,158900等
  • - *
  • webkit系列会返回其build号 (如 522等)
  • - *
- * @example - * ```javascript - * console.log( '当前浏览器版本号是: ' + UE.browser.version ); - * ``` - */ - browser.version = version; + /** + * @property {boolean} mac 检测当前浏览器是否是运行在mac平台下 + * @example + * ```javascript + * if ( UE.browser.mac ) { + * console.log( '当前浏览器运行在mac平台下' ); + * } + * ``` + */ + mac: agent.indexOf("macintosh") > -1, - /** - * @property { boolean } isCompatible 检测当前浏览器是否能够与UEditor良好兼容 - * @example - * ```javascript - * if ( UE.browser.isCompatible ) { - * console.log( '浏览器与UEditor能够良好兼容' ); - * } - * ``` - */ - browser.isCompatible = - !browser.mobile && - ((browser.ie && version >= 6) || - (browser.gecko && version >= 10801) || - (browser.opera && version >= 9.5) || - (browser.air && version >= 1) || - (browser.webkit && version >= 522) || - false); - return browser; -})()); + /** + * @property {boolean} quirks 检测当前浏览器是否处于“怪异模式”下 + * @example + * ```javascript + * if ( UE.browser.quirks ) { + * console.log( '当前浏览器运行处于“怪异模式”' ); + * } + * ``` + */ + quirks: document.compatMode == "BackCompat" + }; + + /** + * @property {boolean} gecko 检测当前浏览器内核是否是gecko内核 + * @example + * ```javascript + * if ( UE.browser.gecko ) { + * console.log( '当前浏览器内核是gecko内核' ); + * } + * ``` + */ + browser.gecko = + navigator.product == "Gecko" && + !browser.webkit && + !browser.opera && + !browser.ie; + + var version = 0; + + // Internet Explorer 6.0+ + if (browser.ie) { + var v1 = agent.match(/(?:msie\s([\w.]+))/); + var v2 = agent.match(/(?:trident.*rv:([\w.]+))/); + if (v1 && v2 && v1[1] && v2[1]) { + version = Math.max(v1[1] * 1, v2[1] * 1); + } else if (v1 && v1[1]) { + version = v1[1] * 1; + } else if (v2 && v2[1]) { + version = v2[1] * 1; + } else { + version = 0; + } + + browser.ie11Compat = document.documentMode == 11; + /** + * @property { boolean } ie9Compat 检测浏览器模式是否为 IE9 兼容模式 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie9Compat ) { + * console.log( '当前浏览器运行在IE9兼容模式下' ); + * } + * ``` + */ + browser.ie9Compat = document.documentMode == 9; + + /** + * @property { boolean } ie8 检测浏览器是否是IE8浏览器 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie8 ) { + * console.log( '当前浏览器是IE8浏览器' ); + * } + * ``` + */ + browser.ie8 = !!document.documentMode; + + /** + * @property { boolean } ie8Compat 检测浏览器模式是否为 IE8 兼容模式 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie8Compat ) { + * console.log( '当前浏览器运行在IE8兼容模式下' ); + * } + * ``` + */ + browser.ie8Compat = document.documentMode == 8; + + /** + * @property { boolean } ie7Compat 检测浏览器模式是否为 IE7 兼容模式 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie7Compat ) { + * console.log( '当前浏览器运行在IE7兼容模式下' ); + * } + * ``` + */ + browser.ie7Compat = + (version == 7 && !document.documentMode) || document.documentMode == 7; + + /** + * @property { boolean } ie6Compat 检测浏览器模式是否为 IE6 模式 或者怪异模式 + * @warning 如果浏览器不是IE, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.ie6Compat ) { + * console.log( '当前浏览器运行在IE6模式或者怪异模式下' ); + * } + * ``` + */ + browser.ie6Compat = version < 7 || browser.quirks; + + browser.ie9above = version > 8; + + browser.ie9below = version < 9; + + browser.ie11above = version > 10; + + browser.ie11below = version < 11; + } + + // Gecko. + if (browser.gecko) { + var geckoRelease = agent.match(/rv:([\d\.]+)/); + if (geckoRelease) { + geckoRelease = geckoRelease[1].split("."); + version = + geckoRelease[0] * 10000 + + (geckoRelease[1] || 0) * 100 + + (geckoRelease[2] || 0) * 1; + } + } + + /** + * @property { Number } chrome 检测当前浏览器是否为Chrome, 如果是,则返回Chrome的大版本号 + * @warning 如果浏览器不是chrome, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.chrome ) { + * console.log( '当前浏览器是Chrome' ); + * } + * ``` + */ + if (/chrome\/(\d+\.\d)/i.test(agent)) { + browser.chrome = +RegExp["\x241"]; + } + + /** + * @property { Number } safari 检测当前浏览器是否为Safari, 如果是,则返回Safari的大版本号 + * @warning 如果浏览器不是safari, 则该值为undefined + * @example + * ```javascript + * if ( UE.browser.safari ) { + * console.log( '当前浏览器是Safari' ); + * } + * ``` + */ + if ( + /(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && + !/chrome/i.test(agent) + ) { + browser.safari = +(RegExp["\x241"] || RegExp["\x242"]); + } + + // Opera 9.50+ + if (browser.opera) version = parseFloat(opera.version()); + + // WebKit 522+ (Safari 3+) + if (browser.webkit) + version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1]); + + /** + * @property { Number } version 检测当前浏览器版本号 + * @remind + *
    + *
  • IE系列返回值为5,6,7,8,9,10等
  • + *
  • gecko系列会返回10900,158900等
  • + *
  • webkit系列会返回其build号 (如 522等)
  • + *
+ * @example + * ```javascript + * console.log( '当前浏览器版本号是: ' + UE.browser.version ); + * ``` + */ + browser.version = version; + + /** + * @property { boolean } isCompatible 检测当前浏览器是否能够与UEditor良好兼容 + * @example + * ```javascript + * if ( UE.browser.isCompatible ) { + * console.log( '浏览器与UEditor能够良好兼容' ); + * } + * ``` + */ + browser.isCompatible = + !browser.mobile && + ((browser.ie && version >= 6) || + (browser.gecko && version >= 10801) || + (browser.opera && version >= 9.5) || + (browser.air && version >= 1) || + (browser.webkit && version >= 522) || + false); + return browser; + })()); //快捷方式 -var ie = browser.ie, - webkit = browser.webkit, - gecko = browser.gecko, - opera = browser.opera; + var ie = browser.ie, + webkit = browser.webkit, + gecko = browser.gecko, + opera = browser.opera; // core/utils.js -/** - * 工具函数包 - * @file - * @module UE.utils - * @since 1.2.6.1 - */ - -/** - * UEditor封装使用的静态工具函数 - * @module UE.utils - * @unfile - */ - -var utils = (UE.utils = { /** - * 用给定的迭代器遍历对象 - * @method each - * @param { Object } obj 需要遍历的对象 - * @param { Function } iterator 迭代器, 该方法接受两个参数, 第一个参数是当前所处理的value, 第二个参数是当前遍历对象的key - * @example - * ```javascript - * var demoObj = { - * key1: 1, - * key2: 2 - * }; - * - * //output: key1: 1, key2: 2 - * UE.utils.each( demoObj, funciton ( value, key ) { - * - * console.log( key + ":" + value ); - * - * } ); - * ``` + * 工具函数包 + * @file + * @module UE.utils + * @since 1.2.6.1 */ /** - * 用给定的迭代器遍历数组或类数组对象 - * @method each - * @param { Array } array 需要遍历的数组或者类数组 - * @param { Function } iterator 迭代器, 该方法接受两个参数, 第一个参数是当前所处理的value, 第二个参数是当前遍历对象的key - * @example - * ```javascript - * var divs = document.getElmentByTagNames( "div" ); - * - * //output: 0: DIV, 1: DIV ... - * UE.utils.each( divs, funciton ( value, key ) { - * - * console.log( key + ":" + value.tagName ); - * - * } ); - * ``` - */ - each: function (obj, iterator, context) { - if (obj == null) return; - if (obj.length === +obj.length) { - for (var i = 0, l = obj.length; i < l; i++) { - if (iterator.call(context, obj[i], i, obj) === false) return false; - } - } else { - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - if (iterator.call(context, obj[key], key, obj) === false) - return false; - } - } - } - }, - - /** - * 以给定对象作为原型创建一个新对象 - * @method makeInstance - * @param { Object } protoObject 该对象将作为新创建对象的原型 - * @return { Object } 新的对象, 该对象的原型是给定的protoObject对象 - * @example - * ```javascript - * - * var protoObject = { sayHello: function () { console.log('Hello UEditor!'); } }; - * - * var newObject = UE.utils.makeInstance( protoObject ); - * //output: Hello UEditor! - * newObject.sayHello(); - * ``` - */ - makeInstance: function (obj) { - var noop = new Function(); - noop.prototype = obj; - obj = new noop(); - noop.prototype = null; - return obj; - }, - - isObject: function (item) { - return (item && typeof item === 'object' && !Array.isArray(item)); - }, - - merge: function (target, source) { - var output = Object.assign({}, target); - if (this.isObject(target) && this.isObject(source)) { - Object.keys(source).forEach(key => { - if (this.isObject(source[key])) { - if (!(key in target)) { - Object.assign(output, {[key]: source[key]}); - } else { - output[key] = this.merge(target[key], source[key]); - } - } else { - Object.assign(output, {[key]: source[key]}); - } - }); - } - return output; - }, - - /** - * 将source对象中的属性扩展到target对象上, 根据指定的isKeepTarget值决定是否保留目标对象中与 - * 源对象属性名相同的属性值。 - * @method extend - * @param { Object } target 目标对象, 新的属性将附加到该对象上 - * @param { Object } source 源对象, 该对象的属性会被附加到target对象上 - * @param { Boolean } isKeepTarget 是否保留目标对象中与源对象中属性名相同的属性 - * @return { Object } 返回target对象 - * @example - * ```javascript - * - * var target = { name: 'target', sex: 1 }, - * source = { name: 'source', age: 17 }; - * - * UE.utils.extend( target, source, true ); - * - * //output: { name: 'target', sex: 1, age: 17 } - * console.log( target ); - * - * ``` - */ - extend: function (t, s, b) { - if (s) { - for (var k in s) { - if (!b || !t.hasOwnProperty(k)) { - t[k] = s[k]; - } - } - } - return t; - }, - - /** - * 将给定的多个对象的属性复制到目标对象target上 - * @method extend2 - * @remind 该方法将强制把源对象上的属性复制到target对象上 - * @remind 该方法支持两个及以上的参数, 从第二个参数开始, 其属性都会被复制到第一个参数上。 如果遇到同名的属性, - * 将会覆盖掉之前的值。 - * @param { Object } target 目标对象, 新的属性将附加到该对象上 - * @param { Object... } source 源对象, 支持多个对象, 该对象的属性会被附加到target对象上 - * @return { Object } 返回target对象 - * @example - * ```javascript - * - * var target = {}, - * source1 = { name: 'source', age: 17 }, - * source2 = { title: 'dev' }; - * - * UE.utils.extend2( target, source1, source2 ); - * - * //output: { name: 'source', age: 17, title: 'dev' } - * console.log( target ); - * - * ``` - */ - extend2: function (t) { - var a = arguments; - for (var i = 1; i < a.length; i++) { - var x = a[i]; - for (var k in x) { - if (!t.hasOwnProperty(k)) { - t[k] = x[k]; - } - } - } - return t; - }, - - /** - * 模拟继承机制, 使得subClass继承自superClass - * @method inherits - * @param { Object } subClass 子类对象 - * @param { Object } superClass 超类对象 - * @warning 该方法只能让subClass继承超类的原型, subClass对象自身的属性和方法不会被继承 - * @return { Object } 继承superClass后的子类对象 - * @example - * ```javascript - * function SuperClass(){ - * this.name = "小李"; - * } - * - * SuperClass.prototype = { - * hello:function(str){ - * console.log(this.name + str); - * } - * } - * - * function SubClass(){ - * this.name = "小张"; - * } - * - * UE.utils.inherits(SubClass,SuperClass); - * - * var sub = new SubClass(); - * //output: '小张早上好! - * sub.hello("早上好!"); - * ``` - */ - inherits: function (subClass, superClass) { - var oldP = subClass.prototype, - newP = utils.makeInstance(superClass.prototype); - utils.extend(newP, oldP, true); - subClass.prototype = newP; - return (newP.constructor = subClass); - }, - - /** - * 用指定的context对象作为函数fn的上下文 - * @method bind - * @param { Function } fn 需要绑定上下文的函数对象 - * @param { Object } content 函数fn新的上下文对象 - * @return { Function } 一个新的函数, 该函数作为原始函数fn的代理, 将完成fn的上下文调换工作。 - * @example - * ```javascript - * - * var name = 'window', - * newTest = null; - * - * function test () { - * console.log( this.name ); - * } - * - * newTest = UE.utils.bind( test, { name: 'object' } ); - * - * //output: object - * newTest(); - * - * //output: window - * test(); - * - * ``` - */ - bind: function (fn, context) { - return function () { - return fn.apply(context, arguments); - }; - }, - - /** - * 创建延迟指定时间后执行的函数fn - * @method defer - * @param { Function } fn 需要延迟执行的函数对象 - * @param { int } delay 延迟的时间, 单位是毫秒 - * @warning 该方法的时间控制是不精确的,仅仅只能保证函数的执行是在给定的时间之后, - * 而不能保证刚好到达延迟时间时执行。 - * @return { Function } 目标函数fn的代理函数, 只有执行该函数才能起到延时效果 - * @example - * ```javascript - * var start = 0; - * - * function test(){ - * console.log( new Date() - start ); - * } - * - * var testDefer = UE.utils.defer( test, 1000 ); - * // - * start = new Date(); - * //output: (大约在1000毫秒之后输出) 1000 - * testDefer(); - * ``` + * UEditor封装使用的静态工具函数 + * @module UE.utils + * @unfile */ - /** - * 创建延迟指定时间后执行的函数fn, 如果在延迟时间内再次执行该方法, 将会根据指定的exclusion的值, - * 决定是否取消前一次函数的执行, 如果exclusion的值为true, 则取消执行,反之,将继续执行前一个方法。 - * @method defer - * @param { Function } fn 需要延迟执行的函数对象 - * @param { int } delay 延迟的时间, 单位是毫秒 - * @param { Boolean } exclusion 如果在延迟时间内再次执行该函数,该值将决定是否取消执行前一次函数的执行, - * 值为true表示取消执行, 反之则将在执行前一次函数之后才执行本次函数调用。 - * @warning 该方法的时间控制是不精确的,仅仅只能保证函数的执行是在给定的时间之后, - * 而不能保证刚好到达延迟时间时执行。 - * @return { Function } 目标函数fn的代理函数, 只有执行该函数才能起到延时效果 - * @example - * ```javascript - * - * function test(){ - * console.log(1); - * } - * - * var testDefer = UE.utils.defer( test, 1000, true ); - * - * //output: (两次调用仅有一次输出) 1 - * testDefer(); - * testDefer(); - * ``` - */ - defer: function (fn, delay, exclusion) { - var timerID; - return function () { - if (exclusion) { - clearTimeout(timerID); - } - timerID = setTimeout(fn, delay); - }; - }, + var utils = (UE.utils = { + /** + * 用给定的迭代器遍历对象 + * @method each + * @param { Object } obj 需要遍历的对象 + * @param { Function } iterator 迭代器, 该方法接受两个参数, 第一个参数是当前所处理的value, 第二个参数是当前遍历对象的key + * @example + * ```javascript + * var demoObj = { + * key1: 1, + * key2: 2 + * }; + * + * //output: key1: 1, key2: 2 + * UE.utils.each( demoObj, funciton ( value, key ) { + * + * console.log( key + ":" + value ); + * + * } ); + * ``` + */ - /** - * 获取元素item在数组array中首次出现的位置, 如果未找到item, 则返回-1 - * @method indexOf - * @remind 该方法的匹配过程使用的是恒等“===” - * @param { Array } array 需要查找的数组对象 - * @param { * } item 需要在目标数组中查找的值 - * @return { int } 返回item在目标数组array中首次出现的位置, 如果在数组中未找到item, 则返回-1 - * @example - * ```javascript - * var item = 1, - * arr = [ 3, 4, 6, 8, 1, 1, 2 ]; - * - * //output: 4 - * console.log( UE.utils.indexOf( arr, item ) ); - * ``` - */ - - /** - * 获取元素item数组array中首次出现的位置, 如果未找到item, 则返回-1。通过start的值可以指定搜索的起始位置。 - * @method indexOf - * @remind 该方法的匹配过程使用的是恒等“===” - * @param { Array } array 需要查找的数组对象 - * @param { * } item 需要在目标数组中查找的值 - * @param { int } start 搜索的起始位置 - * @return { int } 返回item在目标数组array中的start位置之后首次出现的位置, 如果在数组中未找到item, 则返回-1 - * @example - * ```javascript - * var item = 1, - * arr = [ 3, 4, 6, 8, 1, 2, 8, 3, 2, 1, 1, 4 ]; - * - * //output: 9 - * console.log( UE.utils.indexOf( arr, item, 5 ) ); - * ``` - */ - indexOf: function (array, item, start) { - var index = -1; - start = this.isNumber(start) ? start : 0; - this.each(array, function (v, i) { - if (i >= start && v === item) { - index = i; - return false; - } - }); - return index; - }, - - /** - * 移除数组array中所有的元素item - * @method removeItem - * @param { Array } array 要移除元素的目标数组 - * @param { * } item 将要被移除的元素 - * @remind 该方法的匹配过程使用的是恒等“===” - * @example - * ```javascript - * var arr = [ 4, 5, 7, 1, 3, 4, 6 ]; - * - * UE.utils.removeItem( arr, 4 ); - * //output: [ 5, 7, 1, 3, 6 ] - * console.log( arr ); - * - * ``` - */ - removeItem: function (array, item) { - for (var i = 0, l = array.length; i < l; i++) { - if (array[i] === item) { - array.splice(i, 1); - i--; - } - } - }, - - /** - * 删除字符串str的首尾空格 - * @method trim - * @param { String } str 需要删除首尾空格的字符串 - * @return { String } 删除了首尾的空格后的字符串 - * @example - * ```javascript - * - * var str = " UEdtior "; - * - * //output: 9 - * console.log( str.length ); - * - * //output: 7 - * console.log( UE.utils.trim( " UEdtior " ).length ); - * - * //output: 9 - * console.log( str.length ); - * - * ``` - */ - trim: function (str) { - return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, ""); - }, - - /** - * 将字符串str以','分隔成数组后,将该数组转换成哈希对象, 其生成的hash对象的key为数组中的元素, value为1 - * @method listToMap - * @warning 该方法在生成的hash对象中,会为每一个key同时生成一个另一个全大写的key。 - * @param { String } str 该字符串将被以','分割为数组, 然后进行转化 - * @return { Object } 转化之后的hash对象 - * @example - * ```javascript - * - * //output: Object {UEdtior: 1, UEDTIOR: 1, Hello: 1, HELLO: 1} - * console.log( UE.utils.listToMap( 'UEdtior,Hello' ) ); - * - * ``` - */ - - /** - * 将字符串数组转换成哈希对象, 其生成的hash对象的key为数组中的元素, value为1 - * @method listToMap - * @warning 该方法在生成的hash对象中,会为每一个key同时生成一个另一个全大写的key。 - * @param { Array } arr 字符串数组 - * @return { Object } 转化之后的hash对象 - * @example - * ```javascript - * - * //output: Object {UEdtior: 1, UEDTIOR: 1, Hello: 1, HELLO: 1} - * console.log( UE.utils.listToMap( [ 'UEdtior', 'Hello' ] ) ); - * - * ``` - */ - listToMap: function (list) { - if (!list) return {}; - list = utils.isArray(list) ? list : list.split(","); - for (var i = 0, ci, obj = {}; (ci = list[i++]);) { - obj[ci.toUpperCase()] = obj[ci] = 1; - } - return obj; - }, - - /** - * 将str中的html符号转义,将转义“',&,<,",>,”,“”七个字符 - * @method unhtml - * @param { String } str 需要转义的字符串 - * @return { String } 转义后的字符串 - * @example - * ```javascript - * var html = '&'; - * - * //output: <body>&</body> - * console.log( UE.utils.unhtml( html ) ); - * - * ``` - */ - unhtml: function (str, reg) { - return str - ? str.replace( - reg || /[&<">'](?:(amp|lt|ldquo|rdquo|quot|gt|#39|nbsp|#\d+);)?/g, - function (a, b) { - if (b) { - return a; - } else { - return { - "<": "<", - "&": "&", - '"': """, - "“": "“", - "”": "”", - ">": ">", - "'": "'" - }[a]; - } - } - ) - : ""; - }, - - /** - * 将str中的转义字符还原成html字符 - * @see UE.utils.unhtml(String); - * @method html - * @param { String } str 需要逆转义的字符串 - * @return { String } 逆转义后的字符串 - * @example - * ```javascript - * - * var str = '<body>&</body>'; - * - * //output: & - * console.log( UE.utils.html( str ) ); - * - * ``` - */ - html: function (str) { - return str - ? str.replace(/&((g|l|quo|ldquo|rdquo)t|amp|#39|nbsp);/g, function (m) { - return { - "<": "<", - "&": "&", - """: '"', - "“": "“", - "”": "”", - ">": ">", - "'": "'", - " ": " " - }[m]; - }) - : ""; - }, - - /** - * 将css样式转换为驼峰的形式 - * @method cssStyleToDomStyle - * @param { String } cssName 需要转换的css样式名 - * @return { String } 转换成驼峰形式后的css样式名 - * @example - * ```javascript - * - * var str = 'border-top'; - * - * //output: borderTop - * console.log( UE.utils.cssStyleToDomStyle( str ) ); - * - * ``` - */ - cssStyleToDomStyle: (function () { - var test = document.createElement("div").style, - cache = { - float: test.cssFloat !== undefined - ? "cssFloat" - : test.styleFloat !== undefined ? "styleFloat" : "float" - }; - - return function (cssName) { - return ( - cache[cssName] || - (cache[cssName] = cssName.toLowerCase().replace(/-./g, function (match) { - return match.charAt(1).toUpperCase(); - })) - ); - }; - })(), - - /** - * 动态加载文件到doc中 - * @method loadFile - * @param { DomDocument } document 需要加载资源文件的文档对象 - * @param { Object } options 加载资源文件的属性集合, 取值请参考代码示例 - * @example - * ```javascript - * - * UE.utils.loadFile( document, { - * src:"test.js", - * tag:"script", - * type:"text/javascript", - * defer:"defer" - * } ); - * - * ``` - */ - - /** - * 动态加载文件到doc中,加载成功后执行的回调函数fn - * @method loadFile - * @param { DomDocument } document 需要加载资源文件的文档对象 - * @param { Object } options 加载资源文件的属性集合, 该集合支持的值是script标签和style标签支持的所有属性。 - * @param { Function } fn 资源文件加载成功之后执行的回调 - * @warning 对于在同一个文档中多次加载同一URL的文件, 该方法会在第一次加载之后缓存该请求, - * 在此之后的所有同一URL的请求, 将会直接触发回调。 - * @example - * ```javascript - * - * UE.utils.loadFile( document, { - * src:"test.js", - * tag:"script", - * type:"text/javascript", - * defer:"defer" - * }, function () { - * console.log('加载成功'); - * } ); - * - * ``` - */ - loadFile: (function () { - var tmpList = []; - - function getItem(doc, obj) { - try { - for (var i = 0, ci; (ci = tmpList[i++]);) { - if (ci.doc === doc && ci.url == (obj.src || obj.href)) { - return ci; - } - } - } catch (e) { - return null; - } - } - - return function (doc, obj, fn) { - var item = getItem(doc, obj); - if (item) { - if (item.ready) { - fn && fn(); - } else { - item.funs.push(fn); - } - return; - } - tmpList.push({ - doc: doc, - url: obj.src || obj.href, - funs: [fn] - }); - if (!doc.body) { - var html = []; - for (var p in obj) { - if (p == "tag") continue; - html.push(p + '="' + obj[p] + '"'); - } - doc.write( - "<" + obj.tag + " " + html.join(" ") + " >" - ); - return; - } - if (obj.id && doc.getElementById(obj.id)) { - return; - } - var element = doc.createElement(obj.tag); - delete obj.tag; - for (var p in obj) { - element.setAttribute(p, obj[p]); - } - element.onload = element.onreadystatechange = function () { - if (!this.readyState || /loaded|complete/.test(this.readyState)) { - item = getItem(doc, obj); - if (item.funs.length > 0) { - item.ready = 1; - for (var fi; (fi = item.funs.pop());) { - fi(); - } - } - element.onload = element.onreadystatechange = null; - } - }; - element.onerror = function () { - throw Error( - "The load " + - (obj.href || obj.src) + - " fails,check the url settings of file ueditor.config.js " - ); - }; - doc.getElementsByTagName("head")[0].appendChild(element); - }; - })(), - - /** - * 判断obj对象是否为空 - * @method isEmptyObject - * @param { * } obj 需要判断的对象 - * @remind 如果判断的对象是NULL, 将直接返回true, 如果是数组且为空, 返回true, 如果是字符串, 且字符串为空, - * 返回true, 如果是普通对象, 且该对象没有任何实例属性, 返回true - * @return { Boolean } 对象是否为空 - * @example - * ```javascript - * - * //output: true - * console.log( UE.utils.isEmptyObject( {} ) ); - * - * //output: true - * console.log( UE.utils.isEmptyObject( [] ) ); - * - * //output: true - * console.log( UE.utils.isEmptyObject( "" ) ); - * - * //output: false - * console.log( UE.utils.isEmptyObject( { key: 1 } ) ); - * - * //output: false - * console.log( UE.utils.isEmptyObject( [1] ) ); - * - * //output: false - * console.log( UE.utils.isEmptyObject( "1" ) ); - * - * ``` - */ - isEmptyObject: function (obj) { - if (obj == null) return true; - if (this.isArray(obj) || this.isString(obj)) return obj.length === 0; - for (var key in obj) if (obj.hasOwnProperty(key)) return false; - return true; - }, - - /** - * 把rgb格式的颜色值转换成16进制格式 - * @method fixColor - * @param { String } rgb格式的颜色值 - * @param { String } - * @example - * rgb(255,255,255) => "#ffffff" - */ - fixColor: function (name, value) { - if (/color/i.test(name) && /rgba?/.test(value)) { - var array = value.split(","); - if (array.length > 3) return ""; - value = "#"; - for (var i = 0, color; (color = array[i++]);) { - color = parseInt(color.replace(/[^\d]/gi, ""), 10).toString(16); - value += color.length == 1 ? "0" + color : color; - } - value = value.toUpperCase(); - } - return value; - }, - /** - * 只针对border,padding,margin做了处理,因为性能问题 - * @public - * @function - * @param {String} val style字符串 - */ - optCss: function (val) { - var padding, margin, border; - val = val.replace(/(padding|margin|border)\-([^:]+):([^;]+);?/gi, function ( - str, - key, - name, - val - ) { - if (val.split(" ").length == 1) { - switch (key) { - case "padding": - !padding && (padding = {}); - padding[name] = val; - return ""; - case "margin": - !margin && (margin = {}); - margin[name] = val; - return ""; - case "border": - return val == "initial" ? "" : str; - } - } - return str; - }); - - function opt(obj, name) { - if (!obj) { - return ""; - } - var t = obj.top, - b = obj.bottom, - l = obj.left, - r = obj.right, - val = ""; - if (!t || !l || !b || !r) { - for (var p in obj) { - val += ";" + name + "-" + p + ":" + obj[p] + ";"; + /** + * 用给定的迭代器遍历数组或类数组对象 + * @method each + * @param { Array } array 需要遍历的数组或者类数组 + * @param { Function } iterator 迭代器, 该方法接受两个参数, 第一个参数是当前所处理的value, 第二个参数是当前遍历对象的key + * @example + * ```javascript + * var divs = document.getElmentByTagNames( "div" ); + * + * //output: 0: DIV, 1: DIV ... + * UE.utils.each( divs, funciton ( value, key ) { + * + * console.log( key + ":" + value.tagName ); + * + * } ); + * ``` + */ + each: function (obj, iterator, context) { + if (obj == null) return; + if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === false) return false; } } else { - val += - ";" + - name + - ":" + - (t == b && b == l && l == r - ? t - : t == b && l == r - ? t + " " + l - : l == r - ? t + " " + l + " " + b - : t + " " + r + " " + b + " " + l) + - ";"; - } - return val; - } - - val += opt(padding, "padding") + opt(margin, "margin"); - return val - .replace(/^[ \n\r\t;]*|[ \n\r\t]*$/, "") - .replace(/;([ \n\r\t]+)|\1;/g, ";") - .replace(/(&((l|g)t|quot|#39))?;{2,}/g, function (a, b) { - return b ? b + ";;" : ";"; - }); - }, - - /** - * 克隆对象 - * @method clone - * @param { Object } source 源对象 - * @return { Object } source的一个副本 - */ - - /** - * 深度克隆对象,将source的属性克隆到target对象, 会覆盖target重名的属性。 - * @method clone - * @param { Object } source 源对象 - * @param { Object } target 目标对象 - * @return { Object } 附加了source对象所有属性的target对象 - */ - clone: function (source, target) { - var tmp; - target = target || {}; - for (var i in source) { - if (source.hasOwnProperty(i)) { - tmp = source[i]; - if (typeof tmp == "object") { - target[i] = utils.isArray(tmp) ? [] : {}; - utils.clone(source[i], target[i]); - } else { - target[i] = tmp; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + if (iterator.call(context, obj[key], key, obj) === false) + return false; + } } } - } - return target; - }, - - /** - * 把cm/pt为单位的值转换为px为单位的值 - * @method transUnitToPx - * @param { String } 待转换的带单位的字符串 - * @return { String } 转换为px为计量单位的值的字符串 - * @example - * ```javascript - * - * //output: 500px - * console.log( UE.utils.transUnitToPx( '20cm' ) ); - * - * //output: 27px - * console.log( UE.utils.transUnitToPx( '20pt' ) ); - * - * ``` - */ - transUnitToPx: function (val) { - if (!/(pt|cm)/.test(val)) { - return val; - } - var unit; - val.replace(/([\d.]+)(\w+)/, function (str, v, u) { - val = v; - unit = u; - }); - switch (unit) { - case "cm": - val = parseFloat(val) * 25; - break; - case "pt": - val = Math.round(parseFloat(val) * 96 / 72); - } - return val + (val ? "px" : ""); - }, - - /** - * 在dom树ready之后执行给定的回调函数 - * @method domReady - * @remind 如果在执行该方法的时候, dom树已经ready, 那么回调函数将立刻执行 - * @param { Function } fn dom树ready之后的回调函数 - * @example - * ```javascript - * - * UE.utils.domReady( function () { - * - * console.log('123'); - * - * } ); - * - * ``` - */ - domReady: (function () { - var fnArr = []; - - function doReady(doc) { - //确保onready只执行一次 - doc.isReady = true; - for (var ci; (ci = fnArr.pop()); ci()) { - } - } - - return function (onready, win) { - win = win || window; - var doc = win.document; - onready && fnArr.push(onready); - if (doc.readyState === "complete") { - doReady(doc); - } else { - doc.isReady && doReady(doc); - if (browser.ie && browser.version != 11) { - (function () { - if (doc.isReady) return; - try { - doc.documentElement.doScroll("left"); - } catch (error) { - setTimeout(arguments.callee, 0); - return; - } - doReady(doc); - })(); - win.attachEvent("onload", function () { - doReady(doc); - }); - } else { - doc.addEventListener( - "DOMContentLoaded", - function () { - doc.removeEventListener( - "DOMContentLoaded", - arguments.callee, - false - ); - doReady(doc); - }, - false - ); - win.addEventListener( - "load", - function () { - doReady(doc); - }, - false - ); - } - } - }; - })(), - - /** - * 动态添加css样式 - * @method cssRule - * @param { String } 节点名称 - * @grammar UE.utils.cssRule('添加的样式的节点名称',['样式','放到哪个document上']) - * @grammar UE.utils.cssRule('body','body{background:#ccc}') => null //给body添加背景颜色 - * @grammar UE.utils.cssRule('body') =>样式的字符串 //取得key值为body的样式的内容,如果没有找到key值先关的样式将返回空,例如刚才那个背景颜色,将返回 body{background:#ccc} - * @grammar UE.utils.cssRule('body',document) => 返回指定key的样式,并且指定是哪个document - * @grammar UE.utils.cssRule('body','') =>null //清空给定的key值的背景颜色 - */ - cssRule: browser.ie && browser.version != 11 - ? function (key, style, doc) { - var indexList, index; - if ( - style === undefined || - (style && style.nodeType && style.nodeType == 9) - ) { - //获取样式 - doc = style && style.nodeType && style.nodeType == 9 - ? style - : doc || document; - indexList = doc.indexList || (doc.indexList = {}); - index = indexList[key]; - if (index !== undefined) { - return doc.styleSheets[index].cssText; - } - return undefined; - } - doc = doc || document; - indexList = doc.indexList || (doc.indexList = {}); - index = indexList[key]; - //清除样式 - if (style === "") { - if (index !== undefined) { - doc.styleSheets[index].cssText = ""; - delete indexList[key]; - return true; - } - return false; - } - - //添加样式 - if (index !== undefined) { - sheetStyle = doc.styleSheets[index]; - } else { - sheetStyle = doc.createStyleSheet( - "", - (index = doc.styleSheets.length) - ); - indexList[key] = index; - } - sheetStyle.cssText = style; - } - : function (key, style, doc) { - var head, node; - if ( - style === undefined || - (style && style.nodeType && style.nodeType == 9) - ) { - //获取样式 - doc = style && style.nodeType && style.nodeType == 9 - ? style - : doc || document; - node = doc.getElementById(key); - return node ? node.innerHTML : undefined; - } - doc = doc || document; - node = doc.getElementById(key); - - //清除样式 - if (style === "") { - if (node) { - node.parentNode.removeChild(node); - return true; - } - return false; - } - - //添加样式 - if (node) { - node.innerHTML = style; - } else { - node = doc.createElement("style"); - node.id = key; - node.innerHTML = style; - doc.getElementsByTagName("head")[0].appendChild(node); - } }, - sort: function (array, compareFn) { - compareFn = - compareFn || - function (item1, item2) { - return item1.localeCompare(item2); - }; - for (var i = 0, len = array.length; i < len; i++) { - for (var j = i, length = array.length; j < length; j++) { - if (compareFn(array[i], array[j]) > 0) { - var t = array[i]; - array[i] = array[j]; - array[j] = t; - } - } - } - return array; - }, - serializeParam: function (json) { - var strArr = []; - for (var i in json) { - //忽略默认的几个参数 - if (i == "method" || i == "timeout" || i == "async") continue; - //传递过来的对象和函数不在提交之列 - if ( - !( - (typeof json[i]).toLowerCase() == "function" || - (typeof json[i]).toLowerCase() == "object" - ) - ) { - strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i])); - } else if (utils.isArray(json[i])) { - //支持传数组内容 - for (var j = 0; j < json[i].length; j++) { - strArr.push( - encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]) - ); - } - } - } - return strArr.join("&"); - }, - formatUrl: function (url) { - var u = url.replace(/&&/g, "&"); - u = u.replace(/\?&/g, "?"); - u = u.replace(/&$/g, ""); - u = u.replace(/&#/g, "#"); - u = u.replace(/&+/g, "&"); - return u; - }, - addStyleContent: function (cssContent) { - var style = document.createElement("style"); - style.innerHTML = cssContent; - document.head.appendChild(style); - }, - isCrossDomainUrl: function (url) { - var a = document.createElement("a"); - a.href = url; - if (browser.ie) { - a.href = a.href; - } - return !( - a.protocol == location.protocol && - a.hostname == location.hostname && - (a.port == location.port || - (a.port == "80" && location.port == "") || - (a.port == "" && location.port == "80")) - ); - }, - clearEmptyAttrs: function (obj) { - for (var p in obj) { - if (obj[p] === "") { - delete obj[p]; - } - } - return obj; - }, - str2json: function (s) { - if (!utils.isString(s)) return null; - if (window.JSON) { - return JSON.parse(s); - } else { - return new Function("return " + utils.trim(s || ""))(); - } - }, - json2str: (function () { - if (window.JSON) { - return JSON.stringify; - } else { - var escapeMap = { - "\b": "\\b", - "\t": "\\t", - "\n": "\\n", - "\f": "\\f", - "\r": "\\r", - '"': '\\"', - "\\": "\\\\" - }; - function encodeString(source) { - if (/["\\\x00-\x1f]/.test(source)) { - source = source.replace(/["\\\x00-\x1f]/g, function (match) { - var c = escapeMap[match]; - if (c) { - return c; + /** + * 以给定对象作为原型创建一个新对象 + * @method makeInstance + * @param { Object } protoObject 该对象将作为新创建对象的原型 + * @return { Object } 新的对象, 该对象的原型是给定的protoObject对象 + * @example + * ```javascript + * + * var protoObject = { sayHello: function () { console.log('Hello UEditor!'); } }; + * + * var newObject = UE.utils.makeInstance( protoObject ); + * //output: Hello UEditor! + * newObject.sayHello(); + * ``` + */ + makeInstance: function (obj) { + var noop = new Function(); + noop.prototype = obj; + obj = new noop(); + noop.prototype = null; + return obj; + }, + + isObject: function (item) { + return (item && typeof item === 'object' && !Array.isArray(item)); + }, + + merge: function (target, source) { + var output = Object.assign({}, target); + if (this.isObject(target) && this.isObject(source)) { + Object.keys(source).forEach(key => { + if (this.isObject(source[key])) { + if (!(key in target)) { + Object.assign(output, {[key]: source[key]}); + } else { + output[key] = this.merge(target[key], source[key]); } - c = match.charCodeAt(); - return ( - "\\u00" + Math.floor(c / 16).toString(16) + (c % 16).toString(16) - ); - }); - } - return '"' + source + '"'; + } else { + Object.assign(output, {[key]: source[key]}); + } + }); } + return output; + }, - function encodeArray(source) { - var result = ["["], - l = source.length, - preComma, - i, - item; - - for (i = 0; i < l; i++) { - item = source[i]; - - switch (typeof item) { - case "undefined": - case "function": - case "unknown": - break; - default: - if (preComma) { - result.push(","); - } - result.push(utils.json2str(item)); - preComma = 1; + /** + * 将source对象中的属性扩展到target对象上, 根据指定的isKeepTarget值决定是否保留目标对象中与 + * 源对象属性名相同的属性值。 + * @method extend + * @param { Object } target 目标对象, 新的属性将附加到该对象上 + * @param { Object } source 源对象, 该对象的属性会被附加到target对象上 + * @param { Boolean } isKeepTarget 是否保留目标对象中与源对象中属性名相同的属性 + * @return { Object } 返回target对象 + * @example + * ```javascript + * + * var target = { name: 'target', sex: 1 }, + * source = { name: 'source', age: 17 }; + * + * UE.utils.extend( target, source, true ); + * + * //output: { name: 'target', sex: 1, age: 17 } + * console.log( target ); + * + * ``` + */ + extend: function (t, s, b) { + if (s) { + for (var k in s) { + if (!b || !t.hasOwnProperty(k)) { + t[k] = s[k]; } } - result.push("]"); - return result.join(""); } + return t; + }, - function pad(source) { - return source < 10 ? "0" + source : source; + /** + * 将给定的多个对象的属性复制到目标对象target上 + * @method extend2 + * @remind 该方法将强制把源对象上的属性复制到target对象上 + * @remind 该方法支持两个及以上的参数, 从第二个参数开始, 其属性都会被复制到第一个参数上。 如果遇到同名的属性, + * 将会覆盖掉之前的值。 + * @param { Object } target 目标对象, 新的属性将附加到该对象上 + * @param { Object... } source 源对象, 支持多个对象, 该对象的属性会被附加到target对象上 + * @return { Object } 返回target对象 + * @example + * ```javascript + * + * var target = {}, + * source1 = { name: 'source', age: 17 }, + * source2 = { title: 'dev' }; + * + * UE.utils.extend2( target, source1, source2 ); + * + * //output: { name: 'source', age: 17, title: 'dev' } + * console.log( target ); + * + * ``` + */ + extend2: function (t) { + var a = arguments; + for (var i = 1; i < a.length; i++) { + var x = a[i]; + for (var k in x) { + if (!t.hasOwnProperty(k)) { + t[k] = x[k]; + } + } } + return t; + }, - function encodeDate(source) { - return ( - '"' + - source.getFullYear() + - "-" + - pad(source.getMonth() + 1) + - "-" + - pad(source.getDate()) + - "T" + - pad(source.getHours()) + - ":" + - pad(source.getMinutes()) + - ":" + - pad(source.getSeconds()) + - '"' - ); + /** + * 模拟继承机制, 使得subClass继承自superClass + * @method inherits + * @param { Object } subClass 子类对象 + * @param { Object } superClass 超类对象 + * @warning 该方法只能让subClass继承超类的原型, subClass对象自身的属性和方法不会被继承 + * @return { Object } 继承superClass后的子类对象 + * @example + * ```javascript + * function SuperClass(){ + * this.name = "小李"; + * } + * + * SuperClass.prototype = { + * hello:function(str){ + * console.log(this.name + str); + * } + * } + * + * function SubClass(){ + * this.name = "小张"; + * } + * + * UE.utils.inherits(SubClass,SuperClass); + * + * var sub = new SubClass(); + * //output: '小张早上好! + * sub.hello("早上好!"); + * ``` + */ + inherits: function (subClass, superClass) { + var oldP = subClass.prototype, + newP = utils.makeInstance(superClass.prototype); + utils.extend(newP, oldP, true); + subClass.prototype = newP; + return (newP.constructor = subClass); + }, + + /** + * 用指定的context对象作为函数fn的上下文 + * @method bind + * @param { Function } fn 需要绑定上下文的函数对象 + * @param { Object } content 函数fn新的上下文对象 + * @return { Function } 一个新的函数, 该函数作为原始函数fn的代理, 将完成fn的上下文调换工作。 + * @example + * ```javascript + * + * var name = 'window', + * newTest = null; + * + * function test () { + * console.log( this.name ); + * } + * + * newTest = UE.utils.bind( test, { name: 'object' } ); + * + * //output: object + * newTest(); + * + * //output: window + * test(); + * + * ``` + */ + bind: function (fn, context) { + return function () { + return fn.apply(context, arguments); + }; + }, + + /** + * 创建延迟指定时间后执行的函数fn + * @method defer + * @param { Function } fn 需要延迟执行的函数对象 + * @param { int } delay 延迟的时间, 单位是毫秒 + * @warning 该方法的时间控制是不精确的,仅仅只能保证函数的执行是在给定的时间之后, + * 而不能保证刚好到达延迟时间时执行。 + * @return { Function } 目标函数fn的代理函数, 只有执行该函数才能起到延时效果 + * @example + * ```javascript + * var start = 0; + * + * function test(){ + * console.log( new Date() - start ); + * } + * + * var testDefer = UE.utils.defer( test, 1000 ); + * // + * start = new Date(); + * //output: (大约在1000毫秒之后输出) 1000 + * testDefer(); + * ``` + */ + + /** + * 创建延迟指定时间后执行的函数fn, 如果在延迟时间内再次执行该方法, 将会根据指定的exclusion的值, + * 决定是否取消前一次函数的执行, 如果exclusion的值为true, 则取消执行,反之,将继续执行前一个方法。 + * @method defer + * @param { Function } fn 需要延迟执行的函数对象 + * @param { int } delay 延迟的时间, 单位是毫秒 + * @param { Boolean } exclusion 如果在延迟时间内再次执行该函数,该值将决定是否取消执行前一次函数的执行, + * 值为true表示取消执行, 反之则将在执行前一次函数之后才执行本次函数调用。 + * @warning 该方法的时间控制是不精确的,仅仅只能保证函数的执行是在给定的时间之后, + * 而不能保证刚好到达延迟时间时执行。 + * @return { Function } 目标函数fn的代理函数, 只有执行该函数才能起到延时效果 + * @example + * ```javascript + * + * function test(){ + * console.log(1); + * } + * + * var testDefer = UE.utils.defer( test, 1000, true ); + * + * //output: (两次调用仅有一次输出) 1 + * testDefer(); + * testDefer(); + * ``` + */ + defer: function (fn, delay, exclusion) { + var timerID; + return function () { + if (exclusion) { + clearTimeout(timerID); + } + timerID = setTimeout(fn, delay); + }; + }, + + /** + * 获取元素item在数组array中首次出现的位置, 如果未找到item, 则返回-1 + * @method indexOf + * @remind 该方法的匹配过程使用的是恒等“===” + * @param { Array } array 需要查找的数组对象 + * @param { * } item 需要在目标数组中查找的值 + * @return { int } 返回item在目标数组array中首次出现的位置, 如果在数组中未找到item, 则返回-1 + * @example + * ```javascript + * var item = 1, + * arr = [ 3, 4, 6, 8, 1, 1, 2 ]; + * + * //output: 4 + * console.log( UE.utils.indexOf( arr, item ) ); + * ``` + */ + + /** + * 获取元素item数组array中首次出现的位置, 如果未找到item, 则返回-1。通过start的值可以指定搜索的起始位置。 + * @method indexOf + * @remind 该方法的匹配过程使用的是恒等“===” + * @param { Array } array 需要查找的数组对象 + * @param { * } item 需要在目标数组中查找的值 + * @param { int } start 搜索的起始位置 + * @return { int } 返回item在目标数组array中的start位置之后首次出现的位置, 如果在数组中未找到item, 则返回-1 + * @example + * ```javascript + * var item = 1, + * arr = [ 3, 4, 6, 8, 1, 2, 8, 3, 2, 1, 1, 4 ]; + * + * //output: 9 + * console.log( UE.utils.indexOf( arr, item, 5 ) ); + * ``` + */ + indexOf: function (array, item, start) { + var index = -1; + start = this.isNumber(start) ? start : 0; + this.each(array, function (v, i) { + if (i >= start && v === item) { + index = i; + return false; + } + }); + return index; + }, + + /** + * 移除数组array中所有的元素item + * @method removeItem + * @param { Array } array 要移除元素的目标数组 + * @param { * } item 将要被移除的元素 + * @remind 该方法的匹配过程使用的是恒等“===” + * @example + * ```javascript + * var arr = [ 4, 5, 7, 1, 3, 4, 6 ]; + * + * UE.utils.removeItem( arr, 4 ); + * //output: [ 5, 7, 1, 3, 6 ] + * console.log( arr ); + * + * ``` + */ + removeItem: function (array, item) { + for (var i = 0, l = array.length; i < l; i++) { + if (array[i] === item) { + array.splice(i, 1); + i--; + } } + }, - return function (value) { - switch (typeof value) { - case "undefined": - return "undefined"; + /** + * 删除字符串str的首尾空格 + * @method trim + * @param { String } str 需要删除首尾空格的字符串 + * @return { String } 删除了首尾的空格后的字符串 + * @example + * ```javascript + * + * var str = " UEdtior "; + * + * //output: 9 + * console.log( str.length ); + * + * //output: 7 + * console.log( UE.utils.trim( " UEdtior " ).length ); + * + * //output: 9 + * console.log( str.length ); + * + * ``` + */ + trim: function (str) { + return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, ""); + }, - case "number": - return isFinite(value) ? String(value) : "null"; + /** + * 将字符串str以','分隔成数组后,将该数组转换成哈希对象, 其生成的hash对象的key为数组中的元素, value为1 + * @method listToMap + * @warning 该方法在生成的hash对象中,会为每一个key同时生成一个另一个全大写的key。 + * @param { String } str 该字符串将被以','分割为数组, 然后进行转化 + * @return { Object } 转化之后的hash对象 + * @example + * ```javascript + * + * //output: Object {UEdtior: 1, UEDTIOR: 1, Hello: 1, HELLO: 1} + * console.log( UE.utils.listToMap( 'UEdtior,Hello' ) ); + * + * ``` + */ - case "string": - return encodeString(value); + /** + * 将字符串数组转换成哈希对象, 其生成的hash对象的key为数组中的元素, value为1 + * @method listToMap + * @warning 该方法在生成的hash对象中,会为每一个key同时生成一个另一个全大写的key。 + * @param { Array } arr 字符串数组 + * @return { Object } 转化之后的hash对象 + * @example + * ```javascript + * + * //output: Object {UEdtior: 1, UEDTIOR: 1, Hello: 1, HELLO: 1} + * console.log( UE.utils.listToMap( [ 'UEdtior', 'Hello' ] ) ); + * + * ``` + */ + listToMap: function (list) { + if (!list) return {}; + list = utils.isArray(list) ? list : list.split(","); + for (var i = 0, ci, obj = {}; (ci = list[i++]);) { + obj[ci.toUpperCase()] = obj[ci] = 1; + } + return obj; + }, - case "boolean": - return String(value); - - default: - if (value === null) { - return "null"; - } else if (utils.isArray(value)) { - return encodeArray(value); - } else if (utils.isDate(value)) { - return encodeDate(value); + /** + * 将str中的html符号转义,将转义“',&,<,",>,”,“”七个字符 + * @method unhtml + * @param { String } str 需要转义的字符串 + * @return { String } 转义后的字符串 + * @example + * ```javascript + * var html = '&'; + * + * //output: <body>&</body> + * console.log( UE.utils.unhtml( html ) ); + * + * ``` + */ + unhtml: function (str, reg) { + return str + ? str.replace( + reg || /[&<">'](?:(amp|lt|ldquo|rdquo|quot|gt|#39|nbsp|#\d+);)?/g, + function (a, b) { + if (b) { + return a; } else { - var result = ["{"], - encode = utils.json2str, - preComma, - item; - - for (var key in value) { - if (Object.prototype.hasOwnProperty.call(value, key)) { - item = value[key]; - switch (typeof item) { - case "undefined": - case "unknown": - case "function": - break; - default: - if (preComma) { - result.push(","); - } - preComma = 1; - result.push(encode(key) + ":" + encode(item)); - } - } - } - result.push("}"); - return result.join(""); + return { + "<": "<", + "&": "&", + '"': """, + "“": "“", + "”": "”", + ">": ">", + "'": "'" + }[a]; } + } + ) + : ""; + }, + + /** + * 将str中的转义字符还原成html字符 + * @see UE.utils.unhtml(String); + * @method html + * @param { String } str 需要逆转义的字符串 + * @return { String } 逆转义后的字符串 + * @example + * ```javascript + * + * var str = '<body>&</body>'; + * + * //output: & + * console.log( UE.utils.html( str ) ); + * + * ``` + */ + html: function (str) { + return str + ? str.replace(/&((g|l|quo|ldquo|rdquo)t|amp|#39|nbsp);/g, function (m) { + return { + "<": "<", + "&": "&", + """: '"', + "“": "“", + "”": "”", + ">": ">", + "'": "'", + " ": " " + }[m]; + }) + : ""; + }, + + /** + * 将css样式转换为驼峰的形式 + * @method cssStyleToDomStyle + * @param { String } cssName 需要转换的css样式名 + * @return { String } 转换成驼峰形式后的css样式名 + * @example + * ```javascript + * + * var str = 'border-top'; + * + * //output: borderTop + * console.log( UE.utils.cssStyleToDomStyle( str ) ); + * + * ``` + */ + cssStyleToDomStyle: (function () { + var test = document.createElement("div").style, + cache = { + float: test.cssFloat !== undefined + ? "cssFloat" + : test.styleFloat !== undefined ? "styleFloat" : "float" + }; + + return function (cssName) { + return ( + cache[cssName] || + (cache[cssName] = cssName.toLowerCase().replace(/-./g, function (match) { + return match.charAt(1).toUpperCase(); + })) + ); + }; + })(), + + /** + * 动态加载文件到doc中 + * @method loadFile + * @param { DomDocument } document 需要加载资源文件的文档对象 + * @param { Object } options 加载资源文件的属性集合, 取值请参考代码示例 + * @example + * ```javascript + * + * UE.utils.loadFile( document, { + * src:"test.js", + * tag:"script", + * type:"text/javascript", + * defer:"defer" + * } ); + * + * ``` + */ + + /** + * 动态加载文件到doc中,加载成功后执行的回调函数fn + * @method loadFile + * @param { DomDocument } document 需要加载资源文件的文档对象 + * @param { Object } options 加载资源文件的属性集合, 该集合支持的值是script标签和style标签支持的所有属性。 + * @param { Function } fn 资源文件加载成功之后执行的回调 + * @warning 对于在同一个文档中多次加载同一URL的文件, 该方法会在第一次加载之后缓存该请求, + * 在此之后的所有同一URL的请求, 将会直接触发回调。 + * @example + * ```javascript + * + * UE.utils.loadFile( document, { + * src:"test.js", + * tag:"script", + * type:"text/javascript", + * defer:"defer" + * }, function () { + * console.log('加载成功'); + * } ); + * + * ``` + */ + loadFile: (function () { + var tmpList = []; + + function getItem(doc, obj) { + try { + for (var i = 0, ci; (ci = tmpList[i++]);) { + if (ci.doc === doc && ci.url == (obj.src || obj.href)) { + return ci; + } + } + } catch (e) { + return null; + } + } + + return function (doc, obj, fn) { + var item = getItem(doc, obj); + if (item) { + if (item.ready) { + fn && fn(); + } else { + item.funs.push(fn); + } + return; + } + tmpList.push({ + doc: doc, + url: obj.src || obj.href, + funs: [fn] + }); + if (!doc.body) { + var html = []; + for (var p in obj) { + if (p == "tag") continue; + html.push(p + '="' + obj[p] + '"'); + } + doc.write( + "<" + obj.tag + " " + html.join(" ") + " >" + ); + return; + } + if (obj.id && doc.getElementById(obj.id)) { + return; + } + var element = doc.createElement(obj.tag); + delete obj.tag; + for (var p in obj) { + element.setAttribute(p, obj[p]); + } + element.onload = element.onreadystatechange = function () { + if (!this.readyState || /loaded|complete/.test(this.readyState)) { + item = getItem(doc, obj); + if (item.funs.length > 0) { + item.ready = 1; + for (var fi; (fi = item.funs.pop());) { + fi(); + } + } + element.onload = element.onreadystatechange = null; + } + }; + element.onerror = function () { + throw Error( + "The load " + + (obj.href || obj.src) + + " fails,check the url settings of file ueditor.config.js " + ); + }; + doc.getElementsByTagName("head")[0].appendChild(element); + }; + })(), + + /** + * 判断obj对象是否为空 + * @method isEmptyObject + * @param { * } obj 需要判断的对象 + * @remind 如果判断的对象是NULL, 将直接返回true, 如果是数组且为空, 返回true, 如果是字符串, 且字符串为空, + * 返回true, 如果是普通对象, 且该对象没有任何实例属性, 返回true + * @return { Boolean } 对象是否为空 + * @example + * ```javascript + * + * //output: true + * console.log( UE.utils.isEmptyObject( {} ) ); + * + * //output: true + * console.log( UE.utils.isEmptyObject( [] ) ); + * + * //output: true + * console.log( UE.utils.isEmptyObject( "" ) ); + * + * //output: false + * console.log( UE.utils.isEmptyObject( { key: 1 } ) ); + * + * //output: false + * console.log( UE.utils.isEmptyObject( [1] ) ); + * + * //output: false + * console.log( UE.utils.isEmptyObject( "1" ) ); + * + * ``` + */ + isEmptyObject: function (obj) { + if (obj == null) return true; + if (this.isArray(obj) || this.isString(obj)) return obj.length === 0; + for (var key in obj) if (obj.hasOwnProperty(key)) return false; + return true; + }, + + /** + * 把rgb格式的颜色值转换成16进制格式 + * @method fixColor + * @param { String } rgb格式的颜色值 + * @param { String } + * @example + * rgb(255,255,255) => "#ffffff" + */ + fixColor: function (name, value) { + if (/color/i.test(name) && /rgba?/.test(value)) { + var array = value.split(","); + if (array.length > 3) return ""; + value = "#"; + for (var i = 0, color; (color = array[i++]);) { + color = parseInt(color.replace(/[^\d]/gi, ""), 10).toString(16); + value += color.length == 1 ? "0" + color : color; + } + value = value.toUpperCase(); + } + return value; + }, + /** + * 只针对border,padding,margin做了处理,因为性能问题 + * @public + * @function + * @param {String} val style字符串 + */ + optCss: function (val) { + var padding, margin, border; + val = val.replace(/(padding|margin|border)\-([^:]+):([^;]+);?/gi, function ( + str, + key, + name, + val + ) { + if (val.split(" ").length == 1) { + switch (key) { + case "padding": + !padding && (padding = {}); + padding[name] = val; + return ""; + case "margin": + !margin && (margin = {}); + margin[name] = val; + return ""; + case "border": + return val == "initial" ? "" : str; + } + } + return str; + }); + + function opt(obj, name) { + if (!obj) { + return ""; + } + var t = obj.top, + b = obj.bottom, + l = obj.left, + r = obj.right, + val = ""; + if (!t || !l || !b || !r) { + for (var p in obj) { + val += ";" + name + "-" + p + ":" + obj[p] + ";"; + } + } else { + val += + ";" + + name + + ":" + + (t == b && b == l && l == r + ? t + : t == b && l == r + ? t + " " + l + : l == r + ? t + " " + l + " " + b + : t + " " + r + " " + b + " " + l) + + ";"; + } + return val; + } + + val += opt(padding, "padding") + opt(margin, "margin"); + return val + .replace(/^[ \n\r\t;]*|[ \n\r\t]*$/, "") + .replace(/;([ \n\r\t]+)|\1;/g, ";") + .replace(/(&((l|g)t|quot|#39))?;{2,}/g, function (a, b) { + return b ? b + ";;" : ";"; + }); + }, + + /** + * 克隆对象 + * @method clone + * @param { Object } source 源对象 + * @return { Object } source的一个副本 + */ + + /** + * 深度克隆对象,将source的属性克隆到target对象, 会覆盖target重名的属性。 + * @method clone + * @param { Object } source 源对象 + * @param { Object } target 目标对象 + * @return { Object } 附加了source对象所有属性的target对象 + */ + clone: function (source, target) { + var tmp; + target = target || {}; + for (var i in source) { + if (source.hasOwnProperty(i)) { + tmp = source[i]; + if (typeof tmp == "object") { + target[i] = utils.isArray(tmp) ? [] : {}; + utils.clone(source[i], target[i]); + } else { + target[i] = tmp; + } + } + } + return target; + }, + + /** + * 把cm/pt为单位的值转换为px为单位的值 + * @method transUnitToPx + * @param { String } 待转换的带单位的字符串 + * @return { String } 转换为px为计量单位的值的字符串 + * @example + * ```javascript + * + * //output: 500px + * console.log( UE.utils.transUnitToPx( '20cm' ) ); + * + * //output: 27px + * console.log( UE.utils.transUnitToPx( '20pt' ) ); + * + * ``` + */ + transUnitToPx: function (val) { + if (!/(pt|cm)/.test(val)) { + return val; + } + var unit; + val.replace(/([\d.]+)(\w+)/, function (str, v, u) { + val = v; + unit = u; + }); + switch (unit) { + case "cm": + val = parseFloat(val) * 25; + break; + case "pt": + val = Math.round(parseFloat(val) * 96 / 72); + } + return val + (val ? "px" : ""); + }, + + /** + * 在dom树ready之后执行给定的回调函数 + * @method domReady + * @remind 如果在执行该方法的时候, dom树已经ready, 那么回调函数将立刻执行 + * @param { Function } fn dom树ready之后的回调函数 + * @example + * ```javascript + * + * UE.utils.domReady( function () { + * + * console.log('123'); + * + * } ); + * + * ``` + */ + domReady: (function () { + var fnArr = []; + + function doReady(doc) { + //确保onready只执行一次 + doc.isReady = true; + for (var ci; (ci = fnArr.pop()); ci()) { + } + } + + return function (onready, win) { + win = win || window; + var doc = win.document; + onready && fnArr.push(onready); + if (doc.readyState === "complete") { + doReady(doc); + } else { + doc.isReady && doReady(doc); + if (browser.ie && browser.version != 11) { + (function () { + if (doc.isReady) return; + try { + doc.documentElement.doScroll("left"); + } catch (error) { + setTimeout(arguments.callee, 0); + return; + } + doReady(doc); + })(); + win.attachEvent("onload", function () { + doReady(doc); + }); + } else { + doc.addEventListener( + "DOMContentLoaded", + function () { + doc.removeEventListener( + "DOMContentLoaded", + arguments.callee, + false + ); + doReady(doc); + }, + false + ); + win.addEventListener( + "load", + function () { + doReady(doc); + }, + false + ); + } } }; + })(), + + /** + * 动态添加css样式 + * @method cssRule + * @param { String } 节点名称 + * @grammar UE.utils.cssRule('添加的样式的节点名称',['样式','放到哪个document上']) + * @grammar UE.utils.cssRule('body','body{background:#ccc}') => null //给body添加背景颜色 + * @grammar UE.utils.cssRule('body') =>样式的字符串 //取得key值为body的样式的内容,如果没有找到key值先关的样式将返回空,例如刚才那个背景颜色,将返回 body{background:#ccc} + * @grammar UE.utils.cssRule('body',document) => 返回指定key的样式,并且指定是哪个document + * @grammar UE.utils.cssRule('body','') =>null //清空给定的key值的背景颜色 + */ + cssRule: browser.ie && browser.version != 11 + ? function (key, style, doc) { + var indexList, index; + if ( + style === undefined || + (style && style.nodeType && style.nodeType == 9) + ) { + //获取样式 + doc = style && style.nodeType && style.nodeType == 9 + ? style + : doc || document; + indexList = doc.indexList || (doc.indexList = {}); + index = indexList[key]; + if (index !== undefined) { + return doc.styleSheets[index].cssText; + } + return undefined; + } + doc = doc || document; + indexList = doc.indexList || (doc.indexList = {}); + index = indexList[key]; + //清除样式 + if (style === "") { + if (index !== undefined) { + doc.styleSheets[index].cssText = ""; + delete indexList[key]; + return true; + } + return false; + } + + //添加样式 + if (index !== undefined) { + sheetStyle = doc.styleSheets[index]; + } else { + sheetStyle = doc.createStyleSheet( + "", + (index = doc.styleSheets.length) + ); + indexList[key] = index; + } + sheetStyle.cssText = style; + } + : function (key, style, doc) { + var head, node; + if ( + style === undefined || + (style && style.nodeType && style.nodeType == 9) + ) { + //获取样式 + doc = style && style.nodeType && style.nodeType == 9 + ? style + : doc || document; + node = doc.getElementById(key); + return node ? node.innerHTML : undefined; + } + doc = doc || document; + node = doc.getElementById(key); + + //清除样式 + if (style === "") { + if (node) { + node.parentNode.removeChild(node); + return true; + } + return false; + } + + //添加样式 + if (node) { + node.innerHTML = style; + } else { + node = doc.createElement("style"); + node.id = key; + node.innerHTML = style; + doc.getElementsByTagName("head")[0].appendChild(node); + } + }, + sort: function (array, compareFn) { + compareFn = + compareFn || + function (item1, item2) { + return item1.localeCompare(item2); + }; + for (var i = 0, len = array.length; i < len; i++) { + for (var j = i, length = array.length; j < length; j++) { + if (compareFn(array[i], array[j]) > 0) { + var t = array[i]; + array[i] = array[j]; + array[j] = t; + } + } + } + return array; + }, + serializeParam: function (json) { + var strArr = []; + for (var i in json) { + //忽略默认的几个参数 + if (i == "method" || i == "timeout" || i == "async") continue; + //传递过来的对象和函数不在提交之列 + if ( + !( + (typeof json[i]).toLowerCase() == "function" || + (typeof json[i]).toLowerCase() == "object" + ) + ) { + strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i])); + } else if (utils.isArray(json[i])) { + //支持传数组内容 + for (var j = 0; j < json[i].length; j++) { + strArr.push( + encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]) + ); + } + } + } + return strArr.join("&"); + }, + formatUrl: function (url) { + var u = url.replace(/&&/g, "&"); + u = u.replace(/\?&/g, "?"); + u = u.replace(/&$/g, ""); + u = u.replace(/&#/g, "#"); + u = u.replace(/&+/g, "&"); + return u; + }, + addStyleContent: function (cssContent) { + var style = document.createElement("style"); + style.innerHTML = cssContent; + document.head.appendChild(style); + }, + isCrossDomainUrl: function (url) { + var a = document.createElement("a"); + a.href = url; + if (browser.ie) { + a.href = a.href; + } + return !( + a.protocol == location.protocol && + a.hostname == location.hostname && + (a.port == location.port || + (a.port == "80" && location.port == "") || + (a.port == "" && location.port == "80")) + ); + }, + clearEmptyAttrs: function (obj) { + for (var p in obj) { + if (obj[p] === "") { + delete obj[p]; + } + } + return obj; + }, + str2json: function (s) { + if (!utils.isString(s)) return null; + if (window.JSON) { + return JSON.parse(s); + } else { + return new Function("return " + utils.trim(s || ""))(); + } + }, + base64toBlob: function (base64Data, contentType) { + contentType = contentType || ""; + var sliceSize = 1024; + var byteCharacters = atob(base64Data); + var bytesLength = byteCharacters.length; + var slicesCount = Math.ceil(bytesLength / sliceSize); + var byteArrays = new Array(slicesCount); + for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) { + var begin = sliceIndex * sliceSize; + var end = Math.min(begin + sliceSize, bytesLength); + var bytes = new Array(end - begin); + for (var offset = begin, i = 0; offset < end; ++i, ++offset) { + bytes[i] = byteCharacters[offset].charCodeAt(0); + } + byteArrays[sliceIndex] = new Uint8Array(bytes); + } + return new Blob(byteArrays, { type: contentType }); + }, + json2str: (function () { + if (window.JSON) { + return JSON.stringify; + } else { + var escapeMap = { + "\b": "\\b", + "\t": "\\t", + "\n": "\\n", + "\f": "\\f", + "\r": "\\r", + '"': '\\"', + "\\": "\\\\" + }; + + function encodeString(source) { + if (/["\\\x00-\x1f]/.test(source)) { + source = source.replace(/["\\\x00-\x1f]/g, function (match) { + var c = escapeMap[match]; + if (c) { + return c; + } + c = match.charCodeAt(); + return ( + "\\u00" + Math.floor(c / 16).toString(16) + (c % 16).toString(16) + ); + }); + } + return '"' + source + '"'; + } + + function encodeArray(source) { + var result = ["["], + l = source.length, + preComma, + i, + item; + + for (i = 0; i < l; i++) { + item = source[i]; + + switch (typeof item) { + case "undefined": + case "function": + case "unknown": + break; + default: + if (preComma) { + result.push(","); + } + result.push(utils.json2str(item)); + preComma = 1; + } + } + result.push("]"); + return result.join(""); + } + + function pad(source) { + return source < 10 ? "0" + source : source; + } + + function encodeDate(source) { + return ( + '"' + + source.getFullYear() + + "-" + + pad(source.getMonth() + 1) + + "-" + + pad(source.getDate()) + + "T" + + pad(source.getHours()) + + ":" + + pad(source.getMinutes()) + + ":" + + pad(source.getSeconds()) + + '"' + ); + } + + return function (value) { + switch (typeof value) { + case "undefined": + return "undefined"; + + case "number": + return isFinite(value) ? String(value) : "null"; + + case "string": + return encodeString(value); + + case "boolean": + return String(value); + + default: + if (value === null) { + return "null"; + } else if (utils.isArray(value)) { + return encodeArray(value); + } else if (utils.isDate(value)) { + return encodeDate(value); + } else { + var result = ["{"], + encode = utils.json2str, + preComma, + item; + + for (var key in value) { + if (Object.prototype.hasOwnProperty.call(value, key)) { + item = value[key]; + switch (typeof item) { + case "undefined": + case "unknown": + case "function": + break; + default: + if (preComma) { + result.push(","); + } + preComma = 1; + result.push(encode(key) + ":" + encode(item)); + } + } + } + result.push("}"); + return result.join(""); + } + } + }; + } + })() + }); + /** + * 判断给定的对象是否是字符串 + * @method isString + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是字符串 + */ + + /** + * 判断给定的对象是否是数组 + * @method isArray + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是数组 + */ + + /** + * 判断给定的对象是否是一个Function + * @method isFunction + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是Function + */ + + /** + * 判断给定的对象是否是Number + * @method isNumber + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是Number + */ + + /** + * 判断给定的对象是否是一个正则表达式 + * @method isRegExp + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是正则表达式 + */ + + /** + * 判断给定的对象是否是一个普通对象 + * @method isObject + * @param { * } object 需要判断的对象 + * @return { Boolean } 给定的对象是否是普通对象 + */ + utils.each( + ["String", "Function", "Array", "Number", "RegExp", "Object", "Date"], + function (v) { + UE.utils["is" + v] = function (obj) { + return Object.prototype.toString.apply(obj) == "[object " + v + "]"; + }; } - })() -}); -/** - * 判断给定的对象是否是字符串 - * @method isString - * @param { * } object 需要判断的对象 - * @return { Boolean } 给定的对象是否是字符串 - */ - -/** - * 判断给定的对象是否是数组 - * @method isArray - * @param { * } object 需要判断的对象 - * @return { Boolean } 给定的对象是否是数组 - */ - -/** - * 判断给定的对象是否是一个Function - * @method isFunction - * @param { * } object 需要判断的对象 - * @return { Boolean } 给定的对象是否是Function - */ - -/** - * 判断给定的对象是否是Number - * @method isNumber - * @param { * } object 需要判断的对象 - * @return { Boolean } 给定的对象是否是Number - */ - -/** - * 判断给定的对象是否是一个正则表达式 - * @method isRegExp - * @param { * } object 需要判断的对象 - * @return { Boolean } 给定的对象是否是正则表达式 - */ - -/** - * 判断给定的对象是否是一个普通对象 - * @method isObject - * @param { * } object 需要判断的对象 - * @return { Boolean } 给定的对象是否是普通对象 - */ -utils.each( - ["String", "Function", "Array", "Number", "RegExp", "Object", "Date"], - function (v) { - UE.utils["is" + v] = function (obj) { - return Object.prototype.toString.apply(obj) == "[object " + v + "]"; - }; - } -); + ); // core/EventBase.js -/** - * UE采用的事件基类 - * @file - * @module UE - * @class EventBase - * @since 1.2.6.1 - */ - -/** - * UEditor公用空间,UEditor所有的功能都挂载在该空间下 - * @unfile - * @module UE - */ - -/** - * UE采用的事件基类,继承此类的对应类将获取addListener,removeListener,fireEvent方法。 - * 在UE中,Editor以及所有ui实例都继承了该类,故可以在对应的ui对象以及editor对象上使用上述方法。 - * @unfile - * @module UE - * @class EventBase - */ - -/** - * 通过此构造器,子类可以继承EventBase获取事件监听的方法 - * @constructor - * @example - * ```javascript - * UE.EventBase.call(editor); - * ``` - */ -var EventBase = (UE.EventBase = function() {}); - -EventBase.prototype = { - /** - * 注册事件监听器 - * @method addListener - * @param { String } types 监听的事件名称,同时监听多个事件使用空格分隔 - * @param { Function } fn 监听的事件被触发时,会执行该回调函数 - * @waining 事件被触发时,监听的函数假如返回的值恒等于true,回调函数的队列中后面的函数将不执行 - * @example - * ```javascript - * editor.addListener('selectionchange',function(){ - * console.log("选区已经变化!"); - * }) - * editor.addListener('beforegetcontent aftergetcontent',function(type){ - * if(type == 'beforegetcontent'){ - * //do something - * }else{ - * //do something - * } - * console.log(this.getContent) // this是注册的事件的编辑器实例 - * }) - * ``` - * @see UE.EventBase:fireEvent(String) - */ - addListener: function(types, listener) { - types = utils.trim(types).split(/\s+/); - for (var i = 0, ti; (ti = types[i++]); ) { - getListener(this, ti, true).push(listener); - } - }, - - on: function(types, listener) { - return this.addListener(types, listener); - }, - off: function(types, listener) { - return this.removeListener(types, listener); - }, - trigger: function() { - return this.fireEvent.apply(this, arguments); - }, - /** - * 移除事件监听器 - * @method removeListener - * @param { String } types 移除的事件名称,同时移除多个事件使用空格分隔 - * @param { Function } fn 移除监听事件的函数引用 - * @example - * ```javascript - * //changeCallback为方法体 - * editor.removeListener("selectionchange",changeCallback); - * ``` - */ - removeListener: function(types, listener) { - types = utils.trim(types).split(/\s+/); - for (var i = 0, ti; (ti = types[i++]); ) { - utils.removeItem(getListener(this, ti) || [], listener); - } - }, - - /** - * 触发事件 - * @method fireEvent - * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔 - * @remind 该方法会触发addListener - * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值 - * @example - * ```javascript - * editor.fireEvent("selectionchange"); - * ``` + /** + * UE采用的事件基类 + * @file + * @module UE + * @class EventBase + * @since 1.2.6.1 */ - /** - * 触发事件 - * @method fireEvent - * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔 - * @param { *... } options 可选参数,可以传入一个或多个参数,会传给事件触发的回调函数 - * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值 + /** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @unfile + * @module UE + */ + + /** + * UE采用的事件基类,继承此类的对应类将获取addListener,removeListener,fireEvent方法。 + * 在UE中,Editor以及所有ui实例都继承了该类,故可以在对应的ui对象以及editor对象上使用上述方法。 + * @unfile + * @module UE + * @class EventBase + */ + + /** + * 通过此构造器,子类可以继承EventBase获取事件监听的方法 + * @constructor * @example * ```javascript - * - * editor.addListener( "selectionchange", function ( type, arg1, arg2 ) { - * - * console.log( arg1 + " " + arg2 ); - * - * } ); - * - * //触发selectionchange事件, 会执行上面的事件监听器 - * //output: Hello World - * editor.fireEvent("selectionchange", "Hello", "World"); + * UE.EventBase.call(editor); * ``` */ - fireEvent: function() { - var types = arguments[0]; - types = utils.trim(types).split(" "); - for (var i = 0, ti; (ti = types[i++]); ) { - var listeners = getListener(this, ti), - r, - t, - k; - if (listeners) { - k = listeners.length; - while (k--) { - if (!listeners[k]) continue; - t = listeners[k].apply(this, arguments); - if (t === true) { - return t; - } - if (t !== undefined) { - r = t; - } + var EventBase = (UE.EventBase = function () { + }); + + EventBase.prototype = { + /** + * 注册事件监听器 + * @method addListener + * @param { String } types 监听的事件名称,同时监听多个事件使用空格分隔 + * @param { Function } fn 监听的事件被触发时,会执行该回调函数 + * @waining 事件被触发时,监听的函数假如返回的值恒等于true,回调函数的队列中后面的函数将不执行 + * @example + * ```javascript + * editor.addListener('selectionchange',function(){ + * console.log("选区已经变化!"); + * }) + * editor.addListener('beforegetcontent aftergetcontent',function(type){ + * if(type == 'beforegetcontent'){ + * //do something + * }else{ + * //do something + * } + * console.log(this.getContent) // this是注册的事件的编辑器实例 + * }) + * ``` + * @see UE.EventBase:fireEvent(String) + */ + addListener: function (types, listener) { + types = utils.trim(types).split(/\s+/); + for (var i = 0, ti; (ti = types[i++]);) { + getListener(this, ti, true).push(listener); + } + }, + + on: function (types, listener) { + return this.addListener(types, listener); + }, + off: function (types, listener) { + return this.removeListener(types, listener); + }, + trigger: function () { + return this.fireEvent.apply(this, arguments); + }, + /** + * 移除事件监听器 + * @method removeListener + * @param { String } types 移除的事件名称,同时移除多个事件使用空格分隔 + * @param { Function } fn 移除监听事件的函数引用 + * @example + * ```javascript + * //changeCallback为方法体 + * editor.removeListener("selectionchange",changeCallback); + * ``` + */ + removeListener: function (types, listener) { + types = utils.trim(types).split(/\s+/); + for (var i = 0, ti; (ti = types[i++]);) { + utils.removeItem(getListener(this, ti) || [], listener); + } + }, + + /** + * 触发事件 + * @method fireEvent + * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔 + * @remind 该方法会触发addListener + * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值 + * @example + * ```javascript + * editor.fireEvent("selectionchange"); + * ``` + */ + + /** + * 触发事件 + * @method fireEvent + * @param { String } types 触发的事件名称,同时触发多个事件使用空格分隔 + * @param { *... } options 可选参数,可以传入一个或多个参数,会传给事件触发的回调函数 + * @return { * } 返回触发事件的队列中,最后执行的回调函数的返回值 + * @example + * ```javascript + * + * editor.addListener( "selectionchange", function ( type, arg1, arg2 ) { + * + * console.log( arg1 + " " + arg2 ); + * + * } ); + * + * //触发selectionchange事件, 会执行上面的事件监听器 + * //output: Hello World + * editor.fireEvent("selectionchange", "Hello", "World"); + * ``` + */ + fireEvent: function () { + var types = arguments[0]; + types = utils.trim(types).split(" "); + for (var i = 0, ti; (ti = types[i++]);) { + var listeners = getListener(this, ti), + r, + t, + k; + if (listeners) { + k = listeners.length; + while (k--) { + if (!listeners[k]) continue; + t = listeners[k].apply(this, arguments); + if (t === true) { + return t; + } + if (t !== undefined) { + r = t; + } + } + } + if ((t = this["on" + ti.toLowerCase()])) { + r = t.apply(this, arguments); + } + } + return r; } - } - if ((t = this["on" + ti.toLowerCase()])) { - r = t.apply(this, arguments); - } + }; + + /** + * 获得对象所拥有监听类型的所有监听器 + * @unfile + * @module UE + * @since 1.2.6.1 + * @method getListener + * @public + * @param { Object } obj 查询监听器的对象 + * @param { String } type 事件类型 + * @param { Boolean } force 为true且当前所有type类型的侦听器不存在时,创建一个空监听器数组 + * @return { Array } 监听器数组 + */ + function getListener(obj, type, force) { + var allListeners; + type = type.toLowerCase(); + return ( + (allListeners = + obj.__allListeners || (force && (obj.__allListeners = {}))) && + (allListeners[type] || (force && (allListeners[type] = []))) + ); } - return r; - } -}; -/** - * 获得对象所拥有监听类型的所有监听器 - * @unfile - * @module UE - * @since 1.2.6.1 - * @method getListener - * @public - * @param { Object } obj 查询监听器的对象 - * @param { String } type 事件类型 - * @param { Boolean } force 为true且当前所有type类型的侦听器不存在时,创建一个空监听器数组 - * @return { Array } 监听器数组 - */ -function getListener(obj, type, force) { - var allListeners; - type = type.toLowerCase(); - return ( - (allListeners = - obj.__allListeners || (force && (obj.__allListeners = {}))) && - (allListeners[type] || (force && (allListeners[type] = []))) - ); -} // core/dtd.js ///import editor.js ///import core/dom/dom.js ///import core/utils.js -/** - * dtd html语义化的体现类 - * @constructor - * @namespace dtd - */ -var dtd = (dom.dtd = (function() { - function _(s) { - for (var k in s) { - s[k.toUpperCase()] = s[k]; - } - return s; - } - var X = utils.extend2; - var A = _({ isindex: 1, fieldset: 1 }), - B = _({ input: 1, button: 1, select: 1, textarea: 1, label: 1 }), - C = X(_({ a: 1 }), B), - D = X({ iframe: 1 }, C), - E = _({ - hr: 1, - ul: 1, - menu: 1, - div: 1, - blockquote: 1, - noscript: 1, - table: 1, - center: 1, - address: 1, - dir: 1, - pre: 1, - h5: 1, - dl: 1, - h4: 1, - noframes: 1, - h6: 1, - ol: 1, - h1: 1, - h3: 1, - h2: 1 - }), - F = _({ ins: 1, del: 1, script: 1, style: 1 }), - G = X( - _({ - mark: 1, - b: 1, - acronym: 1, - bdo: 1, - var: 1, - "#": 1, - abbr: 1, - code: 1, - br: 1, - i: 1, - cite: 1, - kbd: 1, - u: 1, - strike: 1, - s: 1, - tt: 1, - strong: 1, - q: 1, - samp: 1, - em: 1, - dfn: 1, - span: 1 - }), - F - ), - H = X( - _({ - sub: 1, - img: 1, - embed: 1, - object: 1, - sup: 1, - basefont: 1, - map: 1, - applet: 1, - font: 1, - big: 1, - small: 1 - }), - G - ), - I = X(_({ p: 1 }), H), - J = X(_({ iframe: 1 }), H, B), - K = _({ - img: 1, - embed: 1, - noscript: 1, - br: 1, - kbd: 1, - center: 1, - button: 1, - basefont: 1, - h5: 1, - h4: 1, - samp: 1, - h6: 1, - ol: 1, - h1: 1, - h3: 1, - h2: 1, - form: 1, - font: 1, - "#": 1, - select: 1, - menu: 1, - ins: 1, - abbr: 1, - label: 1, - code: 1, - table: 1, - script: 1, - cite: 1, - input: 1, - iframe: 1, - strong: 1, - textarea: 1, - noframes: 1, - big: 1, - small: 1, - span: 1, - hr: 1, - sub: 1, - bdo: 1, - var: 1, - div: 1, - object: 1, - sup: 1, - strike: 1, - dir: 1, - map: 1, - dl: 1, - applet: 1, - del: 1, - isindex: 1, - fieldset: 1, - ul: 1, - b: 1, - acronym: 1, - a: 1, - blockquote: 1, - i: 1, - u: 1, - s: 1, - tt: 1, - address: 1, - q: 1, - pre: 1, - p: 1, - em: 1, - dfn: 1 - }), - L = X(_({ a: 0 }), J), //a不能被切开,所以把他 - M = _({ tr: 1 }), - N = _({ "#": 1 }), - O = X(_({ param: 1 }), K), - P = X(_({ form: 1 }), A, D, E, I), - Q = _({ li: 1, ol: 1, ul: 1 }), - R = _({ style: 1, script: 1 }), - S = _({ base: 1, link: 1, meta: 1, title: 1 }), - T = X(S, R), - U = _({ head: 1, body: 1 }), - V = _({ html: 1 }); + /** + * dtd html语义化的体现类 + * @constructor + * @namespace dtd + */ + var dtd = (dom.dtd = (function () { + function _(s) { + for (var k in s) { + s[k.toUpperCase()] = s[k]; + } + return s; + } - var block = _({ - address: 1, - blockquote: 1, - center: 1, - dir: 1, - div: 1, - dl: 1, - fieldset: 1, - form: 1, - h1: 1, - h2: 1, - h3: 1, - h4: 1, - h5: 1, - h6: 1, - hr: 1, - isindex: 1, - menu: 1, - noframes: 1, - ol: 1, - p: 1, - pre: 1, - table: 1, - ul: 1 - }), - empty = _({ - area: 1, - base: 1, - basefont: 1, - br: 1, - col: 1, - command: 1, - dialog: 1, - embed: 1, - hr: 1, - img: 1, - input: 1, - isindex: 1, - keygen: 1, - link: 1, - meta: 1, - param: 1, - source: 1, - track: 1, - wbr: 1 - }); + var X = utils.extend2; + var A = _({isindex: 1, fieldset: 1}), + B = _({input: 1, button: 1, select: 1, textarea: 1, label: 1}), + C = X(_({a: 1}), B), + D = X({iframe: 1}, C), + E = _({ + hr: 1, + ul: 1, + menu: 1, + div: 1, + blockquote: 1, + noscript: 1, + table: 1, + center: 1, + address: 1, + dir: 1, + pre: 1, + h5: 1, + dl: 1, + h4: 1, + noframes: 1, + h6: 1, + ol: 1, + h1: 1, + h3: 1, + h2: 1 + }), + F = _({ins: 1, del: 1, script: 1, style: 1}), + G = X( + _({ + mark: 1, + b: 1, + acronym: 1, + bdo: 1, + var: 1, + "#": 1, + abbr: 1, + code: 1, + br: 1, + i: 1, + cite: 1, + kbd: 1, + u: 1, + strike: 1, + s: 1, + tt: 1, + strong: 1, + q: 1, + samp: 1, + em: 1, + dfn: 1, + span: 1 + }), + F + ), + H = X( + _({ + sub: 1, + img: 1, + embed: 1, + object: 1, + sup: 1, + basefont: 1, + map: 1, + applet: 1, + font: 1, + big: 1, + small: 1 + }), + G + ), + I = X(_({p: 1}), H), + J = X(_({iframe: 1}), H, B), + K = _({ + img: 1, + embed: 1, + noscript: 1, + br: 1, + kbd: 1, + center: 1, + button: 1, + basefont: 1, + h5: 1, + h4: 1, + samp: 1, + h6: 1, + ol: 1, + h1: 1, + h3: 1, + h2: 1, + form: 1, + font: 1, + "#": 1, + select: 1, + menu: 1, + ins: 1, + abbr: 1, + label: 1, + code: 1, + table: 1, + script: 1, + cite: 1, + input: 1, + iframe: 1, + strong: 1, + textarea: 1, + noframes: 1, + big: 1, + small: 1, + span: 1, + hr: 1, + sub: 1, + bdo: 1, + var: 1, + div: 1, + object: 1, + sup: 1, + strike: 1, + dir: 1, + map: 1, + dl: 1, + applet: 1, + del: 1, + isindex: 1, + fieldset: 1, + ul: 1, + b: 1, + acronym: 1, + a: 1, + blockquote: 1, + i: 1, + u: 1, + s: 1, + tt: 1, + address: 1, + q: 1, + pre: 1, + p: 1, + em: 1, + dfn: 1 + }), + L = X(_({a: 0}), J), //a不能被切开,所以把他 + M = _({tr: 1}), + N = _({"#": 1}), + O = X(_({param: 1}), K), + P = X(_({form: 1}), A, D, E, I), + Q = _({li: 1, ol: 1, ul: 1}), + R = _({style: 1, script: 1}), + S = _({base: 1, link: 1, meta: 1, title: 1}), + T = X(S, R), + U = _({head: 1, body: 1}), + V = _({html: 1}); - return _({ - // $ 表示自定的属性 + var block = _({ + address: 1, + blockquote: 1, + center: 1, + dir: 1, + div: 1, + dl: 1, + fieldset: 1, + form: 1, + h1: 1, + h2: 1, + h3: 1, + h4: 1, + h5: 1, + h6: 1, + hr: 1, + isindex: 1, + menu: 1, + noframes: 1, + ol: 1, + p: 1, + pre: 1, + table: 1, + ul: 1 + }), + empty = _({ + area: 1, + base: 1, + basefont: 1, + br: 1, + col: 1, + command: 1, + dialog: 1, + embed: 1, + hr: 1, + img: 1, + input: 1, + isindex: 1, + keygen: 1, + link: 1, + meta: 1, + param: 1, + source: 1, + track: 1, + wbr: 1 + }); - // body外的元素列表. - $nonBodyContent: X(V, U, S), + return _({ + // $ 表示自定的属性 - //块结构元素列表 - $block: block, + // body外的元素列表. + $nonBodyContent: X(V, U, S), - //内联元素列表 - $inline: L, + //块结构元素列表 + $block: block, - $inlineWithA: X(_({ a: 1 }), L), + //内联元素列表 + $inline: L, - $body: X(_({ script: 1, style: 1 }), block), + $inlineWithA: X(_({a: 1}), L), - $cdata: _({ script: 1, style: 1 }), + $body: X(_({script: 1, style: 1}), block), - //自闭和元素 - $empty: empty, + $cdata: _({script: 1, style: 1}), - //不是自闭合,但不能让range选中里边 - $nonChild: _({ iframe: 1, textarea: 1 }), - //列表元素列表 - $listItem: _({ dd: 1, dt: 1, li: 1 }), + //自闭和元素 + $empty: empty, - //列表根元素列表 - $list: _({ ul: 1, ol: 1, dl: 1 }), + //不是自闭合,但不能让range选中里边 + $nonChild: _({iframe: 1, textarea: 1}), + //列表元素列表 + $listItem: _({dd: 1, dt: 1, li: 1}), - //不能认为是空的元素 - $isNotEmpty: _({ - table: 1, - ul: 1, - ol: 1, - dl: 1, - iframe: 1, - area: 1, - base: 1, - col: 1, - hr: 1, - img: 1, - embed: 1, - input: 1, - textarea: 1, - link: 1, - meta: 1, - param: 1, - h1: 1, - h2: 1, - h3: 1, - h4: 1, - h5: 1, - h6: 1 - }), + //列表根元素列表 + $list: _({ul: 1, ol: 1, dl: 1}), - //如果没有子节点就可以删除的元素列表,像span,a - $removeEmpty: _({ - a: 1, - abbr: 1, - acronym: 1, - address: 1, - b: 1, - bdo: 1, - big: 1, - cite: 1, - code: 1, - del: 1, - dfn: 1, - em: 1, - font: 1, - i: 1, - ins: 1, - label: 1, - kbd: 1, - q: 1, - s: 1, - samp: 1, - small: 1, - span: 1, - strike: 1, - strong: 1, - sub: 1, - sup: 1, - tt: 1, - u: 1, - var: 1 - }), + //不能认为是空的元素 + $isNotEmpty: _({ + table: 1, + ul: 1, + ol: 1, + dl: 1, + iframe: 1, + area: 1, + base: 1, + col: 1, + hr: 1, + img: 1, + embed: 1, + input: 1, + textarea: 1, + link: 1, + meta: 1, + param: 1, + h1: 1, + h2: 1, + h3: 1, + h4: 1, + h5: 1, + h6: 1 + }), - $removeEmptyBlock: _({ p: 1, div: 1 }), + //如果没有子节点就可以删除的元素列表,像span,a + $removeEmpty: _({ + a: 1, + abbr: 1, + acronym: 1, + address: 1, + b: 1, + bdo: 1, + big: 1, + cite: 1, + code: 1, + del: 1, + dfn: 1, + em: 1, + font: 1, + i: 1, + ins: 1, + label: 1, + kbd: 1, + q: 1, + s: 1, + samp: 1, + small: 1, + span: 1, + strike: 1, + strong: 1, + sub: 1, + sup: 1, + tt: 1, + u: 1, + var: 1 + }), - //在table元素里的元素列表 - $tableContent: _({ - caption: 1, - col: 1, - colgroup: 1, - tbody: 1, - td: 1, - tfoot: 1, - th: 1, - thead: 1, - tr: 1, - table: 1 - }), - //不转换的标签 - $notTransContent: _({ pre: 1, script: 1, style: 1, textarea: 1 }), - html: U, - head: T, - style: N, - script: N, - body: P, - base: {}, - link: {}, - meta: {}, - title: N, - col: {}, - tr: _({ td: 1, th: 1 }), - img: {}, - embed: {}, - colgroup: _({ thead: 1, col: 1, tbody: 1, tr: 1, tfoot: 1 }), - noscript: P, - td: P, - br: {}, - th: P, - center: P, - kbd: L, - button: X(I, E), - basefont: {}, - h5: L, - h4: L, - samp: L, - h6: L, - ol: Q, - h1: L, - h3: L, - option: N, - h2: L, - form: X(A, D, E, I), - select: _({ optgroup: 1, option: 1 }), - font: L, - ins: L, - menu: Q, - abbr: L, - label: L, - table: _({ - thead: 1, - col: 1, - tbody: 1, - tr: 1, - colgroup: 1, - caption: 1, - tfoot: 1 - }), - code: L, - tfoot: M, - cite: L, - li: P, - input: {}, - iframe: P, - strong: L, - textarea: N, - noframes: P, - big: L, - small: L, - //trace: - span: _({ - "#": 1, - br: 1, - b: 1, - strong: 1, - u: 1, - i: 1, - em: 1, - sub: 1, - sup: 1, - strike: 1, - span: 1 - }), - hr: L, - dt: L, - sub: L, - optgroup: _({ option: 1 }), - param: {}, - bdo: L, - var: L, - div: P, - object: O, - sup: L, - dd: P, - strike: L, - area: {}, - dir: Q, - map: X(_({ area: 1, form: 1, p: 1 }), A, F, E), - applet: O, - dl: _({ dt: 1, dd: 1 }), - del: L, - isindex: {}, - fieldset: X(_({ legend: 1 }), K), - thead: M, - ul: Q, - acronym: L, - b: L, - a: X(_({ a: 1 }), J), - blockquote: X(_({ td: 1, tr: 1, tbody: 1, li: 1 }), P), - caption: L, - i: L, - u: L, - tbody: M, - s: L, - address: X(D, I), - tt: L, - legend: L, - q: L, - pre: X(G, C), - p: X(_({ a: 1 }), L), - em: L, - dfn: L, - mark: L - }); -})()); + $removeEmptyBlock: _({p: 1, div: 1}), + + //在table元素里的元素列表 + $tableContent: _({ + caption: 1, + col: 1, + colgroup: 1, + tbody: 1, + td: 1, + tfoot: 1, + th: 1, + thead: 1, + tr: 1, + table: 1 + }), + //不转换的标签 + $notTransContent: _({pre: 1, script: 1, style: 1, textarea: 1}), + html: U, + head: T, + style: N, + script: N, + body: P, + base: {}, + link: {}, + meta: {}, + title: N, + col: {}, + tr: _({td: 1, th: 1}), + img: {}, + embed: {}, + colgroup: _({thead: 1, col: 1, tbody: 1, tr: 1, tfoot: 1}), + noscript: P, + td: P, + br: {}, + th: P, + center: P, + kbd: L, + button: X(I, E), + basefont: {}, + h5: L, + h4: L, + samp: L, + h6: L, + ol: Q, + h1: L, + h3: L, + option: N, + h2: L, + form: X(A, D, E, I), + select: _({optgroup: 1, option: 1}), + font: L, + ins: L, + menu: Q, + abbr: L, + label: L, + table: _({ + thead: 1, + col: 1, + tbody: 1, + tr: 1, + colgroup: 1, + caption: 1, + tfoot: 1 + }), + code: L, + tfoot: M, + cite: L, + li: P, + input: {}, + iframe: P, + strong: L, + textarea: N, + noframes: P, + big: L, + small: L, + //trace: + span: _({ + "#": 1, + br: 1, + b: 1, + strong: 1, + u: 1, + i: 1, + em: 1, + sub: 1, + sup: 1, + strike: 1, + span: 1 + }), + hr: L, + dt: L, + sub: L, + optgroup: _({option: 1}), + param: {}, + bdo: L, + var: L, + div: P, + object: O, + sup: L, + dd: P, + strike: L, + area: {}, + dir: Q, + map: X(_({area: 1, form: 1, p: 1}), A, F, E), + applet: O, + dl: _({dt: 1, dd: 1}), + del: L, + isindex: {}, + fieldset: X(_({legend: 1}), K), + thead: M, + ul: Q, + acronym: L, + b: L, + a: X(_({a: 1}), J), + blockquote: X(_({td: 1, tr: 1, tbody: 1, li: 1}), P), + caption: L, + i: L, + u: L, + tbody: M, + s: L, + address: X(D, I), + tt: L, + legend: L, + q: L, + pre: X(G, C), + p: X(_({a: 1}), L), + em: L, + dfn: L, + mark: L + }); + })()); // core/domUtils.js -/** - * Dom操作工具包 - * @file - * @module UE.dom.domUtils - * @since 1.2.6.1 - */ - -/** - * Dom操作工具包 - * @unfile - * @module UE.dom.domUtils - */ -function getDomNode(node, start, ltr, startFromChild, fn, guard) { - var tmpNode = startFromChild && node[start], - parent; - !tmpNode && (tmpNode = node[ltr]); - while (!tmpNode && (parent = (parent || node).parentNode)) { - if (parent.tagName == "BODY" || (guard && !guard(parent))) { - return null; - } - tmpNode = parent[ltr]; - } - if (tmpNode && fn && !fn(tmpNode)) { - return getDomNode(tmpNode, start, ltr, false, fn); - } - return tmpNode; -} -var attrFix = ie && browser.version < 9 - ? { - tabindex: "tabIndex", - readonly: "readOnly", - for: "htmlFor", - class: "className", - maxlength: "maxLength", - cellspacing: "cellSpacing", - cellpadding: "cellPadding", - rowspan: "rowSpan", - colspan: "colSpan", - usemap: "useMap", - frameborder: "frameBorder" - } - : { - tabindex: "tabIndex", - readonly: "readOnly" - }, - styleBlock = utils.listToMap([ - "-webkit-box", - "-moz-box", - "block", - "list-item", - "table", - "table-row-group", - "table-header-group", - "table-footer-group", - "table-row", - "table-column-group", - "table-column", - "table-cell", - "table-caption" - ]); -var domUtils = (dom.domUtils = { - //节点常量 - NODE_ELEMENT: 1, - NODE_DOCUMENT: 9, - NODE_TEXT: 3, - NODE_COMMENT: 8, - NODE_DOCUMENT_FRAGMENT: 11, - - //位置关系 - POSITION_IDENTICAL: 0, - POSITION_DISCONNECTED: 1, - POSITION_FOLLOWING: 2, - POSITION_PRECEDING: 4, - POSITION_IS_CONTAINED: 8, - POSITION_CONTAINS: 16, - //ie6使用其他的会有一段空白出现 - fillChar: ie && browser.version === "6" ? "\ufeff" : "\u200B", - //-------------------------Node部分-------------------------------- - keys: { - /*Backspace*/ 8: 1, - /*Delete*/ 46: 1, - /*Shift*/ 16: 1, - /*Ctrl*/ 17: 1, - /*Alt*/ 18: 1, - 37: 1, - 38: 1, - 39: 1, - 40: 1, - 13: 1 /*enter*/ - }, - /** - * 获取节点A相对于节点B的位置关系 - * @method getPosition - * @param { Node } nodeA 需要查询位置关系的节点A - * @param { Node } nodeB 需要查询位置关系的节点B - * @return { Number } 节点A与节点B的关系 - * @example - * ```javascript - * //output: 20 - * var position = UE.dom.domUtils.getPosition( document.documentElement, document.body ); - * - * switch ( position ) { - * - * //0 - * case UE.dom.domUtils.POSITION_IDENTICAL: - * console.log('元素相同'); - * break; - * //1 - * case UE.dom.domUtils.POSITION_DISCONNECTED: - * console.log('两个节点在不同的文档中'); - * break; - * //2 - * case UE.dom.domUtils.POSITION_FOLLOWING: - * console.log('节点A在节点B之后'); - * break; - * //4 - * case UE.dom.domUtils.POSITION_PRECEDING; - * console.log('节点A在节点B之前'); - * break; - * //8 - * case UE.dom.domUtils.POSITION_IS_CONTAINED: - * console.log('节点A被节点B包含'); - * break; - * case 10: - * console.log('节点A被节点B包含且节点A在节点B之后'); - * break; - * //16 - * case UE.dom.domUtils.POSITION_CONTAINS: - * console.log('节点A包含节点B'); - * break; - * case 20: - * console.log('节点A包含节点B且节点A在节点B之前'); - * break; - * - * } - * ``` - */ - getPosition: function(nodeA, nodeB) { - // 如果两个节点是同一个节点 - if (nodeA === nodeB) { - // domUtils.POSITION_IDENTICAL - return 0; - } - var node, - parentsA = [nodeA], - parentsB = [nodeB]; - node = nodeA; - while ((node = node.parentNode)) { - // 如果nodeB是nodeA的祖先节点 - if (node === nodeB) { - // domUtils.POSITION_IS_CONTAINED + domUtils.POSITION_FOLLOWING - return 10; - } - parentsA.push(node); - } - node = nodeB; - while ((node = node.parentNode)) { - // 如果nodeA是nodeB的祖先节点 - if (node === nodeA) { - // domUtils.POSITION_CONTAINS + domUtils.POSITION_PRECEDING - return 20; - } - parentsB.push(node); - } - parentsA.reverse(); - parentsB.reverse(); - if (parentsA[0] !== parentsB[0]) { - // domUtils.POSITION_DISCONNECTED - return 1; - } - var i = -1; - while ((i++, parentsA[i] === parentsB[i])) {} - nodeA = parentsA[i]; - nodeB = parentsB[i]; - while ((nodeA = nodeA.nextSibling)) { - if (nodeA === nodeB) { - // domUtils.POSITION_PRECEDING - return 4; - } - } - // domUtils.POSITION_FOLLOWING - return 2; - }, - - /** - * 检测节点node在父节点中的索引位置 - * @method getNodeIndex - * @param { Node } node 需要检测的节点对象 - * @return { Number } 该节点在父节点中的位置 - * @see UE.dom.domUtils.getNodeIndex(Node,Boolean) + /** + * Dom操作工具包 + * @file + * @module UE.dom.domUtils + * @since 1.2.6.1 */ - /** - * 检测节点node在父节点中的索引位置, 根据给定的mergeTextNode参数决定是否要合并多个连续的文本节点为一个节点 - * @method getNodeIndex - * @param { Node } node 需要检测的节点对象 - * @param { Boolean } mergeTextNode 是否合并多个连续的文本节点为一个节点 - * @return { Number } 该节点在父节点中的位置 - * @example - * ```javascript - * - * var node = document.createElement("div"); - * - * node.appendChild( document.createTextNode( "hello" ) ); - * node.appendChild( document.createTextNode( "world" ) ); - * node.appendChild( node = document.createElement( "div" ) ); - * - * //output: 2 - * console.log( UE.dom.domUtils.getNodeIndex( node ) ); - * - * //output: 1 - * console.log( UE.dom.domUtils.getNodeIndex( node, true ) ); - * - * ``` + /** + * Dom操作工具包 + * @unfile + * @module UE.dom.domUtils */ - getNodeIndex: function(node, ignoreTextNode) { - var preNode = node, - i = 0; - while ((preNode = preNode.previousSibling)) { - if (ignoreTextNode && preNode.nodeType == 3) { - if (preNode.nodeType != preNode.nextSibling.nodeType) { - i++; - } - continue; - } - i++; - } - return i; - }, - - /** - * 检测节点node是否在给定的document对象上 - * @method inDoc - * @param { Node } node 需要检测的节点对象 - * @param { DomDocument } doc 需要检测的document对象 - * @return { Boolean } 该节点node是否在给定的document的dom树上 - * @example - * ```javascript - * - * var node = document.createElement("div"); - * - * //output: false - * console.log( UE.do.domUtils.inDoc( node, document ) ); - * - * document.body.appendChild( node ); - * - * //output: true - * console.log( UE.do.domUtils.inDoc( node, document ) ); - * - * ``` - */ - inDoc: function(node, doc) { - return domUtils.getPosition(node, doc) === 10; - }, - /** - * 根据给定的过滤规则filterFn, 查找符合该过滤规则的node节点的第一个祖先节点, - * 查找的起点是给定node节点的父节点。 - * @method findParent - * @param { Node } node 需要查找的节点 - * @param { Function } filterFn 自定义的过滤方法。 - * @warning 查找的终点是到body节点为止 - * @remind 自定义的过滤方法filterFn接受一个Node对象作为参数, 该对象代表当前执行检测的祖先节点。 如果该 - * 节点满足过滤条件, 则要求返回true, 这时将直接返回该节点作为findParent()的结果, 否则, 请返回false。 - * @return { Node | Null } 如果找到符合过滤条件的节点, 就返回该节点, 否则返回NULL - * @example - * ```javascript - * var filterNode = UE.dom.domUtils.findParent( document.body.firstChild, function ( node ) { - * - * //由于查找的终点是body节点, 所以永远也不会匹配当前过滤器的条件, 即这里永远会返回false - * return node.tagName === "HTML"; - * - * } ); - * - * //output: true - * console.log( filterNode === null ); - * ``` - */ - - /** - * 根据给定的过滤规则filterFn, 查找符合该过滤规则的node节点的第一个祖先节点, - * 如果includeSelf的值为true,则查找的起点是给定的节点node, 否则, 起点是node的父节点 - * @method findParent - * @param { Node } node 需要查找的节点 - * @param { Function } filterFn 自定义的过滤方法。 - * @param { Boolean } includeSelf 查找过程是否包含自身 - * @warning 查找的终点是到body节点为止 - * @remind 自定义的过滤方法filterFn接受一个Node对象作为参数, 该对象代表当前执行检测的祖先节点。 如果该 - * 节点满足过滤条件, 则要求返回true, 这时将直接返回该节点作为findParent()的结果, 否则, 请返回false。 - * @remind 如果includeSelf为true, 则过滤器第一次执行时的参数会是节点本身。 - * 反之, 过滤器第一次执行时的参数将是该节点的父节点。 - * @return { Node | Null } 如果找到符合过滤条件的节点, 就返回该节点, 否则返回NULL - * @example - * ```html - * - * - *
- *
- * - * - * - * ``` - */ - findParent: function(node, filterFn, includeSelf) { - if (node && !domUtils.isBody(node)) { - node = includeSelf ? node : node.parentNode; - while (node) { - if (!filterFn || filterFn(node) || domUtils.isBody(node)) { - return filterFn && !filterFn(node) && domUtils.isBody(node) - ? null - : node; - } - node = node.parentNode; - } - } - return null; - }, - /** - * 查找node的节点名为tagName的第一个祖先节点, 查找的起点是node节点的父节点。 - * @method findParentByTagName - * @param { Node } node 需要查找的节点对象 - * @param { Array } tagNames 需要查找的父节点的名称数组 - * @warning 查找的终点是到body节点为止 - * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL - * @example - * ```javascript - * var node = UE.dom.domUtils.findParentByTagName( document.getElementsByTagName("div")[0], [ "BODY" ] ); - * //output: BODY - * console.log( node.tagName ); - * ``` - */ - - /** - * 查找node的节点名为tagName的祖先节点, 如果includeSelf的值为true,则查找的起点是给定的节点node, - * 否则, 起点是node的父节点。 - * @method findParentByTagName - * @param { Node } node 需要查找的节点对象 - * @param { Array } tagNames 需要查找的父节点的名称数组 - * @param { Boolean } includeSelf 查找过程是否包含node节点自身 - * @warning 查找的终点是到body节点为止 - * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL - * @example - * ```javascript - * var queryTarget = document.getElementsByTagName("div")[0]; - * var node = UE.dom.domUtils.findParentByTagName( queryTarget, [ "DIV" ], true ); - * //output: true - * console.log( queryTarget === node ); - * ``` - */ - findParentByTagName: function(node, tagNames, includeSelf, excludeFn) { - tagNames = utils.listToMap(utils.isArray(tagNames) ? tagNames : [tagNames]); - return domUtils.findParent( - node, - function(node) { - return tagNames[node.tagName] && !(excludeFn && excludeFn(node)); - }, - includeSelf - ); - }, - /** - * 查找节点node的祖先节点集合, 查找的起点是给定节点的父节点,结果集中不包含给定的节点。 - * @method findParents - * @param { Node } node 需要查找的节点对象 - * @return { Array } 给定节点的祖先节点数组 - * @grammar UE.dom.domUtils.findParents(node) => Array //返回一个祖先节点数组集合,不包含自身 - * @grammar UE.dom.domUtils.findParents(node,includeSelf) => Array //返回一个祖先节点数组集合,includeSelf指定是否包含自身 - * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn) => Array //返回一个祖先节点数组集合,filterFn指定过滤条件,返回true的node将被选取 - * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn,closerFirst) => Array //返回一个祖先节点数组集合,closerFirst为true的话,node的直接父亲节点是数组的第0个 - */ - - /** - * 查找节点node的祖先节点集合, 如果includeSelf的值为true, - * 则返回的结果集中允许出现当前给定的节点, 否则, 该节点不会出现在其结果集中。 - * @method findParents - * @param { Node } node 需要查找的节点对象 - * @param { Boolean } includeSelf 查找的结果中是否允许包含当前查找的节点对象 - * @return { Array } 给定节点的祖先节点数组 - */ - findParents: function(node, includeSelf, filterFn, closerFirst) { - var parents = includeSelf && ((filterFn && filterFn(node)) || !filterFn) - ? [node] - : []; - while ((node = domUtils.findParent(node, filterFn))) { - parents.push(node); - } - return closerFirst ? parents : parents.reverse(); - }, - - /** - * 在节点node后面插入新节点newNode - * @method insertAfter - * @param { Node } node 目标节点 - * @param { Node } newNode 新插入的节点, 该节点将置于目标节点之后 - * @return { Node } 新插入的节点 - */ - insertAfter: function(node, newNode) { - return node.nextSibling - ? node.parentNode.insertBefore(newNode, node.nextSibling) - : node.parentNode.appendChild(newNode); - }, - - /** - * 删除节点node及其下属的所有节点 - * @method remove - * @param { Node } node 需要删除的节点对象 - * @return { Node } 返回刚删除的节点对象 - * @example - * ```html - *
- *
你好
- *
- * - * ``` - */ - - /** - * 删除节点node,并根据keepChildren的值决定是否保留子节点 - * @method remove - * @param { Node } node 需要删除的节点对象 - * @param { Boolean } keepChildren 是否需要保留子节点 - * @return { Node } 返回刚删除的节点对象 - * @example - * ```html - *
- *
你好
- *
- * - * ``` - */ - remove: function(node, keepChildren) { - var parent = node.parentNode, - child; - if (parent) { - if (keepChildren && node.hasChildNodes()) { - while ((child = node.firstChild)) { - parent.insertBefore(child, node); - } - } - parent.removeChild(node); - } - return node; - }, - - /** - * 取得node节点的下一个兄弟节点, 如果该节点其后没有兄弟节点, 则递归查找其父节点之后的第一个兄弟节点, - * 直到找到满足条件的节点或者递归到BODY节点之后才会结束。 - * @method getNextDomNode - * @param { Node } node 需要获取其后的兄弟节点的节点对象 - * @return { Node | NULL } 如果找满足条件的节点, 则返回该节点, 否则返回NULL - * @example - * ```html - * - *
- * - *
- * xxx - * - * - * ``` - * @example - * ```html - * - *
- * - * xxx - *
- * xxx - * - * - * ``` - */ - - /** - * 取得node节点的下一个兄弟节点, 如果startFromChild的值为ture,则先获取其子节点, - * 如果有子节点则直接返回第一个子节点;如果没有子节点或者startFromChild的值为false, - * 则执行getNextDomNode(Node node)的查找过程。 - * @method getNextDomNode - * @param { Node } node 需要获取其后的兄弟节点的节点对象 - * @param { Boolean } startFromChild 查找过程是否从其子节点开始 - * @return { Node | NULL } 如果找满足条件的节点, 则返回该节点, 否则返回NULL - * @see UE.dom.domUtils.getNextDomNode(Node) - */ - getNextDomNode: function(node, startFromChild, filterFn, guard) { - return getDomNode( - node, - "firstChild", - "nextSibling", - startFromChild, - filterFn, - guard - ); - }, - getPreDomNode: function(node, startFromChild, filterFn, guard) { - return getDomNode( - node, - "lastChild", - "previousSibling", - startFromChild, - filterFn, - guard - ); - }, - /** - * 检测节点node是否属是UEditor定义的bookmark节点 - * @method isBookmarkNode - * @private - * @param { Node } node 需要检测的节点对象 - * @return { Boolean } 是否是bookmark节点 - * @example - * ```html - * - * - * ``` - */ - isBookmarkNode: function(node) { - return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id); - }, - /** - * 获取节点node所属的window对象 - * @method getWindow - * @param { Node } node 节点对象 - * @return { Window } 当前节点所属的window对象 - * @example - * ```javascript - * //output: true - * console.log( UE.dom.domUtils.getWindow( document.body ) === window ); - * ``` - */ - getWindow: function(node) { - var doc = node.ownerDocument || node; - return doc.defaultView || doc.parentWindow; - }, - /** - * 获取离nodeA与nodeB最近的公共的祖先节点 - * @method getCommonAncestor - * @param { Node } nodeA 第一个节点 - * @param { Node } nodeB 第二个节点 - * @remind 如果给定的两个节点是同一个节点, 将直接返回该节点。 - * @return { Node | NULL } 如果未找到公共节点, 返回NULL, 否则返回最近的公共祖先节点。 - * @example - * ```javascript - * var commonAncestor = UE.dom.domUtils.getCommonAncestor( document.body, document.body.firstChild ); - * //output: true - * console.log( commonAncestor.tagName.toLowerCase() === 'body' ); - * ``` - */ - getCommonAncestor: function(nodeA, nodeB) { - if (nodeA === nodeB) return nodeA; - var parentsA = [nodeA], - parentsB = [nodeB], - parent = nodeA, - i = -1; - while ((parent = parent.parentNode)) { - if (parent === nodeB) { - return parent; - } - parentsA.push(parent); - } - parent = nodeB; - while ((parent = parent.parentNode)) { - if (parent === nodeA) return parent; - parentsB.push(parent); - } - parentsA.reverse(); - parentsB.reverse(); - while ((i++, parentsA[i] === parentsB[i])) {} - return i == 0 ? null : parentsA[i - 1]; - }, - /** - * 清除node节点左右连续为空的兄弟inline节点 - * @method clearEmptySibling - * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, - * 则这些兄弟节点将被删除 - * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext) //ignoreNext指定是否忽略右边空节点 - * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext,ignorePre) //ignorePre指定是否忽略左边空节点 - * @example - * ```html - * - *
- * - * - * - * xxx - * - * - * - * ``` - */ - - /** - * 清除node节点左右连续为空的兄弟inline节点, 如果ignoreNext的值为true, - * 则忽略对右边兄弟节点的操作。 - * @method clearEmptySibling - * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, - * @param { Boolean } ignoreNext 是否忽略忽略对右边的兄弟节点的操作 - * 则这些兄弟节点将被删除 - * @see UE.dom.domUtils.clearEmptySibling(Node) - */ - - /** - * 清除node节点左右连续为空的兄弟inline节点, 如果ignoreNext的值为true, - * 则忽略对右边兄弟节点的操作, 如果ignorePre的值为true,则忽略对左边兄弟节点的操作。 - * @method clearEmptySibling - * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, - * @param { Boolean } ignoreNext 是否忽略忽略对右边的兄弟节点的操作 - * @param { Boolean } ignorePre 是否忽略忽略对左边的兄弟节点的操作 - * 则这些兄弟节点将被删除 - * @see UE.dom.domUtils.clearEmptySibling(Node) - */ - clearEmptySibling: function(node, ignoreNext, ignorePre) { - function clear(next, dir) { - var tmpNode; - while ( - next && - !domUtils.isBookmarkNode(next) && - (domUtils.isEmptyInlineElement(next) || - //这里不能把空格算进来会吧空格干掉,出现文字间的空格丢掉了 - !new RegExp("[^\t\n\r" + domUtils.fillChar + "]").test( - next.nodeValue - )) - ) { - tmpNode = next[dir]; - domUtils.remove(next); - next = tmpNode; - } - } - !ignoreNext && clear(node.nextSibling, "nextSibling"); - !ignorePre && clear(node.previousSibling, "previousSibling"); - }, - /** - * 将一个文本节点textNode拆分成两个文本节点,offset指定拆分位置 - * @method split - * @param { Node } textNode 需要拆分的文本节点对象 - * @param { int } offset 需要拆分的位置, 位置计算从0开始 - * @return { Node } 拆分后形成的新节点 - * @example - * ```html - *
abcdef
- * - * ``` - */ - split: function(node, offset) { - var doc = node.ownerDocument; - if (browser.ie && offset == node.nodeValue.length) { - var next = doc.createTextNode(""); - return domUtils.insertAfter(node, next); - } - var retval = node.splitText(offset); - //ie8下splitText不会跟新childNodes,我们手动触发他的更新 - if (browser.ie8) { - var tmpNode = doc.createTextNode(""); - domUtils.insertAfter(retval, tmpNode); - domUtils.remove(tmpNode); - } - return retval; - }, - - /** - * 检测文本节点textNode是否为空节点(包括空格、换行、占位符等字符) - * @method isWhitespace - * @param { Node } node 需要检测的节点对象 - * @return { Boolean } 检测的节点是否为空 - * @example - * ```html - *
- * - *
- * - * ``` - */ - isWhitespace: function(node) { - return !new RegExp("[^ \t\n\r" + domUtils.fillChar + "]").test( - node.nodeValue - ); - }, - /** - * 获取元素element相对于viewport的位置坐标 - * @method getXY - * @param { Node } element 需要计算位置的节点对象 - * @return { Object } 返回形如{x:left,y:top}的一个key-value映射对象, 其中键x代表水平偏移距离, - * y代表垂直偏移距离。 - * - * @example - * ```javascript - * var location = UE.dom.domUtils.getXY( document.getElementById("test") ); - * //output: test的坐标为: 12, 24 - * console.log( 'test的坐标为: ', location.x, ',', location.y ); - * ``` - */ - getXY: function(element) { - var x = 0, - y = 0; - while (element.offsetParent) { - y += element.offsetTop; - x += element.offsetLeft; - element = element.offsetParent; - } - return { x: x, y: y }; - }, - /** - * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数 - * @method on - * @param { Node } element 需要绑定事件的节点对象 - * @param { String } type 绑定的事件类型 - * @param { Function } handler 事件处理器 - * @example - * ```javascript - * UE.dom.domUtils.on(document.body,"click",function(e){ - * //e为事件对象,this为被点击元素对戏那个 - * }); - * ``` - */ - - /** - * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数 - * @method on - * @param { Node } element 需要绑定事件的节点对象 - * @param {string} type 绑定的事件类型数组 - * @param { Function } handler 事件处理器 - * @example - * ```javascript - * UE.dom.domUtils.on(document.body,["click","mousedown"],function(evt){ - * //evt为事件对象,this为被点击元素对象 - * }); - * ``` - */ - on: function(element, type, handler) { - var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/), - k = types.length; - if (k) - while (k--) { - type = types[k]; - if (element.addEventListener) { - element.addEventListener(type, handler, false); - } else { - if (!handler._d) { - handler._d = { - els: [] - }; - } - var key = type + handler.toString(), - index = utils.indexOf(handler._d.els, element); - if (!handler._d[key] || index == -1) { - if (index == -1) { - handler._d.els.push(element); + function getDomNode(node, start, ltr, startFromChild, fn, guard) { + var tmpNode = startFromChild && node[start], + parent; + !tmpNode && (tmpNode = node[ltr]); + while (!tmpNode && (parent = (parent || node).parentNode)) { + if (parent.tagName == "BODY" || (guard && !guard(parent))) { + return null; } - if (!handler._d[key]) { - handler._d[key] = function(evt) { - return handler.call(evt.srcElement, evt || window.event); - }; - } - - element.attachEvent("on" + type, handler._d[key]); - } + tmpNode = parent[ltr]; } - } - element = null; - }, - /** - * 解除DOM事件绑定 - * @method un - * @param { Node } element 需要解除事件绑定的节点对象 - * @param { String } type 需要接触绑定的事件类型 - * @param { Function } handler 对应的事件处理器 - * @example - * ```javascript - * UE.dom.domUtils.un(document.body,"click",function(evt){ - * //evt为事件对象,this为被点击元素对象 - * }); - * ``` - */ + if (tmpNode && fn && !fn(tmpNode)) { + return getDomNode(tmpNode, start, ltr, false, fn); + } + return tmpNode; + } - /** - * 解除DOM事件绑定 - * @method un - * @param { Node } element 需要解除事件绑定的节点对象 - * @param { Array } type 需要接触绑定的事件类型数组 - * @param { Function } handler 对应的事件处理器 - * @example - * ```javascript - * UE.dom.domUtils.un(document.body, ["click","mousedown"],function(evt){ - * //evt为事件对象,this为被点击元素对象 - * }); - * ``` - */ - un: function(element, type, handler) { - var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/), - k = types.length; - if (k) - while (k--) { - type = types[k]; - if (element.removeEventListener) { - element.removeEventListener(type, handler, false); - } else { - var key = type + handler.toString(); - try { - element.detachEvent( - "on" + type, - handler._d ? handler._d[key] : handler + var attrFix = ie && browser.version < 9 + ? { + tabindex: "tabIndex", + readonly: "readOnly", + for: "htmlFor", + class: "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder" + } + : { + tabindex: "tabIndex", + readonly: "readOnly" + }, + styleBlock = utils.listToMap([ + "-webkit-box", + "-moz-box", + "block", + "list-item", + "table", + "table-row-group", + "table-header-group", + "table-footer-group", + "table-row", + "table-column-group", + "table-column", + "table-cell", + "table-caption" + ]); + var domUtils = (dom.domUtils = { + //节点常量 + NODE_ELEMENT: 1, + NODE_DOCUMENT: 9, + NODE_TEXT: 3, + NODE_COMMENT: 8, + NODE_DOCUMENT_FRAGMENT: 11, + + //位置关系 + POSITION_IDENTICAL: 0, + POSITION_DISCONNECTED: 1, + POSITION_FOLLOWING: 2, + POSITION_PRECEDING: 4, + POSITION_IS_CONTAINED: 8, + POSITION_CONTAINS: 16, + //ie6使用其他的会有一段空白出现 + fillChar: ie && browser.version === "6" ? "\ufeff" : "\u200B", + //-------------------------Node部分-------------------------------- + keys: { + /*Backspace*/ 8: 1, + /*Delete*/ 46: 1, + /*Shift*/ 16: 1, + /*Ctrl*/ 17: 1, + /*Alt*/ 18: 1, + 37: 1, + 38: 1, + 39: 1, + 40: 1, + 13: 1 /*enter*/ + }, + /** + * 获取节点A相对于节点B的位置关系 + * @method getPosition + * @param { Node } nodeA 需要查询位置关系的节点A + * @param { Node } nodeB 需要查询位置关系的节点B + * @return { Number } 节点A与节点B的关系 + * @example + * ```javascript + * //output: 20 + * var position = UE.dom.domUtils.getPosition( document.documentElement, document.body ); + * + * switch ( position ) { + * + * //0 + * case UE.dom.domUtils.POSITION_IDENTICAL: + * console.log('元素相同'); + * break; + * //1 + * case UE.dom.domUtils.POSITION_DISCONNECTED: + * console.log('两个节点在不同的文档中'); + * break; + * //2 + * case UE.dom.domUtils.POSITION_FOLLOWING: + * console.log('节点A在节点B之后'); + * break; + * //4 + * case UE.dom.domUtils.POSITION_PRECEDING; + * console.log('节点A在节点B之前'); + * break; + * //8 + * case UE.dom.domUtils.POSITION_IS_CONTAINED: + * console.log('节点A被节点B包含'); + * break; + * case 10: + * console.log('节点A被节点B包含且节点A在节点B之后'); + * break; + * //16 + * case UE.dom.domUtils.POSITION_CONTAINS: + * console.log('节点A包含节点B'); + * break; + * case 20: + * console.log('节点A包含节点B且节点A在节点B之前'); + * break; + * + * } + * ``` + */ + getPosition: function (nodeA, nodeB) { + // 如果两个节点是同一个节点 + if (nodeA === nodeB) { + // domUtils.POSITION_IDENTICAL + return 0; + } + var node, + parentsA = [nodeA], + parentsB = [nodeB]; + node = nodeA; + while ((node = node.parentNode)) { + // 如果nodeB是nodeA的祖先节点 + if (node === nodeB) { + // domUtils.POSITION_IS_CONTAINED + domUtils.POSITION_FOLLOWING + return 10; + } + parentsA.push(node); + } + node = nodeB; + while ((node = node.parentNode)) { + // 如果nodeA是nodeB的祖先节点 + if (node === nodeA) { + // domUtils.POSITION_CONTAINS + domUtils.POSITION_PRECEDING + return 20; + } + parentsB.push(node); + } + parentsA.reverse(); + parentsB.reverse(); + if (parentsA[0] !== parentsB[0]) { + // domUtils.POSITION_DISCONNECTED + return 1; + } + var i = -1; + while ((i++, parentsA[i] === parentsB[i])) { + } + nodeA = parentsA[i]; + nodeB = parentsB[i]; + while ((nodeA = nodeA.nextSibling)) { + if (nodeA === nodeB) { + // domUtils.POSITION_PRECEDING + return 4; + } + } + // domUtils.POSITION_FOLLOWING + return 2; + }, + + /** + * 检测节点node在父节点中的索引位置 + * @method getNodeIndex + * @param { Node } node 需要检测的节点对象 + * @return { Number } 该节点在父节点中的位置 + * @see UE.dom.domUtils.getNodeIndex(Node,Boolean) + */ + + /** + * 检测节点node在父节点中的索引位置, 根据给定的mergeTextNode参数决定是否要合并多个连续的文本节点为一个节点 + * @method getNodeIndex + * @param { Node } node 需要检测的节点对象 + * @param { Boolean } mergeTextNode 是否合并多个连续的文本节点为一个节点 + * @return { Number } 该节点在父节点中的位置 + * @example + * ```javascript + * + * var node = document.createElement("div"); + * + * node.appendChild( document.createTextNode( "hello" ) ); + * node.appendChild( document.createTextNode( "world" ) ); + * node.appendChild( node = document.createElement( "div" ) ); + * + * //output: 2 + * console.log( UE.dom.domUtils.getNodeIndex( node ) ); + * + * //output: 1 + * console.log( UE.dom.domUtils.getNodeIndex( node, true ) ); + * + * ``` + */ + getNodeIndex: function (node, ignoreTextNode) { + var preNode = node, + i = 0; + while ((preNode = preNode.previousSibling)) { + if (ignoreTextNode && preNode.nodeType == 3) { + if (preNode.nodeType != preNode.nextSibling.nodeType) { + i++; + } + continue; + } + i++; + } + return i; + }, + + /** + * 检测节点node是否在给定的document对象上 + * @method inDoc + * @param { Node } node 需要检测的节点对象 + * @param { DomDocument } doc 需要检测的document对象 + * @return { Boolean } 该节点node是否在给定的document的dom树上 + * @example + * ```javascript + * + * var node = document.createElement("div"); + * + * //output: false + * console.log( UE.do.domUtils.inDoc( node, document ) ); + * + * document.body.appendChild( node ); + * + * //output: true + * console.log( UE.do.domUtils.inDoc( node, document ) ); + * + * ``` + */ + inDoc: function (node, doc) { + return domUtils.getPosition(node, doc) === 10; + }, + /** + * 根据给定的过滤规则filterFn, 查找符合该过滤规则的node节点的第一个祖先节点, + * 查找的起点是给定node节点的父节点。 + * @method findParent + * @param { Node } node 需要查找的节点 + * @param { Function } filterFn 自定义的过滤方法。 + * @warning 查找的终点是到body节点为止 + * @remind 自定义的过滤方法filterFn接受一个Node对象作为参数, 该对象代表当前执行检测的祖先节点。 如果该 + * 节点满足过滤条件, 则要求返回true, 这时将直接返回该节点作为findParent()的结果, 否则, 请返回false。 + * @return { Node | Null } 如果找到符合过滤条件的节点, 就返回该节点, 否则返回NULL + * @example + * ```javascript + * var filterNode = UE.dom.domUtils.findParent( document.body.firstChild, function ( node ) { + * + * //由于查找的终点是body节点, 所以永远也不会匹配当前过滤器的条件, 即这里永远会返回false + * return node.tagName === "HTML"; + * + * } ); + * + * //output: true + * console.log( filterNode === null ); + * ``` + */ + + /** + * 根据给定的过滤规则filterFn, 查找符合该过滤规则的node节点的第一个祖先节点, + * 如果includeSelf的值为true,则查找的起点是给定的节点node, 否则, 起点是node的父节点 + * @method findParent + * @param { Node } node 需要查找的节点 + * @param { Function } filterFn 自定义的过滤方法。 + * @param { Boolean } includeSelf 查找过程是否包含自身 + * @warning 查找的终点是到body节点为止 + * @remind 自定义的过滤方法filterFn接受一个Node对象作为参数, 该对象代表当前执行检测的祖先节点。 如果该 + * 节点满足过滤条件, 则要求返回true, 这时将直接返回该节点作为findParent()的结果, 否则, 请返回false。 + * @remind 如果includeSelf为true, 则过滤器第一次执行时的参数会是节点本身。 + * 反之, 过滤器第一次执行时的参数将是该节点的父节点。 + * @return { Node | Null } 如果找到符合过滤条件的节点, 就返回该节点, 否则返回NULL + * @example + * ```html + * + * + *
+ *
+ * + * + * + * ``` + */ + findParent: function (node, filterFn, includeSelf) { + if (node && !domUtils.isBody(node)) { + node = includeSelf ? node : node.parentNode; + while (node) { + if (!filterFn || filterFn(node) || domUtils.isBody(node)) { + return filterFn && !filterFn(node) && domUtils.isBody(node) + ? null + : node; + } + node = node.parentNode; + } + } + return null; + }, + /** + * 查找node的节点名为tagName的第一个祖先节点, 查找的起点是node节点的父节点。 + * @method findParentByTagName + * @param { Node } node 需要查找的节点对象 + * @param { Array } tagNames 需要查找的父节点的名称数组 + * @warning 查找的终点是到body节点为止 + * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var node = UE.dom.domUtils.findParentByTagName( document.getElementsByTagName("div")[0], [ "BODY" ] ); + * //output: BODY + * console.log( node.tagName ); + * ``` + */ + + /** + * 查找node的节点名为tagName的祖先节点, 如果includeSelf的值为true,则查找的起点是给定的节点node, + * 否则, 起点是node的父节点。 + * @method findParentByTagName + * @param { Node } node 需要查找的节点对象 + * @param { Array } tagNames 需要查找的父节点的名称数组 + * @param { Boolean } includeSelf 查找过程是否包含node节点自身 + * @warning 查找的终点是到body节点为止 + * @return { Node | NULL } 如果找到符合条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var queryTarget = document.getElementsByTagName("div")[0]; + * var node = UE.dom.domUtils.findParentByTagName( queryTarget, [ "DIV" ], true ); + * //output: true + * console.log( queryTarget === node ); + * ``` + */ + findParentByTagName: function (node, tagNames, includeSelf, excludeFn) { + tagNames = utils.listToMap(utils.isArray(tagNames) ? tagNames : [tagNames]); + return domUtils.findParent( + node, + function (node) { + return tagNames[node.tagName] && !(excludeFn && excludeFn(node)); + }, + includeSelf ); - } catch (e) {} - if (handler._d && handler._d[key]) { - var index = utils.indexOf(handler._d.els, element); - if (index != -1) { - handler._d.els.splice(index, 1); + }, + /** + * 查找节点node的祖先节点集合, 查找的起点是给定节点的父节点,结果集中不包含给定的节点。 + * @method findParents + * @param { Node } node 需要查找的节点对象 + * @return { Array } 给定节点的祖先节点数组 + * @grammar UE.dom.domUtils.findParents(node) => Array //返回一个祖先节点数组集合,不包含自身 + * @grammar UE.dom.domUtils.findParents(node,includeSelf) => Array //返回一个祖先节点数组集合,includeSelf指定是否包含自身 + * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn) => Array //返回一个祖先节点数组集合,filterFn指定过滤条件,返回true的node将被选取 + * @grammar UE.dom.domUtils.findParents(node,includeSelf,filterFn,closerFirst) => Array //返回一个祖先节点数组集合,closerFirst为true的话,node的直接父亲节点是数组的第0个 + */ + + /** + * 查找节点node的祖先节点集合, 如果includeSelf的值为true, + * 则返回的结果集中允许出现当前给定的节点, 否则, 该节点不会出现在其结果集中。 + * @method findParents + * @param { Node } node 需要查找的节点对象 + * @param { Boolean } includeSelf 查找的结果中是否允许包含当前查找的节点对象 + * @return { Array } 给定节点的祖先节点数组 + */ + findParents: function (node, includeSelf, filterFn, closerFirst) { + var parents = includeSelf && ((filterFn && filterFn(node)) || !filterFn) + ? [node] + : []; + while ((node = domUtils.findParent(node, filterFn))) { + parents.push(node); } - handler._d.els.length == 0 && delete handler._d[key]; - } - } - } - }, + return closerFirst ? parents : parents.reverse(); + }, - /** - * 比较节点nodeA与节点nodeB是否具有相同的标签名、属性名以及属性值 - * @method isSameElement - * @param { Node } nodeA 需要比较的节点 - * @param { Node } nodeB 需要比较的节点 - * @return { Boolean } 两个节点是否具有相同的标签名、属性名以及属性值 - * @example - * ```html - * ssss - * bbbbb - * ssss - * bbbbb - * - * - * ``` - */ - isSameElement: function(nodeA, nodeB) { - if (nodeA.tagName != nodeB.tagName) { - return false; - } - var thisAttrs = nodeA.attributes, - otherAttrs = nodeB.attributes; - if (!ie && thisAttrs.length != otherAttrs.length) { - return false; - } - var attrA, - attrB, - al = 0, - bl = 0; - for (var i = 0; (attrA = thisAttrs[i++]); ) { - if (attrA.nodeName == "style") { - if (attrA.specified) { - al++; - } - if (domUtils.isSameStyle(nodeA, nodeB)) { - continue; - } else { - return false; - } - } - if (ie) { - if (attrA.specified) { - al++; - attrB = otherAttrs.getNamedItem(attrA.nodeName); - } else { - continue; - } - } else { - attrB = nodeB.attributes[attrA.nodeName]; - } - if (!attrB.specified || attrA.nodeValue != attrB.nodeValue) { - return false; - } - } - // 有可能attrB的属性包含了attrA的属性之外还有自己的属性 - if (ie) { - for (i = 0; (attrB = otherAttrs[i++]); ) { - if (attrB.specified) { - bl++; - } - } - if (al != bl) { - return false; - } - } - return true; - }, + /** + * 在节点node后面插入新节点newNode + * @method insertAfter + * @param { Node } node 目标节点 + * @param { Node } newNode 新插入的节点, 该节点将置于目标节点之后 + * @return { Node } 新插入的节点 + */ + insertAfter: function (node, newNode) { + return node.nextSibling + ? node.parentNode.insertBefore(newNode, node.nextSibling) + : node.parentNode.appendChild(newNode); + }, - /** - * 判断节点nodeA与节点nodeB的元素的style属性是否一致 - * @method isSameStyle - * @param { Node } nodeA 需要比较的节点 - * @param { Node } nodeB 需要比较的节点 - * @return { Boolean } 两个节点是否具有相同的style属性值 - * @example - * ```html - * ssss - * bbbbb - * ssss - * bbbbb - * - * - * ``` - */ - isSameStyle: function(nodeA, nodeB) { - var styleA = nodeA.style.cssText - .replace(/( ?; ?)/g, ";") - .replace(/( ?: ?)/g, ":"), - styleB = nodeB.style.cssText - .replace(/( ?; ?)/g, ";") - .replace(/( ?: ?)/g, ":"); - if (browser.opera) { - styleA = nodeA.style; - styleB = nodeB.style; - if (styleA.length != styleB.length) return false; - for (var p in styleA) { - if (/^(\d+|csstext)$/i.test(p)) { - continue; - } - if (styleA[p] != styleB[p]) { - return false; - } - } - return true; - } - if (!styleA || !styleB) { - return styleA == styleB; - } - styleA = styleA.split(";"); - styleB = styleB.split(";"); - if (styleA.length != styleB.length) { - return false; - } - for (var i = 0, ci; (ci = styleA[i++]); ) { - if (utils.indexOf(styleB, ci) == -1) { - return false; - } - } - return true; - }, - /** - * 检查节点node是否为block元素 - * @method isBlockElm - * @param { Node } node 需要检测的节点对象 - * @return { Boolean } 是否是block元素节点 - * @warning 该方法的判断规则如下: 如果该元素原本是block元素, 则不论该元素当前的css样式是什么都会返回true; - * 否则,检测该元素的css样式, 如果该元素当前是block元素, 则返回true。 其余情况下都返回false。 - * @example - * ```html - * - * - *
- * - * - * ``` - */ - isBlockElm: function(node) { - return ( - node.nodeType == 1 && - (dtd.$block[node.tagName] || - styleBlock[domUtils.getComputedStyle(node, "display")]) && - !dtd.$nonChild[node.tagName] - ); - }, - /** - * 检测node节点是否为body节点 - * @method isBody - * @param { Element } node 需要检测的dom元素 - * @return { Boolean } 给定的元素是否是body元素 - * @example - * ```javascript - * //output: true - * console.log( UE.dom.domUtils.isBody( document.body ) ); - * ``` - */ - isBody: function(node) { - return node && node.nodeType == 1 && node.tagName.toLowerCase() == "body"; - }, - /** - * 以node节点为分界,将该节点的指定祖先节点parent拆分成两个独立的节点, - * 拆分形成的两个节点之间是node节点 - * @method breakParent - * @param { Node } node 作为分界的节点对象 - * @param { Node } parent 该节点必须是node节点的祖先节点, 且是block节点。 - * @return { Node } 给定的node分界节点 - * @example - * ```javascript - * - * var node = document.createElement("span"), - * wrapNode = document.createElement( "div" ), - * parent = document.createElement("p"); - * - * parent.appendChild( node ); - * wrapNode.appendChild( parent ); - * - * //拆分前 - * //output:

- * console.log( wrapNode.innerHTML ); - * - * - * UE.dom.domUtils.breakParent( node, parent ); - * //拆分后 - * //output:

- * console.log( wrapNode.innerHTML ); - * - * ``` - */ - breakParent: function(node, parent) { - var tmpNode, - parentClone = node, - clone = node, - leftNodes, - rightNodes; - do { - parentClone = parentClone.parentNode; - if (leftNodes) { - tmpNode = parentClone.cloneNode(false); - tmpNode.appendChild(leftNodes); - leftNodes = tmpNode; - tmpNode = parentClone.cloneNode(false); - tmpNode.appendChild(rightNodes); - rightNodes = tmpNode; - } else { - leftNodes = parentClone.cloneNode(false); - rightNodes = leftNodes.cloneNode(false); - } - while ((tmpNode = clone.previousSibling)) { - leftNodes.insertBefore(tmpNode, leftNodes.firstChild); - } - while ((tmpNode = clone.nextSibling)) { - rightNodes.appendChild(tmpNode); - } - clone = parentClone; - } while (parent !== parentClone); - tmpNode = parent.parentNode; - tmpNode.insertBefore(leftNodes, parent); - tmpNode.insertBefore(rightNodes, parent); - tmpNode.insertBefore(node, rightNodes); - domUtils.remove(parent); - return node; - }, - /** - * 检查节点node是否是空inline节点 - * @method isEmptyInlineElement - * @param { Node } node 需要检测的节点对象 - * @return { Number } 如果给定的节点是空的inline节点, 则返回1, 否则返回0。 - * @example - * ```html - * => 1 - * => 1 - * => 1 - * xx => 0 - * ``` - */ - isEmptyInlineElement: function(node) { - if (node.nodeType != 1 || !dtd.$removeEmpty[node.tagName]) { - return 0; - } - node = node.firstChild; - while (node) { - //如果是创建的bookmark就跳过 - if (domUtils.isBookmarkNode(node)) { - return 0; - } - if ( - (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node)) || - (node.nodeType == 3 && !domUtils.isWhitespace(node)) - ) { - return 0; - } - node = node.nextSibling; - } - return 1; - }, + /** + * 删除节点node及其下属的所有节点 + * @method remove + * @param { Node } node 需要删除的节点对象 + * @return { Node } 返回刚删除的节点对象 + * @example + * ```html + *
+ *
你好
+ *
+ * + * ``` + */ - /** - * 删除node节点下首尾两端的空白文本子节点 - * @method trimWhiteTextNode - * @param { Element } node 需要执行删除操作的元素对象 - * @example - * ```javascript - * var node = document.createElement("div"); - * - * node.appendChild( document.createTextNode( "" ) ); - * - * node.appendChild( document.createElement("div") ); - * - * node.appendChild( document.createTextNode( "" ) ); - * - * //3 - * console.log( node.childNodes.length ); - * - * UE.dom.domUtils.trimWhiteTextNode( node ); - * - * //1 - * console.log( node.childNodes.length ); - * ``` - */ - trimWhiteTextNode: function(node) { - function remove(dir) { - var child; - while ( - (child = node[dir]) && - child.nodeType == 3 && - domUtils.isWhitespace(child) - ) { - node.removeChild(child); - } - } - remove("firstChild"); - remove("lastChild"); - }, - - /** - * 合并node节点下相同的子节点 - * @name mergeChild - * @desc - * UE.dom.domUtils.mergeChild(node,tagName) //tagName要合并的子节点的标签 - * @example - *

xxaaxx

- * ==> UE.dom.domUtils.mergeChild(node,'span') - *

xxaaxx

- */ - mergeChild: function(node, tagName, attrs) { - var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase()); - for (var i = 0, ci; (ci = list[i++]); ) { - if (!ci.parentNode || domUtils.isBookmarkNode(ci)) { - continue; - } - //span单独处理 - if (ci.tagName.toLowerCase() == "span") { - if (node === ci.parentNode) { - domUtils.trimWhiteTextNode(node); - if (node.childNodes.length == 1) { - node.style.cssText = ci.style.cssText + ";" + node.style.cssText; - domUtils.remove(ci, true); - continue; - } - } - ci.style.cssText = node.style.cssText + ";" + ci.style.cssText; - if (attrs) { - var style = attrs.style; - if (style) { - style = style.split(";"); - for (var j = 0, s; (s = style[j++]); ) { - ci.style[utils.cssStyleToDomStyle(s.split(":")[0])] = s.split( - ":" - )[1]; + /** + * 删除节点node,并根据keepChildren的值决定是否保留子节点 + * @method remove + * @param { Node } node 需要删除的节点对象 + * @param { Boolean } keepChildren 是否需要保留子节点 + * @return { Node } 返回刚删除的节点对象 + * @example + * ```html + *
+ *
你好
+ *
+ * + * ``` + */ + remove: function (node, keepChildren) { + var parent = node.parentNode, + child; + if (parent) { + if (keepChildren && node.hasChildNodes()) { + while ((child = node.firstChild)) { + parent.insertBefore(child, node); + } + } + parent.removeChild(node); } - } - } - if (domUtils.isSameStyle(ci, node)) { - domUtils.remove(ci, true); - } - continue; - } - if (domUtils.isSameElement(node, ci)) { - domUtils.remove(ci, true); - } - } - }, + return node; + }, - /** - * 原生方法getElementsByTagName的封装 - * @method getElementsByTagName - * @param { Node } node 目标节点对象 - * @param { String } tagName 需要查找的节点的tagName, 多个tagName以空格分割 - * @return { Array } 符合条件的节点集合 - */ - getElementsByTagName: function(node, name, filter) { - if (filter && utils.isString(filter)) { - var className = filter; - filter = function(node) { - return domUtils.hasClass(node, className); - }; - } - name = utils.trim(name).replace(/[ ]{2,}/g, " ").split(" "); - var arr = []; - for (var n = 0, ni; (ni = name[n++]); ) { - var list = node.getElementsByTagName(ni); - for (var i = 0, ci; (ci = list[i++]); ) { - if (!filter || filter(ci)) arr.push(ci); - } - } + /** + * 取得node节点的下一个兄弟节点, 如果该节点其后没有兄弟节点, 则递归查找其父节点之后的第一个兄弟节点, + * 直到找到满足条件的节点或者递归到BODY节点之后才会结束。 + * @method getNextDomNode + * @param { Node } node 需要获取其后的兄弟节点的节点对象 + * @return { Node | NULL } 如果找满足条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```html + * + *
+ * + *
+ * xxx + * + * + * ``` + * @example + * ```html + * + *
+ * + * xxx + *
+ * xxx + * + * + * ``` + */ - return arr; - }, - /** - * 将节点node提取到父节点上 - * @method mergeToParent - * @param { Element } node 需要提取的元素对象 - * @example - * ```html - *
- *
- * - *
- *
- * - * - * ``` - */ - mergeToParent: function(node) { - var parent = node.parentNode; - while (parent && dtd.$removeEmpty[parent.tagName]) { - if (parent.tagName == node.tagName || parent.tagName == "A") { - //针对a标签单独处理 - domUtils.trimWhiteTextNode(parent); - //span需要特殊处理 不处理这样的情况 xxxxxxxxx - if ( - (parent.tagName == "SPAN" && !domUtils.isSameStyle(parent, node)) || - (parent.tagName == "A" && node.tagName == "SPAN") - ) { - if (parent.childNodes.length > 1 || parent !== node.parentNode) { - node.style.cssText = - parent.style.cssText + ";" + node.style.cssText; - parent = parent.parentNode; - continue; - } else { - parent.style.cssText += ";" + node.style.cssText; - //trace:952 a标签要保持下划线 - if (parent.tagName == "A") { - parent.style.textDecoration = "underline"; + /** + * 取得node节点的下一个兄弟节点, 如果startFromChild的值为ture,则先获取其子节点, + * 如果有子节点则直接返回第一个子节点;如果没有子节点或者startFromChild的值为false, + * 则执行getNextDomNode(Node node)的查找过程。 + * @method getNextDomNode + * @param { Node } node 需要获取其后的兄弟节点的节点对象 + * @param { Boolean } startFromChild 查找过程是否从其子节点开始 + * @return { Node | NULL } 如果找满足条件的节点, 则返回该节点, 否则返回NULL + * @see UE.dom.domUtils.getNextDomNode(Node) + */ + getNextDomNode: function (node, startFromChild, filterFn, guard) { + return getDomNode( + node, + "firstChild", + "nextSibling", + startFromChild, + filterFn, + guard + ); + }, + getPreDomNode: function (node, startFromChild, filterFn, guard) { + return getDomNode( + node, + "lastChild", + "previousSibling", + startFromChild, + filterFn, + guard + ); + }, + /** + * 检测节点node是否属是UEditor定义的bookmark节点 + * @method isBookmarkNode + * @private + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 是否是bookmark节点 + * @example + * ```html + * + * + * ``` + */ + isBookmarkNode: function (node) { + return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id); + }, + /** + * 获取节点node所属的window对象 + * @method getWindow + * @param { Node } node 节点对象 + * @return { Window } 当前节点所属的window对象 + * @example + * ```javascript + * //output: true + * console.log( UE.dom.domUtils.getWindow( document.body ) === window ); + * ``` + */ + getWindow: function (node) { + var doc = node.ownerDocument || node; + return doc.defaultView || doc.parentWindow; + }, + /** + * 获取离nodeA与nodeB最近的公共的祖先节点 + * @method getCommonAncestor + * @param { Node } nodeA 第一个节点 + * @param { Node } nodeB 第二个节点 + * @remind 如果给定的两个节点是同一个节点, 将直接返回该节点。 + * @return { Node | NULL } 如果未找到公共节点, 返回NULL, 否则返回最近的公共祖先节点。 + * @example + * ```javascript + * var commonAncestor = UE.dom.domUtils.getCommonAncestor( document.body, document.body.firstChild ); + * //output: true + * console.log( commonAncestor.tagName.toLowerCase() === 'body' ); + * ``` + */ + getCommonAncestor: function (nodeA, nodeB) { + if (nodeA === nodeB) return nodeA; + var parentsA = [nodeA], + parentsB = [nodeB], + parent = nodeA, + i = -1; + while ((parent = parent.parentNode)) { + if (parent === nodeB) { + return parent; + } + parentsA.push(parent); } - } + parent = nodeB; + while ((parent = parent.parentNode)) { + if (parent === nodeA) return parent; + parentsB.push(parent); + } + parentsA.reverse(); + parentsB.reverse(); + while ((i++, parentsA[i] === parentsB[i])) { + } + return i == 0 ? null : parentsA[i - 1]; + }, + /** + * 清除node节点左右连续为空的兄弟inline节点 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * 则这些兄弟节点将被删除 + * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext) //ignoreNext指定是否忽略右边空节点 + * @grammar UE.dom.domUtils.clearEmptySibling(node,ignoreNext,ignorePre) //ignorePre指定是否忽略左边空节点 + * @example + * ```html + * + *
+ * + * + * + * xxx + * + * + * + * ``` + */ + + /** + * 清除node节点左右连续为空的兄弟inline节点, 如果ignoreNext的值为true, + * 则忽略对右边兄弟节点的操作。 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * @param { Boolean } ignoreNext 是否忽略忽略对右边的兄弟节点的操作 + * 则这些兄弟节点将被删除 + * @see UE.dom.domUtils.clearEmptySibling(Node) + */ + + /** + * 清除node节点左右连续为空的兄弟inline节点, 如果ignoreNext的值为true, + * 则忽略对右边兄弟节点的操作, 如果ignorePre的值为true,则忽略对左边兄弟节点的操作。 + * @method clearEmptySibling + * @param { Node } node 执行的节点对象, 如果该节点的左右连续的兄弟节点是空的inline节点, + * @param { Boolean } ignoreNext 是否忽略忽略对右边的兄弟节点的操作 + * @param { Boolean } ignorePre 是否忽略忽略对左边的兄弟节点的操作 + * 则这些兄弟节点将被删除 + * @see UE.dom.domUtils.clearEmptySibling(Node) + */ + clearEmptySibling: function (node, ignoreNext, ignorePre) { + function clear(next, dir) { + var tmpNode; + while ( + next && + !domUtils.isBookmarkNode(next) && + (domUtils.isEmptyInlineElement(next) || + //这里不能把空格算进来会吧空格干掉,出现文字间的空格丢掉了 + !new RegExp("[^\t\n\r" + domUtils.fillChar + "]").test( + next.nodeValue + )) + ) { + tmpNode = next[dir]; + domUtils.remove(next); + next = tmpNode; + } + } + + !ignoreNext && clear(node.nextSibling, "nextSibling"); + !ignorePre && clear(node.previousSibling, "previousSibling"); + }, + /** + * 将一个文本节点textNode拆分成两个文本节点,offset指定拆分位置 + * @method split + * @param { Node } textNode 需要拆分的文本节点对象 + * @param { int } offset 需要拆分的位置, 位置计算从0开始 + * @return { Node } 拆分后形成的新节点 + * @example + * ```html + *
abcdef
+ * + * ``` + */ + split: function (node, offset) { + var doc = node.ownerDocument; + if (browser.ie && offset == node.nodeValue.length) { + var next = doc.createTextNode(""); + return domUtils.insertAfter(node, next); + } + var retval = node.splitText(offset); + //ie8下splitText不会跟新childNodes,我们手动触发他的更新 + if (browser.ie8) { + var tmpNode = doc.createTextNode(""); + domUtils.insertAfter(retval, tmpNode); + domUtils.remove(tmpNode); + } + return retval; + }, + + /** + * 检测文本节点textNode是否为空节点(包括空格、换行、占位符等字符) + * @method isWhitespace + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 检测的节点是否为空 + * @example + * ```html + *
+ * + *
+ * + * ``` + */ + isWhitespace: function (node) { + return !new RegExp("[^ \t\n\r" + domUtils.fillChar + "]").test( + node.nodeValue + ); + }, + /** + * 获取元素element相对于viewport的位置坐标 + * @method getXY + * @param { Node } element 需要计算位置的节点对象 + * @return { Object } 返回形如{x:left,y:top}的一个key-value映射对象, 其中键x代表水平偏移距离, + * y代表垂直偏移距离。 + * + * @example + * ```javascript + * var location = UE.dom.domUtils.getXY( document.getElementById("test") ); + * //output: test的坐标为: 12, 24 + * console.log( 'test的坐标为: ', location.x, ',', location.y ); + * ``` + */ + getXY: function (element) { + var x = 0, + y = 0; + while (element.offsetParent) { + y += element.offsetTop; + x += element.offsetLeft; + element = element.offsetParent; + } + return {x: x, y: y}; + }, + /** + * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数 + * @method on + * @param { Node } element 需要绑定事件的节点对象 + * @param { String } type 绑定的事件类型 + * @param { Function } handler 事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.on(document.body,"click",function(e){ + * //e为事件对象,this为被点击元素对戏那个 + * }); + * ``` + */ + + /** + * 为元素element绑定原生DOM事件,type为事件类型,handler为处理函数 + * @method on + * @param { Node } element 需要绑定事件的节点对象 + * @param {string} type 绑定的事件类型数组 + * @param { Function } handler 事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.on(document.body,["click","mousedown"],function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + on: function (element, type, handler) { + var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/), + k = types.length; + if (k) + while (k--) { + type = types[k]; + if (element.addEventListener) { + element.addEventListener(type, handler, false); + } else { + if (!handler._d) { + handler._d = { + els: [] + }; + } + var key = type + handler.toString(), + index = utils.indexOf(handler._d.els, element); + if (!handler._d[key] || index == -1) { + if (index == -1) { + handler._d.els.push(element); + } + if (!handler._d[key]) { + handler._d[key] = function (evt) { + return handler.call(evt.srcElement, evt || window.event); + }; + } + + element.attachEvent("on" + type, handler._d[key]); + } + } + } + element = null; + }, + /** + * 解除DOM事件绑定 + * @method un + * @param { Node } element 需要解除事件绑定的节点对象 + * @param { String } type 需要接触绑定的事件类型 + * @param { Function } handler 对应的事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.un(document.body,"click",function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + + /** + * 解除DOM事件绑定 + * @method un + * @param { Node } element 需要解除事件绑定的节点对象 + * @param { Array } type 需要接触绑定的事件类型数组 + * @param { Function } handler 对应的事件处理器 + * @example + * ```javascript + * UE.dom.domUtils.un(document.body, ["click","mousedown"],function(evt){ + * //evt为事件对象,this为被点击元素对象 + * }); + * ``` + */ + un: function (element, type, handler) { + var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/), + k = types.length; + if (k) + while (k--) { + type = types[k]; + if (element.removeEventListener) { + element.removeEventListener(type, handler, false); + } else { + var key = type + handler.toString(); + try { + element.detachEvent( + "on" + type, + handler._d ? handler._d[key] : handler + ); + } catch (e) { + } + if (handler._d && handler._d[key]) { + var index = utils.indexOf(handler._d.els, element); + if (index != -1) { + handler._d.els.splice(index, 1); + } + handler._d.els.length == 0 && delete handler._d[key]; + } + } + } + }, + + /** + * 比较节点nodeA与节点nodeB是否具有相同的标签名、属性名以及属性值 + * @method isSameElement + * @param { Node } nodeA 需要比较的节点 + * @param { Node } nodeB 需要比较的节点 + * @return { Boolean } 两个节点是否具有相同的标签名、属性名以及属性值 + * @example + * ```html + * ssss + * bbbbb + * ssss + * bbbbb + * + * + * ``` + */ + isSameElement: function (nodeA, nodeB) { + if (nodeA.tagName != nodeB.tagName) { + return false; + } + var thisAttrs = nodeA.attributes, + otherAttrs = nodeB.attributes; + if (!ie && thisAttrs.length != otherAttrs.length) { + return false; + } + var attrA, + attrB, + al = 0, + bl = 0; + for (var i = 0; (attrA = thisAttrs[i++]);) { + if (attrA.nodeName == "style") { + if (attrA.specified) { + al++; + } + if (domUtils.isSameStyle(nodeA, nodeB)) { + continue; + } else { + return false; + } + } + if (ie) { + if (attrA.specified) { + al++; + attrB = otherAttrs.getNamedItem(attrA.nodeName); + } else { + continue; + } + } else { + attrB = nodeB.attributes[attrA.nodeName]; + } + if (!attrB.specified || attrA.nodeValue != attrB.nodeValue) { + return false; + } + } + // 有可能attrB的属性包含了attrA的属性之外还有自己的属性 + if (ie) { + for (i = 0; (attrB = otherAttrs[i++]);) { + if (attrB.specified) { + bl++; + } + } + if (al != bl) { + return false; + } + } + return true; + }, + + /** + * 判断节点nodeA与节点nodeB的元素的style属性是否一致 + * @method isSameStyle + * @param { Node } nodeA 需要比较的节点 + * @param { Node } nodeB 需要比较的节点 + * @return { Boolean } 两个节点是否具有相同的style属性值 + * @example + * ```html + * ssss + * bbbbb + * ssss + * bbbbb + * + * + * ``` + */ + isSameStyle: function (nodeA, nodeB) { + var styleA = nodeA.style.cssText + .replace(/( ?; ?)/g, ";") + .replace(/( ?: ?)/g, ":"), + styleB = nodeB.style.cssText + .replace(/( ?; ?)/g, ";") + .replace(/( ?: ?)/g, ":"); + if (browser.opera) { + styleA = nodeA.style; + styleB = nodeB.style; + if (styleA.length != styleB.length) return false; + for (var p in styleA) { + if (/^(\d+|csstext)$/i.test(p)) { + continue; + } + if (styleA[p] != styleB[p]) { + return false; + } + } + return true; + } + if (!styleA || !styleB) { + return styleA == styleB; + } + styleA = styleA.split(";"); + styleB = styleB.split(";"); + if (styleA.length != styleB.length) { + return false; + } + for (var i = 0, ci; (ci = styleA[i++]);) { + if (utils.indexOf(styleB, ci) == -1) { + return false; + } + } + return true; + }, + /** + * 检查节点node是否为block元素 + * @method isBlockElm + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 是否是block元素节点 + * @warning 该方法的判断规则如下: 如果该元素原本是block元素, 则不论该元素当前的css样式是什么都会返回true; + * 否则,检测该元素的css样式, 如果该元素当前是block元素, 则返回true。 其余情况下都返回false。 + * @example + * ```html + * + * + *
+ * + * + * ``` + */ + isBlockElm: function (node) { + return ( + node.nodeType == 1 && + (dtd.$block[node.tagName] || + styleBlock[domUtils.getComputedStyle(node, "display")]) && + !dtd.$nonChild[node.tagName] + ); + }, + /** + * 检测node节点是否为body节点 + * @method isBody + * @param { Element } node 需要检测的dom元素 + * @return { Boolean } 给定的元素是否是body元素 + * @example + * ```javascript + * //output: true + * console.log( UE.dom.domUtils.isBody( document.body ) ); + * ``` + */ + isBody: function (node) { + return node && node.nodeType == 1 && node.tagName.toLowerCase() == "body"; + }, + /** + * 以node节点为分界,将该节点的指定祖先节点parent拆分成两个独立的节点, + * 拆分形成的两个节点之间是node节点 + * @method breakParent + * @param { Node } node 作为分界的节点对象 + * @param { Node } parent 该节点必须是node节点的祖先节点, 且是block节点。 + * @return { Node } 给定的node分界节点 + * @example + * ```javascript + * + * var node = document.createElement("span"), + * wrapNode = document.createElement( "div" ), + * parent = document.createElement("p"); + * + * parent.appendChild( node ); + * wrapNode.appendChild( parent ); + * + * //拆分前 + * //output:

+ * console.log( wrapNode.innerHTML ); + * + * + * UE.dom.domUtils.breakParent( node, parent ); + * //拆分后 + * //output:

+ * console.log( wrapNode.innerHTML ); + * + * ``` + */ + breakParent: function (node, parent) { + var tmpNode, + parentClone = node, + clone = node, + leftNodes, + rightNodes; + do { + parentClone = parentClone.parentNode; + if (leftNodes) { + tmpNode = parentClone.cloneNode(false); + tmpNode.appendChild(leftNodes); + leftNodes = tmpNode; + tmpNode = parentClone.cloneNode(false); + tmpNode.appendChild(rightNodes); + rightNodes = tmpNode; + } else { + leftNodes = parentClone.cloneNode(false); + rightNodes = leftNodes.cloneNode(false); + } + while ((tmpNode = clone.previousSibling)) { + leftNodes.insertBefore(tmpNode, leftNodes.firstChild); + } + while ((tmpNode = clone.nextSibling)) { + rightNodes.appendChild(tmpNode); + } + clone = parentClone; + } while (parent !== parentClone); + tmpNode = parent.parentNode; + tmpNode.insertBefore(leftNodes, parent); + tmpNode.insertBefore(rightNodes, parent); + tmpNode.insertBefore(node, rightNodes); + domUtils.remove(parent); + return node; + }, + /** + * 检查节点node是否是空inline节点 + * @method isEmptyInlineElement + * @param { Node } node 需要检测的节点对象 + * @return { Number } 如果给定的节点是空的inline节点, 则返回1, 否则返回0。 + * @example + * ```html + * => 1 + * => 1 + * => 1 + * xx => 0 + * ``` + */ + isEmptyInlineElement: function (node) { + if (node.nodeType != 1 || !dtd.$removeEmpty[node.tagName]) { + return 0; + } + node = node.firstChild; + while (node) { + //如果是创建的bookmark就跳过 + if (domUtils.isBookmarkNode(node)) { + return 0; + } + if ( + (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node)) || + (node.nodeType == 3 && !domUtils.isWhitespace(node)) + ) { + return 0; + } + node = node.nextSibling; + } + return 1; + }, + + /** + * 删除node节点下首尾两端的空白文本子节点 + * @method trimWhiteTextNode + * @param { Element } node 需要执行删除操作的元素对象 + * @example + * ```javascript + * var node = document.createElement("div"); + * + * node.appendChild( document.createTextNode( "" ) ); + * + * node.appendChild( document.createElement("div") ); + * + * node.appendChild( document.createTextNode( "" ) ); + * + * //3 + * console.log( node.childNodes.length ); + * + * UE.dom.domUtils.trimWhiteTextNode( node ); + * + * //1 + * console.log( node.childNodes.length ); + * ``` + */ + trimWhiteTextNode: function (node) { + function remove(dir) { + var child; + while ( + (child = node[dir]) && + child.nodeType == 3 && + domUtils.isWhitespace(child) + ) { + node.removeChild(child); + } + } + + remove("firstChild"); + remove("lastChild"); + }, + + /** + * 合并node节点下相同的子节点 + * @name mergeChild + * @desc + * UE.dom.domUtils.mergeChild(node,tagName) //tagName要合并的子节点的标签 + * @example + *

xxaaxx

+ * ==> UE.dom.domUtils.mergeChild(node,'span') + *

xxaaxx

+ */ + mergeChild: function (node, tagName, attrs) { + var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase()); + for (var i = 0, ci; (ci = list[i++]);) { + if (!ci.parentNode || domUtils.isBookmarkNode(ci)) { + continue; + } + //span单独处理 + if (ci.tagName.toLowerCase() == "span") { + if (node === ci.parentNode) { + domUtils.trimWhiteTextNode(node); + if (node.childNodes.length == 1) { + node.style.cssText = ci.style.cssText + ";" + node.style.cssText; + domUtils.remove(ci, true); + continue; + } + } + ci.style.cssText = node.style.cssText + ";" + ci.style.cssText; + if (attrs) { + var style = attrs.style; + if (style) { + style = style.split(";"); + for (var j = 0, s; (s = style[j++]);) { + ci.style[utils.cssStyleToDomStyle(s.split(":")[0])] = s.split( + ":" + )[1]; + } + } + } + if (domUtils.isSameStyle(ci, node)) { + domUtils.remove(ci, true); + } + continue; + } + if (domUtils.isSameElement(node, ci)) { + domUtils.remove(ci, true); + } + } + }, + + /** + * 原生方法getElementsByTagName的封装 + * @method getElementsByTagName + * @param { Node } node 目标节点对象 + * @param { String } tagName 需要查找的节点的tagName, 多个tagName以空格分割 + * @return { Array } 符合条件的节点集合 + */ + getElementsByTagName: function (node, tagName, filter) { + if (filter && utils.isString(filter)) { + var className = filter; + filter = function (node) { + return domUtils.hasClass(node, className); + }; + } + tagName = utils.trim(tagName).replace(/[ ]{2,}/g, " ").split(" "); + var arr = []; + for (var n = 0, ni; (ni = tagName[n++]);) { + var list = node.getElementsByTagName(ni); + for (var i = 0, ci; (ci = list[i++]);) { + if (!filter || filter(ci)) arr.push(ci); + } + } + + return arr; + }, + /** + * 将节点node提取到父节点上 + * @method mergeToParent + * @param { Element } node 需要提取的元素对象 + * @example + * ```html + *
+ *
+ * + *
+ *
+ * + * + * ``` + */ + mergeToParent: function (node) { + var parent = node.parentNode; + while (parent && dtd.$removeEmpty[parent.tagName]) { + if (parent.tagName == node.tagName || parent.tagName == "A") { + //针对a标签单独处理 + domUtils.trimWhiteTextNode(parent); + //span需要特殊处理 不处理这样的情况 xxxxxxxxx + if ( + (parent.tagName == "SPAN" && !domUtils.isSameStyle(parent, node)) || + (parent.tagName == "A" && node.tagName == "SPAN") + ) { + if (parent.childNodes.length > 1 || parent !== node.parentNode) { + node.style.cssText = + parent.style.cssText + ";" + node.style.cssText; + parent = parent.parentNode; + continue; + } else { + parent.style.cssText += ";" + node.style.cssText; + //trace:952 a标签要保持下划线 + if (parent.tagName == "A") { + parent.style.textDecoration = "underline"; + } + } + } + if (parent.tagName != "A") { + parent === node.parentNode && domUtils.remove(node, true); + break; + } + } + parent = parent.parentNode; + } + }, + /** + * 合并节点node的左右兄弟节点 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + + /** + * 合并节点node的左右兄弟节点, 可以根据给定的条件选择是否忽略合并左节点。 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @param { Boolean } ignorePre 是否忽略合并左节点 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + + /** + * 合并节点node的左右兄弟节点,可以根据给定的条件选择是否忽略合并左右节点。 + * @method mergeSibling + * @param { Element } node 需要合并的目标节点 + * @param { Boolean } ignorePre 是否忽略合并左节点 + * @param { Boolean } ignoreNext 是否忽略合并右节点 + * @remind 如果同时忽略左右节点, 则该操作什么也不会做 + * @example + * ```html + * xxxxoooxxxx + * + * + * ``` + */ + mergeSibling: function (node, ignorePre, ignoreNext) { + function merge(rtl, start, node) { + var next; + if ( + (next = node[rtl]) && + !domUtils.isBookmarkNode(next) && + next.nodeType == 1 && + domUtils.isSameElement(node, next) + ) { + while (next.firstChild) { + if (start == "firstChild") { + node.insertBefore(next.lastChild, node.firstChild); + } else { + node.appendChild(next.firstChild); + } + } + domUtils.remove(next); + } + } + + !ignorePre && merge("previousSibling", "firstChild", node); + !ignoreNext && merge("nextSibling", "lastChild", node); + }, + + /** + * 设置节点node及其子节点不会被选中 + * @method unSelectable + * @param { Element } node 需要执行操作的dom元素 + * @remind 执行该操作后的节点, 将不能被鼠标选中 + * @example + * ```javascript + * UE.dom.domUtils.unSelectable( document.body ); + * ``` + */ + unSelectable: (ie && browser.ie9below) || browser.opera + ? function (node) { + //for ie9 + node.onselectstart = function () { + return false; + }; + node.onclick = node.onkeyup = node.onkeydown = function () { + return false; + }; + node.unselectable = "on"; + node.setAttribute("unselectable", "on"); + for (var i = 0, ci; (ci = node.all[i++]);) { + switch (ci.tagName.toLowerCase()) { + case "iframe": + case "textarea": + case "input": + case "select": + break; + default: + ci.unselectable = "on"; + node.setAttribute("unselectable", "on"); + } + } + } + : function (node) { + node.style.MozUserSelect = node.style.webkitUserSelect = node.style.msUserSelect = node.style.KhtmlUserSelect = + "none"; + }, + /** + * 删除节点node上的指定属性名称的属性 + * @method removeAttributes + * @param { Node } node 需要删除属性的节点对象 + * @param { String } attrNames 可以是空格隔开的多个属性名称,该操作将会依次删除相应的属性 + * @example + * ```html + *
+ * xxxxx + *
+ * + * + * ``` + */ + + /** + * 删除节点node上的指定属性名称的属性 + * @method removeAttributes + * @param { Node } node 需要删除属性的节点对象 + * @param { Array } attrNames 需要删除的属性名数组 + * @example + * ```html + *
+ * xxxxx + *
+ * + * + * ``` + */ + removeAttributes: function (node, attrNames) { + attrNames = utils.isArray(attrNames) + ? attrNames + : utils.trim(attrNames).replace(/[ ]{2,}/g, " ").split(" "); + for (var i = 0, ci; (ci = attrNames[i++]);) { + ci = attrFix[ci] || ci; + switch (ci) { + case "className": + node[ci] = ""; + break; + case "style": + node.style.cssText = ""; + var val = node.getAttributeNode("style"); + !browser.ie && val && node.removeAttributeNode(val); + } + node.removeAttribute(ci); + } + }, + /** + * 在doc下创建一个标签名为tag,属性为attrs的元素 + * @method createElement + * @param { DomDocument } doc 新创建的元素属于该document节点创建 + * @param { String } tagName 需要创建的元素的标签名 + * @param { Object } attrs 新创建的元素的属性key-value集合 + * @return { Element } 新创建的元素对象 + * @example + * ```javascript + * var ele = UE.dom.domUtils.createElement( document, 'div', { + * id: 'test' + * } ); + * + * //output: DIV + * console.log( ele.tagName ); + * + * //output: test + * console.log( ele.id ); + * + * ``` + */ + createElement: function (doc, tag, attrs) { + return domUtils.setAttributes(doc.createElement(tag), attrs); + }, + /** + * 为节点node添加属性attrs,attrs为属性键值对 + * @method setAttributes + * @param { Element } node 需要设置属性的元素对象 + * @param { Object } attrs 需要设置的属性名-值对 + * @return { Element } 设置属性的元素对象 + * @example + * ```html + * + * + * + * + */ + setAttributes: function (node, attrs) { + for (var attr in attrs) { + if ('_propertyDelete' === attr) { + for (var j = 0; j < attrs[attr].length; j++) { + if (node.hasAttribute(attrs[attr][j])) { + node.removeAttribute(attrs[attr][j]); + } + } + continue; + } + if (attrs.hasOwnProperty(attr)) { + var value = attrs[attr]; + switch (attr) { + case "class": + //ie下要这样赋值,setAttribute不起作用 + node.className = value; + break; + case "style": + node.style.cssText = node.style.cssText + ";" + value; + break; + case "innerHTML": + node[attr] = value; + break; + case "value": + node.value = value; + break; + default: + node.setAttribute(attrFix[attr] || attr, value); + } + } + } + return node; + }, + + /** + * 获取元素element经过计算后的样式值 + * @method getComputedStyle + * @param { Element } element 需要获取样式的元素对象 + * @param { String } styleName 需要获取的样式名 + * @return { String } 获取到的样式值 + * @example + * ```html + * + * + * + * + * + * ``` + */ + getComputedStyle: function (element, styleName) { + //以下的属性单独处理 + var pros = "width height top left"; + + if (pros.indexOf(styleName) > -1) { + return ( + element[ + "offset" + + styleName.replace(/^\w/, function (s) { + return s.toUpperCase(); + }) + ] + "px" + ); + } + //忽略文本节点 + if (element.nodeType === 3) { + element = element.parentNode; + } + //ie下font-size若body下定义了font-size,则从currentStyle里会取到这个font-size. 取不到实际值,故此修改. + if ( + browser.ie && + browser.version < 9 && + styleName === "font-size" && + !element.style.fontSize && + !dtd.$empty[element.tagName] && + !dtd.$nonChild[element.tagName] + ) { + var span = element.ownerDocument.createElement("span"); + span.style.cssText = "padding:0;border:0;font-family:simsun;"; + span.innerHTML = "."; + element.appendChild(span); + var result = span.offsetHeight; + element.removeChild(span); + span = null; + return result + "px"; + } + try { + var value = + domUtils.getStyle(element, styleName) || + (window.getComputedStyle + ? domUtils + .getWindow(element) + .getComputedStyle(element, "") + .getPropertyValue(styleName) + : (element.currentStyle || element.style)[ + utils.cssStyleToDomStyle(styleName) + ]); + } catch (e) { + return ""; + } + return utils.transUnitToPx(utils.fixColor(styleName, value)); + }, + /** + * 删除元素element指定的className + * @method removeClasses + * @param { Element } ele 需要删除class的元素节点 + * @param { String } classNames 需要删除的className, 多个className之间以空格分开 + * @example + * ```html + * xxx + * + * + * ``` + */ + + /** + * 删除元素element指定的className + * @method removeClasses + * @param { Element } ele 需要删除class的元素节点 + * @param { Array } classNames 需要删除的className数组 + * @example + * ```html + * xxx + * + * + * ``` + */ + removeClasses: function (elm, classNames) { + classNames = utils.isArray(classNames) + ? classNames + : utils.trim(classNames).replace(/[ ]{2,}/g, " ").split(" "); + for (var i = 0, ci, cls = elm.className; (ci = classNames[i++]);) { + cls = cls.replace(new RegExp("\\b" + ci + "\\b"), ""); + } + cls = utils.trim(cls).replace(/[ ]{2,}/g, " "); + if (cls) { + elm.className = cls; + } else { + domUtils.removeAttributes(elm, ["class"]); + } + }, + /** + * 给元素element添加className + * @method addClass + * @param { Node } ele 需要增加className的元素 + * @param { String } classNames 需要添加的className, 多个className之间以空格分割 + * @remind 相同的类名不会被重复添加 + * @example + * ```html + * + * + * + * ``` + */ + + /** + * 判断元素element是否包含给定的样式类名className + * @method hasClass + * @param { Node } ele 需要检测的元素 + * @param { Array } classNames 需要检测的className数组 + * @return { Boolean } 元素是否包含所有给定的className + * @example + * ```html + * + * + * + * ``` + */ + hasClass: function (element, className) { + if (utils.isRegExp(className)) { + return className.test(element.className); + } + className = utils.trim(className).replace(/[ ]{2,}/g, " ").split(" "); + for (var i = 0, ci, cls = element.className; (ci = className[i++]);) { + if (!new RegExp("\\b" + ci + "\\b", "i").test(cls)) { + return false; + } + } + return i - 1 == className.length; + }, + + /** + * 阻止事件默认行为 + * @method preventDefault + * @param { Event } evt 需要阻止默认行为的事件对象 + * @example + * ```javascript + * UE.dom.domUtils.preventDefault( evt ); + * ``` + */ + preventDefault: function (evt) { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + }, + /** + * 删除元素element指定的样式 + * @method removeStyle + * @param { Element } element 需要删除样式的元素 + * @param { String } styleName 需要删除的样式名 + * @example + * ```html + * + * + * + * ``` + */ + removeStyle: function (element, name) { + if (browser.ie) { + //针对color先单独处理一下 + if (name == "color") { + name = "(^|;)" + name; + } + element.style.cssText = element.style.cssText.replace( + new RegExp(name + "[^:]*:[^;]+;?", "ig"), + "" + ); + } else { + if (element.style.removeProperty) { + element.style.removeProperty(name); + } else { + element.style.removeAttribute(utils.cssStyleToDomStyle(name)); + } + } + + if (!element.style.cssText) { + domUtils.removeAttributes(element, ["style"]); + } + }, + /** + * 获取元素element的style属性的指定值 + * @method getStyle + * @param { Element } element 需要获取属性值的元素 + * @param { String } styleName 需要获取的style的名称 + * @warning 该方法仅获取元素style属性中所标明的值 + * @return { String } 该元素包含指定的style属性值 + * @example + * ```html + *
+ * + * + * ``` + */ + getStyle: function (element, name) { + var value = element.style[utils.cssStyleToDomStyle(name)]; + return utils.fixColor(name, value); + }, + /** + * 为元素element设置样式属性值 + * @method setStyle + * @param { Element } element 需要设置样式的元素 + * @param { String } styleName 样式名 + * @param { String } styleValue 样式值 + * @example + * ```html + *
+ * + * + * ``` + */ + setStyle: function (element, name, value) { + element.style[utils.cssStyleToDomStyle(name)] = value; + if (!utils.trim(element.style.cssText)) { + this.removeAttributes(element, "style"); + } + }, + /** + * 为元素element设置多个样式属性值 + * @method setStyles + * @param { Element } element 需要设置样式的元素 + * @param { Object } styles 样式名值对 + * @example + * ```html + *
+ * + * + * ``` + */ + setStyles: function (element, styles) { + for (var name in styles) { + if (styles.hasOwnProperty(name)) { + domUtils.setStyle(element, name, styles[name]); + } + } + }, + /** + * 删除_moz_dirty属性 + * @private + * @method removeDirtyAttr + */ + removeDirtyAttr: function (node) { + for ( + var i = 0, ci, nodes = node.getElementsByTagName("*"); + (ci = nodes[i++]); + ) { + ci.removeAttribute("_moz_dirty"); + } + node.removeAttribute("_moz_dirty"); + }, + /** + * 获取子节点的数量 + * @method getChildCount + * @param { Element } node 需要检测的元素 + * @return { Number } 给定的node元素的子节点数量 + * @example + * ```html + *
+ * + *
+ * + * + * ``` + */ + + /** + * 根据给定的过滤规则, 获取符合条件的子节点的数量 + * @method getChildCount + * @param { Element } node 需要检测的元素 + * @param { Function } fn 过滤器, 要求对符合条件的子节点返回true, 反之则要求返回false + * @return { Number } 符合过滤条件的node元素的子节点数量 + * @example + * ```html + *
+ * + *
+ * + * + * ``` + */ + getChildCount: function (node, fn) { + var count = 0, + first = node.firstChild; + fn = + fn || + function () { + return 1; + }; + while (first) { + if (fn(first)) { + count++; + } + first = first.nextSibling; + } + return count; + }, + + /** + * 判断给定节点是否为空节点 + * @method isEmptyNode + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 节点是否为空 + * @example + * ```javascript + * UE.dom.domUtils.isEmptyNode( document.body ); + * ``` + */ + isEmptyNode: function (node) { + return ( + !node.firstChild || + domUtils.getChildCount(node, function (node) { + return ( + !domUtils.isBr(node) && + !domUtils.isBookmarkNode(node) && + !domUtils.isWhitespace(node) + ); + }) == 0 + ); + }, + clearSelectedArr: function (nodes) { + var node; + while ((node = nodes.pop())) { + domUtils.removeAttributes(node, ["class"]); + } + }, + /** + * 将显示区域滚动到指定节点的位置 + * @method scrollToView + * @param {Node} node 节点 + * @param {window} win window对象 + * @param {Number} offsetTop 距离上方的偏移量 + */ + scrollToView: function (node, win, offsetTop) { + offsetTop = offsetTop || 0 + var getViewPaneSize = function () { + var doc = win.document, + mode = doc.compatMode == "CSS1Compat"; + return { + width: + (mode ? doc.documentElement.clientWidth : doc.body.clientWidth) || 0, + height: + (mode ? doc.documentElement.clientHeight : doc.body.clientHeight) || 0 + }; + }, + getScrollPosition = function (win) { + if ("pageXOffset" in win) { + return { + x: win.pageXOffset || 0, + y: win.pageYOffset || 0 + }; + } else { + var doc = win.document; + return { + x: doc.documentElement.scrollLeft || doc.body.scrollLeft || 0, + y: doc.documentElement.scrollTop || doc.body.scrollTop || 0 + }; + } + }; + var winHeight = getViewPaneSize().height, + offset = winHeight * -1 + offsetTop; + offset += node.offsetHeight || 0; + var elementPosition = domUtils.getXY(node); + offset += elementPosition.y; + var currentScroll = getScrollPosition(win).y; + // console.log({currentScroll,winHeight,offset,y:elementPosition.y}); + // offset += 50; + if (offset > currentScroll || offset < currentScroll - winHeight) { + win.scrollTo({ + top: offset + (offset < 0 ? -20 : 20), + behavior: "smooth" + }); + } + }, + /** + * 判断给定节点是否为br + * @method isBr + * @param { Node } node 需要判断的节点对象 + * @return { Boolean } 给定的节点是否是br节点 + */ + isBr: function (node) { + return node.nodeType == 1 && node.tagName == "BR"; + }, + /** + * 判断给定的节点是否是一个“填充”节点 + * @private + * @method isFillChar + * @param { Node } node 需要判断的节点 + * @param { Boolean } isInStart 是否从节点内容的开始位置匹配 + * @returns { Boolean } 节点是否是填充节点 + */ + isFillChar: function (node, isInStart) { + if (node.nodeType != 3) return false; + var text = node.nodeValue; + if (isInStart) { + return new RegExp("^" + domUtils.fillChar).test(text); + } + return !text.replace(new RegExp(domUtils.fillChar, "g"), "").length; + }, + isStartInblock: function (range) { + var tmpRange = range.cloneRange(), + flag = 0, + start = tmpRange.startContainer, + tmp; + if (start.nodeType == 1 && start.childNodes[tmpRange.startOffset]) { + start = start.childNodes[tmpRange.startOffset]; + var pre = start.previousSibling; + while (pre && domUtils.isFillChar(pre)) { + start = pre; + pre = pre.previousSibling; + } + } + if (this.isFillChar(start, true) && tmpRange.startOffset == 1) { + tmpRange.setStartBefore(start); + start = tmpRange.startContainer; + } + + while (start && domUtils.isFillChar(start)) { + tmp = start; + start = start.previousSibling; + } + if (tmp) { + tmpRange.setStartBefore(tmp); + start = tmpRange.startContainer; + } + if ( + start.nodeType == 1 && + domUtils.isEmptyNode(start) && + tmpRange.startOffset == 1 + ) { + tmpRange.setStart(start, 0).collapse(true); + } + while (!tmpRange.startOffset) { + start = tmpRange.startContainer; + if (domUtils.isBlockElm(start) || domUtils.isBody(start)) { + flag = 1; + break; + } + var pre = tmpRange.startContainer.previousSibling, + tmpNode; + if (!pre) { + tmpRange.setStartBefore(tmpRange.startContainer); + } else { + while (pre && domUtils.isFillChar(pre)) { + tmpNode = pre; + pre = pre.previousSibling; + } + if (tmpNode) { + tmpRange.setStartBefore(tmpNode); + } else { + tmpRange.setStartBefore(tmpRange.startContainer); + } + } + } + return flag && !domUtils.isBody(tmpRange.startContainer) ? 1 : 0; + }, + + /** + * 判断给定的元素是否是一个空元素 + * @method isEmptyBlock + * @param { Element } node 需要判断的元素 + * @return { Boolean } 是否是空元素 + * @example + * ```html + *
+ * + * + * ``` + */ + + /** + * 根据指定的判断规则判断给定的元素是否是一个空元素 + * @method isEmptyBlock + * @param { Element } node 需要判断的元素 + * @param { RegExp } reg 对内容执行判断的正则表达式对象 + * @return { Boolean } 是否是空元素 + */ + isEmptyBlock: function (node, reg) { + if (node.nodeType != 1) return 0; + reg = reg || new RegExp("[ \xa0\t\r\n" + domUtils.fillChar + "]", "g"); + + if ( + node[browser.ie ? "innerText" : "textContent"].replace(reg, "").length > 0 + ) { + return 0; + } + for (var n in dtd.$isNotEmpty) { + if (node.getElementsByTagName(n).length) { + return 0; + } + } + return 1; + }, + + /** + * 移动元素使得该元素的位置移动指定的偏移量的距离 + * @method setViewportOffset + * @param { Element } element 需要设置偏移量的元素 + * @param { Object } offset 偏移量, 形如{ left: 100, top: 50 }的一个键值对, 表示该元素将在 + * 现有的位置上向水平方向偏移offset.left的距离, 在竖直方向上偏移 + * offset.top的距离 + * @example + * ```html + *
+ * + * + * ``` + */ + setViewportOffset: function (element, offset) { + var left = parseInt(element.style.left) | 0; + var top = parseInt(element.style.top) | 0; + var rect = element.getBoundingClientRect(); + var offsetLeft = offset.left - rect.left; + var offsetTop = offset.top - rect.top; + if (offsetLeft) { + element.style.left = left + offsetLeft + "px"; + } + if (offsetTop) { + element.style.top = top + offsetTop + "px"; + } + }, + + /** + * 用“填充字符”填充节点 + * @method fillNode + * @private + * @param { DomDocument } doc 填充的节点所在的docment对象 + * @param { Node } node 需要填充的节点对象 + * @example + * ```html + *
+ * + * + * ``` + */ + fillNode: function (doc, node) { + var tmpNode = browser.ie + ? doc.createTextNode(domUtils.fillChar) + : doc.createElement("br"); + node.innerHTML = ""; + node.appendChild(tmpNode); + }, + + /** + * 把节点src的所有子节点追加到另一个节点tag上去 + * @method moveChild + * @param { Node } src 源节点, 该节点下的所有子节点将被移除 + * @param { Node } tag 目标节点, 从源节点移除的子节点将被追加到该节点下 + * @example + * ```html + *
+ * + *
+ *
+ *
+ *
+ * + * + * ``` + */ + + /** + * 把节点src的所有子节点移动到另一个节点tag上去, 可以通过dir参数控制附加的行为是“追加”还是“插入顶部” + * @method moveChild + * @param { Node } src 源节点, 该节点下的所有子节点将被移除 + * @param { Node } tag 目标节点, 从源节点移除的子节点将被附加到该节点下 + * @param { Boolean } dir 附加方式, 如果为true, 则附加进去的节点将被放到目标节点的顶部, 反之,则放到末尾 + * @example + * ```html + *
+ * + *
+ *
+ *
+ *
+ * + * + * ``` + */ + moveChild: function (src, tag, dir) { + while (src.firstChild) { + if (dir && tag.firstChild) { + tag.insertBefore(src.lastChild, tag.firstChild); + } else { + tag.appendChild(src.firstChild); + } + } + }, + + /** + * 判断节点的标签上是否不存在任何属性 + * @method hasNoAttributes + * @private + * @param { Node } node 需要检测的节点对象 + * @return { Boolean } 节点是否不包含任何属性 + * @example + * ```html + *
xxxx
+ * + * + * ``` + */ + hasNoAttributes: function (node) { + return browser.ie + ? /^<\w+\s*?>/.test(node.outerHTML) + : node.attributes.length == 0; + }, + + /** + * 检测节点是否是UEditor所使用的辅助节点 + * @method isCustomeNode + * @private + * @param { Node } node 需要检测的节点 + * @remind 辅助节点是指编辑器要完成工作临时添加的节点, 在输出的时候将会从编辑器内移除, 不会影响最终的结果。 + * @return { Boolean } 给定的节点是否是一个辅助节点 + */ + isCustomeNode: function (node) { + return node.nodeType == 1 && node.getAttribute("_ue_custom_node_"); + }, + + /** + * 检测节点的标签是否是给定的标签 + * @method isTagNode + * @param { Node } node 需要检测的节点对象 + * @param { String } tagName 标签 + * @return { Boolean } 节点的标签是否是给定的标签 + * @example + * ```html + *
+ * + * + * ``` + */ + isTagNode: function (node, tagNames) { + return ( + node.nodeType == 1 && + new RegExp("\\b" + node.tagName + "\\b", "i").test(tagNames) + ); + }, + + /** + * 给定一个节点数组,在通过指定的过滤器过滤后, 获取其中满足过滤条件的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false + * @return { Node | NULL } 如果找到符合过滤条件的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: null + * console.log( UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() !== 'div'; + * } ) ); + * ``` + */ + + /** + * 给定一个节点数组nodeList和一组标签名tagNames, 获取其中能够匹配标签名的节点集合中的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { String } tagNames 需要匹配的标签名, 多个标签名之间用空格分割 + * @return { Node | NULL } 如果找到标签名匹配的节点, 则返回该节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: null + * console.log( UE.dom.domUtils.filterNodeList( divNodes, 'a span' ) ); + * ``` + */ + + /** + * 给定一个节点数组,在通过指定的过滤器过滤后, 如果参数forAll为true, 则会返回所有满足过滤 + * 条件的节点集合, 否则, 返回满足条件的节点集合中的第一个节点 + * @method filterNodeList + * @param { Array } nodeList 需要过滤的节点数组 + * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false + * @param { Boolean } forAll 是否返回整个节点数组, 如果该参数为false, 则返回节点集合中的第一个节点 + * @return { Array | Node | NULL } 如果找到符合过滤条件的节点, 则根据参数forAll的值决定返回满足 + * 过滤条件的节点数组或第一个节点, 否则返回NULL + * @example + * ```javascript + * var divNodes = document.getElementsByTagName("div"); + * divNodes = [].slice.call( divNodes, 0 ); + * + * //output: 3(假定有3个div) + * console.log( divNodes.length ); + * + * var nodes = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() === 'div'; + * }, true ); + * + * //output: 3 + * console.log( nodes.length ); + * + * var node = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { + * return node.tagName.toLowerCase() === 'div'; + * }, false ); + * + * //output: div + * console.log( node.nodeName ); + * ``` + */ + filterNodeList: function (nodelist, filter, forAll) { + var results = []; + if (!utils.isFunction(filter)) { + var str = filter; + filter = function (n) { + return ( + utils.indexOf( + utils.isArray(str) ? str : str.split(" "), + n.tagName.toLowerCase() + ) != -1 + ); + }; + } + utils.each(nodelist, function (n) { + filter(n) && results.push(n); + }); + return results.length == 0 + ? null + : results.length == 1 || !forAll ? results[0] : results; + }, + + /** + * 查询给定的range选区是否在给定的node节点内,且在该节点的最末尾 + * @method isInNodeEndBoundary + * @param { UE.dom.Range } rng 需要判断的range对象, 该对象的startContainer不能为NULL + * @param node 需要检测的节点对象 + * @return { Number } 如果给定的选取range对象是在node内部的最末端, 则返回1, 否则返回0 + */ + isInNodeEndBoundary: function (rng, node) { + var start = rng.startContainer; + if (start.nodeType == 3 && rng.startOffset != start.nodeValue.length) { + return 0; + } + if (start.nodeType == 1 && rng.startOffset != start.childNodes.length) { + return 0; + } + while (start !== node) { + if (start.nextSibling) { + return 0; + } + start = start.parentNode; + } + return 1; + }, + isBoundaryNode: function (node, dir) { + var tmp; + while (!domUtils.isBody(node)) { + tmp = node; + node = node.parentNode; + if (tmp !== node[dir]) { + return false; + } + } + return true; + }, + fillHtml: browser.ie11below ? " " : "
", + loadScript: function (url, cb) { + var script; + script = document.createElement('script'); + script.src = url; + script.onload = function () { + cb && cb({isNew: true}) + }; + document.getElementsByTagName('head')[0].appendChild(script); } - if (parent.tagName != "A") { - parent === node.parentNode && domUtils.remove(node, true); - break; - } - } - parent = parent.parentNode; - } - }, - /** - * 合并节点node的左右兄弟节点 - * @method mergeSibling - * @param { Element } node 需要合并的目标节点 - * @example - * ```html - * xxxxoooxxxx - * - * - * ``` - */ - - /** - * 合并节点node的左右兄弟节点, 可以根据给定的条件选择是否忽略合并左节点。 - * @method mergeSibling - * @param { Element } node 需要合并的目标节点 - * @param { Boolean } ignorePre 是否忽略合并左节点 - * @example - * ```html - * xxxxoooxxxx - * - * - * ``` - */ - - /** - * 合并节点node的左右兄弟节点,可以根据给定的条件选择是否忽略合并左右节点。 - * @method mergeSibling - * @param { Element } node 需要合并的目标节点 - * @param { Boolean } ignorePre 是否忽略合并左节点 - * @param { Boolean } ignoreNext 是否忽略合并右节点 - * @remind 如果同时忽略左右节点, 则该操作什么也不会做 - * @example - * ```html - * xxxxoooxxxx - * - * - * ``` - */ - mergeSibling: function(node, ignorePre, ignoreNext) { - function merge(rtl, start, node) { - var next; - if ( - (next = node[rtl]) && - !domUtils.isBookmarkNode(next) && - next.nodeType == 1 && - domUtils.isSameElement(node, next) - ) { - while (next.firstChild) { - if (start == "firstChild") { - node.insertBefore(next.lastChild, node.firstChild); - } else { - node.appendChild(next.firstChild); - } - } - domUtils.remove(next); - } - } - !ignorePre && merge("previousSibling", "firstChild", node); - !ignoreNext && merge("nextSibling", "lastChild", node); - }, - - /** - * 设置节点node及其子节点不会被选中 - * @method unSelectable - * @param { Element } node 需要执行操作的dom元素 - * @remind 执行该操作后的节点, 将不能被鼠标选中 - * @example - * ```javascript - * UE.dom.domUtils.unSelectable( document.body ); - * ``` - */ - unSelectable: (ie && browser.ie9below) || browser.opera - ? function(node) { - //for ie9 - node.onselectstart = function() { - return false; - }; - node.onclick = node.onkeyup = node.onkeydown = function() { - return false; - }; - node.unselectable = "on"; - node.setAttribute("unselectable", "on"); - for (var i = 0, ci; (ci = node.all[i++]); ) { - switch (ci.tagName.toLowerCase()) { - case "iframe": - case "textarea": - case "input": - case "select": - break; - default: - ci.unselectable = "on"; - node.setAttribute("unselectable", "on"); - } - } - } - : function(node) { - node.style.MozUserSelect = node.style.webkitUserSelect = node.style.msUserSelect = node.style.KhtmlUserSelect = - "none"; - }, - /** - * 删除节点node上的指定属性名称的属性 - * @method removeAttributes - * @param { Node } node 需要删除属性的节点对象 - * @param { String } attrNames 可以是空格隔开的多个属性名称,该操作将会依次删除相应的属性 - * @example - * ```html - *
- * xxxxx - *
- * - * - * ``` - */ - - /** - * 删除节点node上的指定属性名称的属性 - * @method removeAttributes - * @param { Node } node 需要删除属性的节点对象 - * @param { Array } attrNames 需要删除的属性名数组 - * @example - * ```html - *
- * xxxxx - *
- * - * - * ``` - */ - removeAttributes: function(node, attrNames) { - attrNames = utils.isArray(attrNames) - ? attrNames - : utils.trim(attrNames).replace(/[ ]{2,}/g, " ").split(" "); - for (var i = 0, ci; (ci = attrNames[i++]); ) { - ci = attrFix[ci] || ci; - switch (ci) { - case "className": - node[ci] = ""; - break; - case "style": - node.style.cssText = ""; - var val = node.getAttributeNode("style"); - !browser.ie && val && node.removeAttributeNode(val); - } - node.removeAttribute(ci); - } - }, - /** - * 在doc下创建一个标签名为tag,属性为attrs的元素 - * @method createElement - * @param { DomDocument } doc 新创建的元素属于该document节点创建 - * @param { String } tagName 需要创建的元素的标签名 - * @param { Object } attrs 新创建的元素的属性key-value集合 - * @return { Element } 新创建的元素对象 - * @example - * ```javascript - * var ele = UE.dom.domUtils.createElement( document, 'div', { - * id: 'test' - * } ); - * - * //output: DIV - * console.log( ele.tagName ); - * - * //output: test - * console.log( ele.id ); - * - * ``` - */ - createElement: function(doc, tag, attrs) { - return domUtils.setAttributes(doc.createElement(tag), attrs); - }, - /** - * 为节点node添加属性attrs,attrs为属性键值对 - * @method setAttributes - * @param { Element } node 需要设置属性的元素对象 - * @param { Object } attrs 需要设置的属性名-值对 - * @return { Element } 设置属性的元素对象 - * @example - * ```html - * - * - * - * - */ - setAttributes: function(node, attrs) { - for (var attr in attrs) { - if('_propertyDelete'===attr){ - for(var j=0;j - * #test { - * font-size: 15px; - * } - * - * - * - * - * - * ``` - */ - getComputedStyle: function(element, styleName) { - //以下的属性单独处理 - var pros = "width height top left"; - - if (pros.indexOf(styleName) > -1) { - return ( - element[ - "offset" + - styleName.replace(/^\w/, function(s) { - return s.toUpperCase(); - }) - ] + "px" - ); - } - //忽略文本节点 - if (element.nodeType === 3) { - element = element.parentNode; - } - //ie下font-size若body下定义了font-size,则从currentStyle里会取到这个font-size. 取不到实际值,故此修改. - if ( - browser.ie && - browser.version < 9 && - styleName === "font-size" && - !element.style.fontSize && - !dtd.$empty[element.tagName] && - !dtd.$nonChild[element.tagName] - ) { - var span = element.ownerDocument.createElement("span"); - span.style.cssText = "padding:0;border:0;font-family:simsun;"; - span.innerHTML = "."; - element.appendChild(span); - var result = span.offsetHeight; - element.removeChild(span); - span = null; - return result + "px"; - } - try { - var value = - domUtils.getStyle(element, styleName) || - (window.getComputedStyle - ? domUtils - .getWindow(element) - .getComputedStyle(element, "") - .getPropertyValue(styleName) - : (element.currentStyle || element.style)[ - utils.cssStyleToDomStyle(styleName) - ]); - } catch (e) { - return ""; - } - return utils.transUnitToPx(utils.fixColor(styleName, value)); - }, - /** - * 删除元素element指定的className - * @method removeClasses - * @param { Element } ele 需要删除class的元素节点 - * @param { String } classNames 需要删除的className, 多个className之间以空格分开 - * @example - * ```html - * xxx - * - * - * ``` - */ - - /** - * 删除元素element指定的className - * @method removeClasses - * @param { Element } ele 需要删除class的元素节点 - * @param { Array } classNames 需要删除的className数组 - * @example - * ```html - * xxx - * - * - * ``` - */ - removeClasses: function(elm, classNames) { - classNames = utils.isArray(classNames) - ? classNames - : utils.trim(classNames).replace(/[ ]{2,}/g, " ").split(" "); - for (var i = 0, ci, cls = elm.className; (ci = classNames[i++]); ) { - cls = cls.replace(new RegExp("\\b" + ci + "\\b"), ""); - } - cls = utils.trim(cls).replace(/[ ]{2,}/g, " "); - if (cls) { - elm.className = cls; - } else { - domUtils.removeAttributes(elm, ["class"]); - } - }, - /** - * 给元素element添加className - * @method addClass - * @param { Node } ele 需要增加className的元素 - * @param { String } classNames 需要添加的className, 多个className之间以空格分割 - * @remind 相同的类名不会被重复添加 - * @example - * ```html - * - * - * - * ``` - */ - - /** - * 判断元素element是否包含给定的样式类名className - * @method hasClass - * @param { Node } ele 需要检测的元素 - * @param { Array } classNames 需要检测的className数组 - * @return { Boolean } 元素是否包含所有给定的className - * @example - * ```html - * - * - * - * ``` - */ - hasClass: function(element, className) { - if (utils.isRegExp(className)) { - return className.test(element.className); - } - className = utils.trim(className).replace(/[ ]{2,}/g, " ").split(" "); - for (var i = 0, ci, cls = element.className; (ci = className[i++]); ) { - if (!new RegExp("\\b" + ci + "\\b", "i").test(cls)) { - return false; - } - } - return i - 1 == className.length; - }, - - /** - * 阻止事件默认行为 - * @method preventDefault - * @param { Event } evt 需要阻止默认行为的事件对象 - * @example - * ```javascript - * UE.dom.domUtils.preventDefault( evt ); - * ``` - */ - preventDefault: function(evt) { - evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); - }, - /** - * 删除元素element指定的样式 - * @method removeStyle - * @param { Element } element 需要删除样式的元素 - * @param { String } styleName 需要删除的样式名 - * @example - * ```html - * - * - * - * ``` - */ - removeStyle: function(element, name) { - if (browser.ie) { - //针对color先单独处理一下 - if (name == "color") { - name = "(^|;)" + name; - } - element.style.cssText = element.style.cssText.replace( - new RegExp(name + "[^:]*:[^;]+;?", "ig"), - "" - ); - } else { - if (element.style.removeProperty) { - element.style.removeProperty(name); - } else { - element.style.removeAttribute(utils.cssStyleToDomStyle(name)); - } - } - - if (!element.style.cssText) { - domUtils.removeAttributes(element, ["style"]); - } - }, - /** - * 获取元素element的style属性的指定值 - * @method getStyle - * @param { Element } element 需要获取属性值的元素 - * @param { String } styleName 需要获取的style的名称 - * @warning 该方法仅获取元素style属性中所标明的值 - * @return { String } 该元素包含指定的style属性值 - * @example - * ```html - *
- * - * - * ``` - */ - getStyle: function(element, name) { - var value = element.style[utils.cssStyleToDomStyle(name)]; - return utils.fixColor(name, value); - }, - /** - * 为元素element设置样式属性值 - * @method setStyle - * @param { Element } element 需要设置样式的元素 - * @param { String } styleName 样式名 - * @param { String } styleValue 样式值 - * @example - * ```html - *
- * - * - * ``` - */ - setStyle: function(element, name, value) { - element.style[utils.cssStyleToDomStyle(name)] = value; - if (!utils.trim(element.style.cssText)) { - this.removeAttributes(element, "style"); - } - }, - /** - * 为元素element设置多个样式属性值 - * @method setStyles - * @param { Element } element 需要设置样式的元素 - * @param { Object } styles 样式名值对 - * @example - * ```html - *
- * - * - * ``` - */ - setStyles: function(element, styles) { - for (var name in styles) { - if (styles.hasOwnProperty(name)) { - domUtils.setStyle(element, name, styles[name]); - } - } - }, - /** - * 删除_moz_dirty属性 - * @private - * @method removeDirtyAttr - */ - removeDirtyAttr: function(node) { - for ( - var i = 0, ci, nodes = node.getElementsByTagName("*"); - (ci = nodes[i++]); - - ) { - ci.removeAttribute("_moz_dirty"); - } - node.removeAttribute("_moz_dirty"); - }, - /** - * 获取子节点的数量 - * @method getChildCount - * @param { Element } node 需要检测的元素 - * @return { Number } 给定的node元素的子节点数量 - * @example - * ```html - *
- * - *
- * - * - * ``` - */ - - /** - * 根据给定的过滤规则, 获取符合条件的子节点的数量 - * @method getChildCount - * @param { Element } node 需要检测的元素 - * @param { Function } fn 过滤器, 要求对符合条件的子节点返回true, 反之则要求返回false - * @return { Number } 符合过滤条件的node元素的子节点数量 - * @example - * ```html - *
- * - *
- * - * - * ``` - */ - getChildCount: function(node, fn) { - var count = 0, - first = node.firstChild; - fn = - fn || - function() { - return 1; - }; - while (first) { - if (fn(first)) { - count++; - } - first = first.nextSibling; - } - return count; - }, - - /** - * 判断给定节点是否为空节点 - * @method isEmptyNode - * @param { Node } node 需要检测的节点对象 - * @return { Boolean } 节点是否为空 - * @example - * ```javascript - * UE.dom.domUtils.isEmptyNode( document.body ); - * ``` - */ - isEmptyNode: function(node) { - return ( - !node.firstChild || - domUtils.getChildCount(node, function(node) { - return ( - !domUtils.isBr(node) && - !domUtils.isBookmarkNode(node) && - !domUtils.isWhitespace(node) - ); - }) == 0 - ); - }, - clearSelectedArr: function(nodes) { - var node; - while ((node = nodes.pop())) { - domUtils.removeAttributes(node, ["class"]); - } - }, - /** - * 将显示区域滚动到指定节点的位置 - * @method scrollToView - * @param {Node} node 节点 - * @param {window} win window对象 - * @param {Number} offsetTop 距离上方的偏移量 - */ - scrollToView: function(node, win, offsetTop) { - offsetTop = offsetTop || 0 - var getViewPaneSize = function() { - var doc = win.document, - mode = doc.compatMode == "CSS1Compat"; - return { - width: - (mode ? doc.documentElement.clientWidth : doc.body.clientWidth) || 0, - height: - (mode ? doc.documentElement.clientHeight : doc.body.clientHeight) || 0 - }; - }, - getScrollPosition = function(win) { - if ("pageXOffset" in win) { - return { - x: win.pageXOffset || 0, - y: win.pageYOffset || 0 - }; - } else { - var doc = win.document; - return { - x: doc.documentElement.scrollLeft || doc.body.scrollLeft || 0, - y: doc.documentElement.scrollTop || doc.body.scrollTop || 0 - }; - } - }; - var winHeight = getViewPaneSize().height, - offset = winHeight * -1 + offsetTop; - offset += node.offsetHeight || 0; - var elementPosition = domUtils.getXY(node); - offset += elementPosition.y; - var currentScroll = getScrollPosition(win).y; - // console.log({currentScroll,winHeight,offset,y:elementPosition.y}); - // offset += 50; - if (offset > currentScroll || offset < currentScroll - winHeight) { - win.scrollTo({ - top:offset + (offset < 0 ? -20 : 20), - behavior: "smooth" - }); - } - }, - /** - * 判断给定节点是否为br - * @method isBr - * @param { Node } node 需要判断的节点对象 - * @return { Boolean } 给定的节点是否是br节点 - */ - isBr: function(node) { - return node.nodeType == 1 && node.tagName == "BR"; - }, - /** - * 判断给定的节点是否是一个“填充”节点 - * @private - * @method isFillChar - * @param { Node } node 需要判断的节点 - * @param { Boolean } isInStart 是否从节点内容的开始位置匹配 - * @returns { Boolean } 节点是否是填充节点 - */ - isFillChar: function(node, isInStart) { - if (node.nodeType != 3) return false; - var text = node.nodeValue; - if (isInStart) { - return new RegExp("^" + domUtils.fillChar).test(text); - } - return !text.replace(new RegExp(domUtils.fillChar, "g"), "").length; - }, - isStartInblock: function(range) { - var tmpRange = range.cloneRange(), - flag = 0, - start = tmpRange.startContainer, - tmp; - if (start.nodeType == 1 && start.childNodes[tmpRange.startOffset]) { - start = start.childNodes[tmpRange.startOffset]; - var pre = start.previousSibling; - while (pre && domUtils.isFillChar(pre)) { - start = pre; - pre = pre.previousSibling; - } - } - if (this.isFillChar(start, true) && tmpRange.startOffset == 1) { - tmpRange.setStartBefore(start); - start = tmpRange.startContainer; - } - - while (start && domUtils.isFillChar(start)) { - tmp = start; - start = start.previousSibling; - } - if (tmp) { - tmpRange.setStartBefore(tmp); - start = tmpRange.startContainer; - } - if ( - start.nodeType == 1 && - domUtils.isEmptyNode(start) && - tmpRange.startOffset == 1 - ) { - tmpRange.setStart(start, 0).collapse(true); - } - while (!tmpRange.startOffset) { - start = tmpRange.startContainer; - if (domUtils.isBlockElm(start) || domUtils.isBody(start)) { - flag = 1; - break; - } - var pre = tmpRange.startContainer.previousSibling, - tmpNode; - if (!pre) { - tmpRange.setStartBefore(tmpRange.startContainer); - } else { - while (pre && domUtils.isFillChar(pre)) { - tmpNode = pre; - pre = pre.previousSibling; - } - if (tmpNode) { - tmpRange.setStartBefore(tmpNode); - } else { - tmpRange.setStartBefore(tmpRange.startContainer); - } - } - } - return flag && !domUtils.isBody(tmpRange.startContainer) ? 1 : 0; - }, - - /** - * 判断给定的元素是否是一个空元素 - * @method isEmptyBlock - * @param { Element } node 需要判断的元素 - * @return { Boolean } 是否是空元素 - * @example - * ```html - *
- * - * - * ``` - */ - - /** - * 根据指定的判断规则判断给定的元素是否是一个空元素 - * @method isEmptyBlock - * @param { Element } node 需要判断的元素 - * @param { RegExp } reg 对内容执行判断的正则表达式对象 - * @return { Boolean } 是否是空元素 - */ - isEmptyBlock: function(node, reg) { - if (node.nodeType != 1) return 0; - reg = reg || new RegExp("[ \xa0\t\r\n" + domUtils.fillChar + "]", "g"); - - if ( - node[browser.ie ? "innerText" : "textContent"].replace(reg, "").length > 0 - ) { - return 0; - } - for (var n in dtd.$isNotEmpty) { - if (node.getElementsByTagName(n).length) { - return 0; - } - } - return 1; - }, - - /** - * 移动元素使得该元素的位置移动指定的偏移量的距离 - * @method setViewportOffset - * @param { Element } element 需要设置偏移量的元素 - * @param { Object } offset 偏移量, 形如{ left: 100, top: 50 }的一个键值对, 表示该元素将在 - * 现有的位置上向水平方向偏移offset.left的距离, 在竖直方向上偏移 - * offset.top的距离 - * @example - * ```html - *
- * - * - * ``` - */ - setViewportOffset: function(element, offset) { - var left = parseInt(element.style.left) | 0; - var top = parseInt(element.style.top) | 0; - var rect = element.getBoundingClientRect(); - var offsetLeft = offset.left - rect.left; - var offsetTop = offset.top - rect.top; - if (offsetLeft) { - element.style.left = left + offsetLeft + "px"; - } - if (offsetTop) { - element.style.top = top + offsetTop + "px"; - } - }, - - /** - * 用“填充字符”填充节点 - * @method fillNode - * @private - * @param { DomDocument } doc 填充的节点所在的docment对象 - * @param { Node } node 需要填充的节点对象 - * @example - * ```html - *
- * - * - * ``` - */ - fillNode: function(doc, node) { - var tmpNode = browser.ie - ? doc.createTextNode(domUtils.fillChar) - : doc.createElement("br"); - node.innerHTML = ""; - node.appendChild(tmpNode); - }, - - /** - * 把节点src的所有子节点追加到另一个节点tag上去 - * @method moveChild - * @param { Node } src 源节点, 该节点下的所有子节点将被移除 - * @param { Node } tag 目标节点, 从源节点移除的子节点将被追加到该节点下 - * @example - * ```html - *
- * - *
- *
- *
- *
- * - * - * ``` - */ - - /** - * 把节点src的所有子节点移动到另一个节点tag上去, 可以通过dir参数控制附加的行为是“追加”还是“插入顶部” - * @method moveChild - * @param { Node } src 源节点, 该节点下的所有子节点将被移除 - * @param { Node } tag 目标节点, 从源节点移除的子节点将被附加到该节点下 - * @param { Boolean } dir 附加方式, 如果为true, 则附加进去的节点将被放到目标节点的顶部, 反之,则放到末尾 - * @example - * ```html - *
- * - *
- *
- *
- *
- * - * - * ``` - */ - moveChild: function(src, tag, dir) { - while (src.firstChild) { - if (dir && tag.firstChild) { - tag.insertBefore(src.lastChild, tag.firstChild); - } else { - tag.appendChild(src.firstChild); - } - } - }, - - /** - * 判断节点的标签上是否不存在任何属性 - * @method hasNoAttributes - * @private - * @param { Node } node 需要检测的节点对象 - * @return { Boolean } 节点是否不包含任何属性 - * @example - * ```html - *
xxxx
- * - * - * ``` - */ - hasNoAttributes: function(node) { - return browser.ie - ? /^<\w+\s*?>/.test(node.outerHTML) - : node.attributes.length == 0; - }, - - /** - * 检测节点是否是UEditor所使用的辅助节点 - * @method isCustomeNode - * @private - * @param { Node } node 需要检测的节点 - * @remind 辅助节点是指编辑器要完成工作临时添加的节点, 在输出的时候将会从编辑器内移除, 不会影响最终的结果。 - * @return { Boolean } 给定的节点是否是一个辅助节点 - */ - isCustomeNode: function(node) { - return node.nodeType == 1 && node.getAttribute("_ue_custom_node_"); - }, - - /** - * 检测节点的标签是否是给定的标签 - * @method isTagNode - * @param { Node } node 需要检测的节点对象 - * @param { String } tagName 标签 - * @return { Boolean } 节点的标签是否是给定的标签 - * @example - * ```html - *
- * - * - * ``` - */ - isTagNode: function(node, tagNames) { - return ( - node.nodeType == 1 && - new RegExp("\\b" + node.tagName + "\\b", "i").test(tagNames) - ); - }, - - /** - * 给定一个节点数组,在通过指定的过滤器过滤后, 获取其中满足过滤条件的第一个节点 - * @method filterNodeList - * @param { Array } nodeList 需要过滤的节点数组 - * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false - * @return { Node | NULL } 如果找到符合过滤条件的节点, 则返回该节点, 否则返回NULL - * @example - * ```javascript - * var divNodes = document.getElementsByTagName("div"); - * divNodes = [].slice.call( divNodes, 0 ); - * - * //output: null - * console.log( UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { - * return node.tagName.toLowerCase() !== 'div'; - * } ) ); - * ``` - */ - - /** - * 给定一个节点数组nodeList和一组标签名tagNames, 获取其中能够匹配标签名的节点集合中的第一个节点 - * @method filterNodeList - * @param { Array } nodeList 需要过滤的节点数组 - * @param { String } tagNames 需要匹配的标签名, 多个标签名之间用空格分割 - * @return { Node | NULL } 如果找到标签名匹配的节点, 则返回该节点, 否则返回NULL - * @example - * ```javascript - * var divNodes = document.getElementsByTagName("div"); - * divNodes = [].slice.call( divNodes, 0 ); - * - * //output: null - * console.log( UE.dom.domUtils.filterNodeList( divNodes, 'a span' ) ); - * ``` - */ - - /** - * 给定一个节点数组,在通过指定的过滤器过滤后, 如果参数forAll为true, 则会返回所有满足过滤 - * 条件的节点集合, 否则, 返回满足条件的节点集合中的第一个节点 - * @method filterNodeList - * @param { Array } nodeList 需要过滤的节点数组 - * @param { Function } fn 过滤器, 对符合条件的节点, 执行结果返回true, 反之则返回false - * @param { Boolean } forAll 是否返回整个节点数组, 如果该参数为false, 则返回节点集合中的第一个节点 - * @return { Array | Node | NULL } 如果找到符合过滤条件的节点, 则根据参数forAll的值决定返回满足 - * 过滤条件的节点数组或第一个节点, 否则返回NULL - * @example - * ```javascript - * var divNodes = document.getElementsByTagName("div"); - * divNodes = [].slice.call( divNodes, 0 ); - * - * //output: 3(假定有3个div) - * console.log( divNodes.length ); - * - * var nodes = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { - * return node.tagName.toLowerCase() === 'div'; - * }, true ); - * - * //output: 3 - * console.log( nodes.length ); - * - * var node = UE.dom.domUtils.filterNodeList( divNodes, function ( node ) { - * return node.tagName.toLowerCase() === 'div'; - * }, false ); - * - * //output: div - * console.log( node.nodeName ); - * ``` - */ - filterNodeList: function(nodelist, filter, forAll) { - var results = []; - if (!utils.isFunction(filter)) { - var str = filter; - filter = function(n) { - return ( - utils.indexOf( - utils.isArray(str) ? str : str.split(" "), - n.tagName.toLowerCase() - ) != -1 - ); - }; - } - utils.each(nodelist, function(n) { - filter(n) && results.push(n); }); - return results.length == 0 - ? null - : results.length == 1 || !forAll ? results[0] : results; - }, - - /** - * 查询给定的range选区是否在给定的node节点内,且在该节点的最末尾 - * @method isInNodeEndBoundary - * @param { UE.dom.Range } rng 需要判断的range对象, 该对象的startContainer不能为NULL - * @param node 需要检测的节点对象 - * @return { Number } 如果给定的选取range对象是在node内部的最末端, 则返回1, 否则返回0 - */ - isInNodeEndBoundary: function(rng, node) { - var start = rng.startContainer; - if (start.nodeType == 3 && rng.startOffset != start.nodeValue.length) { - return 0; - } - if (start.nodeType == 1 && rng.startOffset != start.childNodes.length) { - return 0; - } - while (start !== node) { - if (start.nextSibling) { - return 0; - } - start = start.parentNode; - } - return 1; - }, - isBoundaryNode: function(node, dir) { - var tmp; - while (!domUtils.isBody(node)) { - tmp = node; - node = node.parentNode; - if (tmp !== node[dir]) { - return false; - } - } - return true; - }, - fillHtml: browser.ie11below ? " " : "
", - loadScript : function (url, cb) { - var script; - script = document.createElement('script'); - script.src = url; - script.onload = function(){ - cb && cb({isNew: true}) - }; - document.getElementsByTagName('head')[0].appendChild(script); - } -}); -var fillCharReg = new RegExp(domUtils.fillChar, "g"); + var fillCharReg = new RegExp(domUtils.fillChar, "g"); // core/Range.js -/** - * Range封装 - * @file - * @module UE.dom - * @class Range - * @since 1.2.6.1 - */ - -/** - * dom操作封装 - * @unfile - * @module UE.dom - */ - -/** - * Range实现类,本类是UEditor底层核心类,封装不同浏览器之间的Range操作。 - * @unfile - * @module UE.dom - * @class Range - */ - -(function() { - var guid = 0, - fillChar = domUtils.fillChar, - fillData; - - /** - * 更新range的collapse状态 - * @param {Range} range range对象 + /** + * Range封装 + * @file + * @module UE.dom + * @class Range + * @since 1.2.6.1 */ - function updateCollapse(range) { - range.collapsed = - range.startContainer && - range.endContainer && - range.startContainer === range.endContainer && - range.startOffset === range.endOffset; - } - function selectOneNode(rng) { - return ( - !rng.collapsed && - rng.startContainer.nodeType === 1 && - rng.startContainer === rng.endContainer && - rng.endOffset - rng.startOffset === 1 - ); - } - function setEndPoint(toStart, node, offset, range) { - //如果node是自闭合标签要处理 - if ( - node.nodeType === 1 && - (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName]) - ) { - offset = domUtils.getNodeIndex(node) + (toStart ? 0 : 1); - node = node.parentNode; - } - if (toStart) { - range.startContainer = node; - range.startOffset = offset; - if (!range.endContainer) { - range.collapse(true); - } - } else { - range.endContainer = node; - range.endOffset = offset; - if (!range.startContainer) { - range.collapse(false); - } - } - updateCollapse(range); - return range; - } + /** + * dom操作封装 + * @unfile + * @module UE.dom + */ - function execContentsAction(range, action) { - //调整边界 - //range.includeBookmark(); - var start = range.startContainer, - end = range.endContainer, - startOffset = range.startOffset, - endOffset = range.endOffset, - doc = range.document, - frag = doc.createDocumentFragment(), - tmpStart, - tmpEnd; - if (start.nodeType == 1) { - start = - start.childNodes[startOffset] || - (tmpStart = start.appendChild(doc.createTextNode(""))); - } - if (end.nodeType == 1) { - end = - end.childNodes[endOffset] || - (tmpEnd = end.appendChild(doc.createTextNode(""))); - } - if (start === end && start.nodeType == 3) { - frag.appendChild( - doc.createTextNode( - start.substringData(startOffset, endOffset - startOffset) - ) - ); - //is not clone - if (action) { - start.deleteData(startOffset, endOffset - startOffset); - range.collapse(true); - } - return frag; - } - var current, - currentLevel, - clone = frag, - startParents = domUtils.findParents(start, true), - endParents = domUtils.findParents(end, true); - for (var i = 0; startParents[i] == endParents[i]; ) { - i++; - } - for (var j = i, si; (si = startParents[j]); j++) { - current = si.nextSibling; - if (si == start) { - if (!tmpStart) { - if (range.startContainer.nodeType == 3) { - clone.appendChild( - doc.createTextNode(start.nodeValue.slice(startOffset)) + /** + * Range实现类,本类是UEditor底层核心类,封装不同浏览器之间的Range操作。 + * @unfile + * @module UE.dom + * @class Range + */ + + (function () { + var guid = 0, + fillChar = domUtils.fillChar, + fillData; + + /** + * 更新range的collapse状态 + * @param {Range} range range对象 + */ + function updateCollapse(range) { + range.collapsed = + range.startContainer && + range.endContainer && + range.startContainer === range.endContainer && + range.startOffset === range.endOffset; + } + + function selectOneNode(rng) { + return ( + !rng.collapsed && + rng.startContainer.nodeType === 1 && + rng.startContainer === rng.endContainer && + rng.endOffset - rng.startOffset === 1 ); - //is not clone - if (action) { - start.deleteData( - startOffset, - start.nodeValue.length - startOffset - ); - } - } else { - clone.appendChild(!action ? start.cloneNode(true) : start); - } } - } else { - currentLevel = si.cloneNode(false); - clone.appendChild(currentLevel); - } - while (current) { - if (current === end || current === endParents[j]) { - break; - } - si = current.nextSibling; - clone.appendChild(!action ? current.cloneNode(true) : current); - current = si; - } - clone = currentLevel; - } - clone = frag; - if (!startParents[i]) { - clone.appendChild(startParents[i - 1].cloneNode(false)); - clone = clone.firstChild; - } - for (var j = i, ei; (ei = endParents[j]); j++) { - current = ei.previousSibling; - if (ei == end) { - if (!tmpEnd && range.endContainer.nodeType == 3) { - clone.appendChild( - doc.createTextNode(end.substringData(0, endOffset)) - ); - //is not clone - if (action) { - end.deleteData(0, endOffset); - } - } - } else { - currentLevel = ei.cloneNode(false); - clone.appendChild(currentLevel); - } - //如果两端同级,右边第一次已经被开始做了 - if (j != i || !startParents[i]) { - while (current) { - if (current === start) { - break; - } - ei = current.previousSibling; - clone.insertBefore( - !action ? current.cloneNode(true) : current, - clone.firstChild - ); - current = ei; - } - } - clone = currentLevel; - } - if (action) { - range - .setStartBefore( - !endParents[i] - ? endParents[i - 1] - : !startParents[i] ? startParents[i - 1] : endParents[i] - ) - .collapse(true); - } - tmpStart && domUtils.remove(tmpStart); - tmpEnd && domUtils.remove(tmpEnd); - return frag; - } - /** - * 创建一个跟document绑定的空的Range实例 - * @constructor - * @param { Document } document 新建的选区所属的文档对象 - */ - - /** - * @property { Node } startContainer 当前Range的开始边界的容器节点, 可以是一个元素节点或者是文本节点 - */ - - /** - * @property { Node } startOffset 当前Range的开始边界容器节点的偏移量, 如果是元素节点, - * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符 - */ - - /** - * @property { Node } endContainer 当前Range的结束边界的容器节点, 可以是一个元素节点或者是文本节点 - */ - - /** - * @property { Node } endOffset 当前Range的结束边界容器节点的偏移量, 如果是元素节点, - * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符 - */ - - /** - * @property { Boolean } collapsed 当前Range是否闭合 - * @default true - * @remind Range是闭合的时候, startContainer === endContainer && startOffset === endOffset - */ - - /** - * @property { Document } document 当前Range所属的Document对象 - * @remind 不同range的的document属性可以是不同的 - */ - var Range = (dom.Range = function(document) { - var me = this; - me.startContainer = me.startOffset = me.endContainer = me.endOffset = null; - me.document = document; - me.collapsed = true; - }); - - /** - * 删除fillData - * @param doc - * @param excludeNode - */ - function removeFillData(doc, excludeNode) { - try { - if (fillData && domUtils.inDoc(fillData, doc)) { - if (!fillData.nodeValue.replace(fillCharReg, "").length) { - var tmpNode = fillData.parentNode; - domUtils.remove(fillData); - while ( - tmpNode && - domUtils.isEmptyInlineElement(tmpNode) && - //safari的contains有bug - (browser.safari - ? !( - domUtils.getPosition(tmpNode, excludeNode) & - domUtils.POSITION_CONTAINS - ) - : !tmpNode.contains(excludeNode)) - ) { - fillData = tmpNode.parentNode; - domUtils.remove(tmpNode); - tmpNode = fillData; - } - } else { - fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, ""); - } - } - } catch (e) {} - } - - /** - * @param node - * @param dir - */ - function mergeSibling(node, dir) { - var tmpNode; - node = node[dir]; - while (node && domUtils.isFillChar(node)) { - tmpNode = node[dir]; - domUtils.remove(node); - node = tmpNode; - } - } - - Range.prototype = { - /** - * 克隆选区的内容到一个DocumentFragment里 - * @method cloneContents - * @return { DocumentFragment | NULL } 如果选区是闭合的将返回null, 否则, 返回包含所clone内容的DocumentFragment元素 - * @example - * ```html - * - * - * xx[xxx]x - * - * - * - * ``` - */ - cloneContents: function() { - return this.collapsed ? null : execContentsAction(this, 0); - }, - - /** - * 删除当前选区范围中的所有内容 - * @method deleteContents - * @remind 执行完该操作后, 当前Range对象变成了闭合状态 - * @return { UE.dom.Range } 当前操作的Range对象 - * @example - * ```html - * - * - * xx[xxx]x - * - * - * - * ``` - */ - deleteContents: function() { - var txt; - if (!this.collapsed) { - execContentsAction(this, 1); - } - if (browser.webkit) { - txt = this.startContainer; - if (txt.nodeType == 3 && !txt.nodeValue.length) { - this.setStartBefore(txt).collapse(true); - domUtils.remove(txt); - } - } - return this; - }, - - /** - * 将当前选区的内容提取到一个DocumentFragment里 - * @method extractContents - * @remind 执行该操作后, 选区将变成闭合状态 - * @warning 执行该操作后, 原来选区所选中的内容将从dom树上剥离出来 - * @return { DocumentFragment } 返回包含所提取内容的DocumentFragment对象 - * @example - * ```html - * - * - * xx[xxx]x - * - * - * - */ - extractContents: function() { - return this.collapsed ? null : execContentsAction(this, 2); - }, - - /** - * 设置Range的开始容器节点和偏移量 - * @method setStart - * @remind 如果给定的节点是元素节点,那么offset指的是其子元素中索引为offset的元素, - * 如果是文本节点,那么offset指的是其文本内容的第offset个字符 - * @remind 如果提供的容器节点是一个不能包含子元素的节点, 则该选区的开始容器将被设置 - * 为该节点的父节点, 此时, 其距离开始容器的偏移量也变成了该节点在其父节点 - * 中的索引 - * @param { Node } node 将被设为当前选区开始边界容器的节点对象 - * @param { int } offset 选区的开始位置偏移量 - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * - * xxxxxxxxxxxxx[xxx] - * - * - * ``` - * @example - * ```html - * - * xxx[xx]x - * - * - * ``` - */ - setStart: function(node, offset) { - return setEndPoint(true, node, offset, this); - }, - - /** - * 设置Range的结束容器和偏移量 - * @method setEnd - * @param { Node } node 作为当前选区结束边界容器的节点对象 - * @param { int } offset 结束边界的偏移量 - * @see UE.dom.Range:setStart(Node,int) - * @return { UE.dom.Range } 当前range对象 - */ - setEnd: function(node, offset) { - return setEndPoint(false, node, offset, this); - }, - - /** - * 将Range开始位置设置到node节点之后 - * @method setStartAfter - * @remind 该操作将会把给定节点的父节点作为range的开始容器, 且偏移量是该节点在其父节点中的位置索引+1 - * @param { Node } node 选区的开始边界将紧接着该节点之后 - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * - * xxxxxxx[xxxx] - * - * - * ``` - */ - setStartAfter: function(node) { - return this.setStart(node.parentNode, domUtils.getNodeIndex(node) + 1); - }, - - /** - * 将Range开始位置设置到node节点之前 - * @method setStartBefore - * @remind 该操作将会把给定节点的父节点作为range的开始容器, 且偏移量是该节点在其父节点中的位置索引 - * @param { Node } node 新的选区开始位置在该节点之前 - * @see UE.dom.Range:setStartAfter(Node) - * @return { UE.dom.Range } 当前range对象 - */ - setStartBefore: function(node) { - return this.setStart(node.parentNode, domUtils.getNodeIndex(node)); - }, - - /** - * 将Range结束位置设置到node节点之后 - * @method setEndAfter - * @remind 该操作将会把给定节点的父节点作为range的结束容器, 且偏移量是该节点在其父节点中的位置索引+1 - * @param { Node } node 目标节点 - * @see UE.dom.Range:setStartAfter(Node) - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * - * [xxxxxxx]xxxx - * - * - * ``` - */ - setEndAfter: function(node) { - return this.setEnd(node.parentNode, domUtils.getNodeIndex(node) + 1); - }, - - /** - * 将Range结束位置设置到node节点之前 - * @method setEndBefore - * @remind 该操作将会把给定节点的父节点作为range的结束容器, 且偏移量是该节点在其父节点中的位置索引 - * @param { Node } node 目标节点 - * @see UE.dom.Range:setEndAfter(Node) - * @return { UE.dom.Range } 当前range对象 - */ - setEndBefore: function(node) { - return this.setEnd(node.parentNode, domUtils.getNodeIndex(node)); - }, - - /** - * 设置Range的开始位置到node节点内的第一个子节点之前 - * @method setStartAtFirst - * @remind 选区的开始容器将变成给定的节点, 且偏移量为0 - * @remind 如果给定的节点是元素节点, 则该节点必须是允许包含子节点的元素。 - * @param { Node } node 目标节点 - * @see UE.dom.Range:setStartBefore(Node) - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * - * xxxxx[xx]xxxx - * - * - * ``` - */ - setStartAtFirst: function(node) { - return this.setStart(node, 0); - }, - - /** - * 设置Range的开始位置到node节点内的最后一个节点之后 - * @method setStartAtLast - * @remind 选区的开始容器将变成给定的节点, 且偏移量为该节点的子节点数 - * @remind 如果给定的节点是元素节点, 则该节点必须是允许包含子节点的元素。 - * @param { Node } node 目标节点 - * @see UE.dom.Range:setStartAtFirst(Node) - * @return { UE.dom.Range } 当前range对象 - */ - setStartAtLast: function(node) { - return this.setStart( - node, - node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length - ); - }, - - /** - * 设置Range的结束位置到node节点内的第一个节点之前 - * @method setEndAtFirst - * @param { Node } node 目标节点 - * @remind 选区的结束容器将变成给定的节点, 且偏移量为0 - * @remind node必须是一个元素节点, 且必须是允许包含子节点的元素。 - * @see UE.dom.Range:setStartAtFirst(Node) - * @return { UE.dom.Range } 当前range对象 - */ - setEndAtFirst: function(node) { - return this.setEnd(node, 0); - }, - - /** - * 设置Range的结束位置到node节点内的最后一个节点之后 - * @method setEndAtLast - * @param { Node } node 目标节点 - * @remind 选区的结束容器将变成给定的节点, 且偏移量为该节点的子节点数量 - * @remind node必须是一个元素节点, 且必须是允许包含子节点的元素。 - * @see UE.dom.Range:setStartAtFirst(Node) - * @return { UE.dom.Range } 当前range对象 - */ - setEndAtLast: function(node) { - return this.setEnd( - node, - node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length - ); - }, - - /** - * 选中给定节点 - * @method selectNode - * @remind 此时, 选区的开始容器和结束容器都是该节点的父节点, 其startOffset是该节点在父节点中的位置索引, - * 而endOffset为startOffset+1 - * @param { Node } node 需要选中的节点 - * @return { UE.dom.Range } 当前range对象,此时的range仅包含当前给定的节点对象 - * @example - * ```html - * - * xxxxx[xx]xxxx - * - * - * ``` - */ - selectNode: function(node) { - return this.setStartBefore(node).setEndAfter(node); - }, - - /** - * 选中给定节点内部的所有节点 - * @method selectNodeContents - * @remind 此时, 选区的开始容器和结束容器都是该节点, 其startOffset为0, - * 而endOffset是该节点的子节点数。 - * @param { Node } node 目标节点, 当前range将包含该节点内的所有节点 - * @return { UE.dom.Range } 当前range对象, 此时range仅包含给定节点的所有子节点 - * @example - * ```html - * - * xxxxx[xx]xxxx - * - * - * ``` - */ - selectNodeContents: function(node) { - return this.setStart(node, 0).setEndAtLast(node); - }, - - /** - * clone当前Range对象 - * @method cloneRange - * @remind 返回的range是一个全新的range对象, 其内部所有属性与当前被clone的range相同。 - * @return { UE.dom.Range } 当前range对象的一个副本 - */ - cloneRange: function() { - var me = this; - return new Range(me.document) - .setStart(me.startContainer, me.startOffset) - .setEnd(me.endContainer, me.endOffset); - }, - - /** - * 向当前选区的结束处闭合选区 - * @method collapse - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * - * xxxxx[xx]xxxx - * - * - * ``` - */ - - /** - * 闭合当前选区,根据给定的toStart参数项决定是向当前选区开始处闭合还是向结束处闭合, - * 如果toStart的值为true,则向开始位置闭合, 反之,向结束位置闭合。 - * @method collapse - * @param { Boolean } toStart 是否向选区开始处闭合 - * @return { UE.dom.Range } 当前range对象,此时range对象处于闭合状态 - * @see UE.dom.Range:collapse() - * @example - * ```html - * - * xxxxx[xx]xxxx - * - * - * ``` - */ - collapse: function(toStart) { - var me = this; - if (toStart) { - me.endContainer = me.startContainer; - me.endOffset = me.startOffset; - } else { - me.startContainer = me.endContainer; - me.startOffset = me.endOffset; - } - me.collapsed = true; - return me; - }, - - /** - * 调整range的开始位置和结束位置,使其"收缩"到最小的位置 - * @method shrinkBoundary - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * xxxx[xxxxx] => xxxx[xxxxx] - * ``` - * - * @example - * ```html - * - * x[xx]xxx - * - * - * ``` - * - * @example - * ```html - * [xxxxxxxxxxx] => [xxxxxxxxxxx] - * ``` - */ - - /** - * 调整range的开始位置和结束位置,使其"收缩"到最小的位置, - * 如果ignoreEnd的值为true,则忽略对结束位置的调整 - * @method shrinkBoundary - * @param { Boolean } ignoreEnd 是否忽略对结束位置的调整 - * @return { UE.dom.Range } 当前range对象 - * @see UE.dom.domUtils.Range:shrinkBoundary() - */ - shrinkBoundary: function(ignoreEnd) { - var me = this, - child, - collapsed = me.collapsed; - function check(node) { - return ( - node.nodeType == 1 && - !domUtils.isBookmarkNode(node) && - !dtd.$empty[node.tagName] && - !dtd.$nonChild[node.tagName] - ); - } - while ( - me.startContainer.nodeType == 1 && //是element - (child = me.startContainer.childNodes[me.startOffset]) && //子节点也是element - check(child) - ) { - me.setStart(child, 0); - } - if (collapsed) { - return me.collapse(true); - } - if (!ignoreEnd) { - while ( - me.endContainer.nodeType == 1 && //是element - me.endOffset > 0 && //如果是空元素就退出 endOffset=0那么endOffst-1为负值,childNodes[endOffset]报错 - (child = me.endContainer.childNodes[me.endOffset - 1]) && //子节点也是element - check(child) - ) { - me.setEnd(child, child.childNodes.length); - } - } - return me; - }, - - /** - * 获取离当前选区内包含的所有节点最近的公共祖先节点, - * @method getCommonAncestor - * @remind 返回的公共祖先节点一定不是range自身的容器节点, 但有可能是一个文本节点 - * @return { Node } 当前range对象内所有节点的公共祖先节点 - * @example - * ```html - * //选区示例 - * xxxx[xxx]xxxxxx - * - * ``` - */ - - /** - * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到 - * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf - * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点 - * @method getCommonAncestor - * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点 - * @return { Node } 当前range对象内所有节点的公共祖先节点 - * @see UE.dom.Range:getCommonAncestor() - * @example - * ```html - * - * - * - * xxxxxxxxx[xxx]xxxxxxxx - * - * - * - * - * ``` - */ - - /** - * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到 - * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf - * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点; 同时可以根据 - * ignoreTextNode 参数的取值决定是否忽略类型为文本节点的祖先节点。 - * @method getCommonAncestor - * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点 - * @param { Boolean } ignoreTextNode 获取祖先节点的过程中是否忽略类型为文本节点的祖先节点 - * @return { Node } 当前range对象内所有节点的公共祖先节点 - * @see UE.dom.Range:getCommonAncestor() - * @see UE.dom.Range:getCommonAncestor(Boolean) - * @example - * ```html - * - * - * - * xxxxxxxx[x]xxxxxxxxxxx - * - * - * - * - * ``` - */ - getCommonAncestor: function(includeSelf, ignoreTextNode) { - var me = this, - start = me.startContainer, - end = me.endContainer; - if (start === end) { - if (includeSelf && selectOneNode(this)) { - start = start.childNodes[me.startOffset]; - if (start.nodeType == 1) return start; - } - //只有在上来就相等的情况下才会出现是文本的情况 - return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start; - } - return domUtils.getCommonAncestor(start, end); - }, - - /** - * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上 - * @method trimBoundary - * @remind 该操作有可能会引起文本节点被切开 - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * - * //选区示例 - * xxx[xxxxx]xxx - * - * - * ``` - */ - - /** - * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上, - * 可以根据 ignoreEnd 参数的值决定是否调整对结束边界的调整 - * @method trimBoundary - * @param { Boolean } ignoreEnd 是否忽略对结束边界的调整 - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * - * //选区示例 - * xxx[xxxxx]xxx - * - * - * ``` - */ - trimBoundary: function(ignoreEnd) { - this.txtToElmBoundary(); - var start = this.startContainer, - offset = this.startOffset, - collapsed = this.collapsed, - end = this.endContainer; - if (start.nodeType == 3) { - if (offset == 0) { - this.setStartBefore(start); - } else { - if (offset >= start.nodeValue.length) { - this.setStartAfter(start); - } else { - var textNode = domUtils.split(start, offset); - //跟新结束边界 - if (start === end) { - this.setEnd(textNode, this.endOffset - offset); - } else if (start.parentNode === end) { - this.endOffset += 1; - } - this.setStartBefore(textNode); - } - } - if (collapsed) { - return this.collapse(true); - } - } - if (!ignoreEnd) { - offset = this.endOffset; - end = this.endContainer; - if (end.nodeType == 3) { - if (offset == 0) { - this.setEndBefore(end); - } else { - offset < end.nodeValue.length && domUtils.split(end, offset); - this.setEndAfter(end); - } - } - } - return this; - }, - - /** - * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则什么也不做 - * @method txtToElmBoundary - * @remind 该操作不会修改dom节点 - * @return { UE.dom.Range } 当前range对象 - */ - - /** - * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则根据参数项 - * ignoreCollapsed 的值决定是否执行该调整 - * @method txtToElmBoundary - * @param { Boolean } ignoreCollapsed 是否忽略选区的闭合状态, 如果该参数取值为true, 则 - * 不论选区是否闭合, 都会执行该操作, 反之, 则不会对闭合的选区执行该操作 - * @return { UE.dom.Range } 当前range对象 - */ - txtToElmBoundary: function(ignoreCollapsed) { - function adjust(r, c) { - var container = r[c + "Container"], - offset = r[c + "Offset"]; - if (container.nodeType == 3) { - if (!offset) { - r[ - "set" + - c.replace(/(\w)/, function(a) { - return a.toUpperCase(); - }) + - "Before" - ](container); - } else if (offset >= container.nodeValue.length) { - r[ - "set" + - c.replace(/(\w)/, function(a) { - return a.toUpperCase(); - }) + - "After" - ](container); - } - } - } - - if (ignoreCollapsed || !this.collapsed) { - adjust(this, "start"); - adjust(this, "end"); - } - return this; - }, - - /** - * 在当前选区的开始位置前插入节点,新插入的节点会被该range包含 - * @method insertNode - * @param { Node } node 需要插入的节点 - * @remind 插入的节点可以是一个DocumentFragment依次插入多个节点 - * @return { UE.dom.Range } 当前range对象 - */ - insertNode: function(node) { - var first = node, - length = 1; - if (node.nodeType == 11) { - first = node.firstChild; - length = node.childNodes.length; - } - this.trimBoundary(true); - var start = this.startContainer, - offset = this.startOffset; - var nextNode = start.childNodes[offset]; - if (nextNode) { - start.insertBefore(node, nextNode); - } else { - start.appendChild(node); - } - if (first.parentNode === this.endContainer) { - this.endOffset = this.endOffset + length; - } - return this.setStartBefore(first); - }, - - /** - * 闭合选区到当前选区的开始位置, 并且定位光标到闭合后的位置 - * @method setCursor - * @return { UE.dom.Range } 当前range对象 - * @see UE.dom.Range:collapse() - */ - - /** - * 闭合选区,可以根据参数toEnd的值控制选区是向前闭合还是向后闭合, 并且定位光标到闭合后的位置。 - * @method setCursor - * @param { Boolean } toEnd 是否向后闭合, 如果为true, 则闭合选区时, 将向结束容器方向闭合, - * 反之,则向开始容器方向闭合 - * @return { UE.dom.Range } 当前range对象 - * @see UE.dom.Range:collapse(Boolean) - */ - setCursor: function(toEnd, noFillData) { - return this.collapse(!toEnd).select(noFillData); - }, - - /** - * 创建当前range的一个书签,记录下当前range的位置,方便当dom树改变时,还能找回原来的选区位置 - * @method createBookmark - * @param { Boolean } serialize 控制返回的标记位置是对当前位置的引用还是ID,如果该值为true,则 - * 返回标记位置的ID, 反之则返回标记位置节点的引用 - * @return { Object } 返回一个书签记录键值对, 其包含的key有: start => 开始标记的ID或者引用, - * end => 结束标记的ID或引用, id => 当前标记的类型, 如果为true,则表示 - * 返回的记录的类型为ID, 反之则为引用 - */ - createBookmark: function(serialize, same) { - var endNode, - startNode = this.document.createElement("span"); - startNode.style.cssText = "display:none;line-height:0px;"; - startNode.appendChild(this.document.createTextNode("\u200D")); - startNode.id = "_baidu_bookmark_start_" + (same ? "" : guid++); - - if (!this.collapsed) { - endNode = startNode.cloneNode(true); - endNode.id = "_baidu_bookmark_end_" + (same ? "" : guid++); - } - this.insertNode(startNode); - if (endNode) { - this.collapse().insertNode(endNode).setEndBefore(endNode); - } - this.setStartAfter(startNode); - return { - start: serialize ? startNode.id : startNode, - end: endNode ? (serialize ? endNode.id : endNode) : null, - id: serialize - }; - }, - - /** - * 调整当前range的边界到书签位置,并删除该书签对象所标记的位置内的节点 - * @method moveToBookmark - * @param { BookMark } bookmark createBookmark所创建的标签对象 - * @return { UE.dom.Range } 当前range对象 - * @see UE.dom.Range:createBookmark(Boolean) - */ - moveToBookmark: function(bookmark) { - var start = bookmark.id - ? this.document.getElementById(bookmark.start) - : bookmark.start, - end = bookmark.end && bookmark.id - ? this.document.getElementById(bookmark.end) - : bookmark.end; - this.setStartBefore(start); - domUtils.remove(start); - if (end) { - this.setEndBefore(end); - domUtils.remove(end); - } else { - this.collapse(true); - } - return this; - }, - - /** - * 调整range的边界,使其"放大"到最近的父节点 - * @method enlarge - * @remind 会引起选区的变化 - * @return { UE.dom.Range } 当前range对象 - */ - - /** - * 调整range的边界,使其"放大"到最近的父节点,根据参数 toBlock 的取值, 可以 - * 要求扩大之后的父节点是block节点 - * @method enlarge - * @param { Boolean } toBlock 是否要求扩大之后的父节点必须是block节点 - * @return { UE.dom.Range } 当前range对象 - */ - enlarge: function(toBlock, stopFn) { - var isBody = domUtils.isBody, - pre, - node, - tmp = this.document.createTextNode(""); - if (toBlock) { - node = this.startContainer; - if (node.nodeType == 1) { - if (node.childNodes[this.startOffset]) { - pre = node = node.childNodes[this.startOffset]; - } else { - node.appendChild(tmp); - pre = node = tmp; - } - } else { - pre = node; - } - while (1) { - if (domUtils.isBlockElm(node)) { - node = pre; - while ((pre = node.previousSibling) && !domUtils.isBlockElm(pre)) { - node = pre; - } - this.setStartBefore(node); - break; - } - pre = node; - node = node.parentNode; - } - node = this.endContainer; - if (node.nodeType == 1) { - if ((pre = node.childNodes[this.endOffset])) { - node.insertBefore(tmp, pre); - } else { - node.appendChild(tmp); - } - pre = node = tmp; - } else { - pre = node; - } - while (1) { - if (domUtils.isBlockElm(node)) { - node = pre; - while ((pre = node.nextSibling) && !domUtils.isBlockElm(pre)) { - node = pre; - } - this.setEndAfter(node); - break; - } - pre = node; - node = node.parentNode; - } - if (tmp.parentNode === this.endContainer) { - this.endOffset--; - } - domUtils.remove(tmp); - } - - // 扩展边界到最大 - if (!this.collapsed) { - while (this.startOffset == 0) { - if (stopFn && stopFn(this.startContainer)) { - break; - } - if (isBody(this.startContainer)) { - break; - } - this.setStartBefore(this.startContainer); - } - while ( - this.endOffset == - (this.endContainer.nodeType == 1 - ? this.endContainer.childNodes.length - : this.endContainer.nodeValue.length) - ) { - if (stopFn && stopFn(this.endContainer)) { - break; - } - if (isBody(this.endContainer)) { - break; - } - this.setEndAfter(this.endContainer); - } - } - return this; - }, - enlargeToBlockElm: function(ignoreEnd) { - while (!domUtils.isBlockElm(this.startContainer)) { - this.setStartBefore(this.startContainer); - } - if (!ignoreEnd) { - while (!domUtils.isBlockElm(this.endContainer)) { - this.setEndAfter(this.endContainer); - } - } - return this; - }, - /** - * 调整Range的边界,使其"缩小"到最合适的位置 - * @method adjustmentBoundary - * @return { UE.dom.Range } 当前range对象 - * @see UE.dom.Range:shrinkBoundary() - */ - adjustmentBoundary: function() { - if (!this.collapsed) { - while ( - !domUtils.isBody(this.startContainer) && - this.startOffset == - this.startContainer[ - this.startContainer.nodeType == 3 ? "nodeValue" : "childNodes" - ].length && - this.startContainer[ - this.startContainer.nodeType == 3 ? "nodeValue" : "childNodes" - ].length - ) { - this.setStartAfter(this.startContainer); - } - while ( - !domUtils.isBody(this.endContainer) && - !this.endOffset && - this.endContainer[ - this.endContainer.nodeType == 3 ? "nodeValue" : "childNodes" - ].length - ) { - this.setEndBefore(this.endContainer); - } - } - return this; - }, - - /** - * 给range选区中的内容添加给定的inline标签 - * @method applyInlineStyle - * @param { String } tagName 需要添加的标签名 - * @example - * ```html - *

xxxx[xxxx]x

==> range.applyInlineStyle("strong") ==>

xxxx[xxxx]x

- * ``` - */ - - /** - * 给range选区中的内容添加给定的inline标签, 并且为标签附加上一些初始化属性。 - * @method applyInlineStyle - * @param { String } tagName 需要添加的标签名 - * @param { Object } attrs 跟随新添加的标签的属性 - * @return { UE.dom.Range } 当前选区 - * @example - * ```html - *

xxxx[xxxx]x

- * - * ==> - * - * - * range.applyInlineStyle("strong",{"style":"font-size:12px"}) - * - * ==> - * - *

xxxx[xxxx]x

- * ``` - */ - applyInlineStyle: function(tagName, attrs, list) { - if (this.collapsed) return this; - this.trimBoundary() - .enlarge(false, function(node) { - return node.nodeType == 1 && domUtils.isBlockElm(node); - }) - .adjustmentBoundary(); - var bookmark = this.createBookmark(), - end = bookmark.end, - filterFn = function(node) { - return node.nodeType == 1 - ? node.tagName.toLowerCase() != "br" - : !domUtils.isWhitespace(node); - }, - current = domUtils.getNextDomNode(bookmark.start, false, filterFn), - node, - pre, - range = this.cloneRange(); - while ( - current && - domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING - ) { - if (current.nodeType == 3 || dtd[tagName][current.tagName]) { - range.setStartBefore(current); - node = current; - while ( - node && - (node.nodeType == 3 || dtd[tagName][node.tagName]) && - node !== end - ) { - pre = node; - node = domUtils.getNextDomNode( - node, - node.nodeType == 1, - null, - function(parent) { - return dtd[tagName][parent.tagName]; - } - ); - } - var frag = range.setEndAfter(pre).extractContents(), - elm; - if (list && list.length > 0) { - var level, top; - top = level = list[0].cloneNode(false); - for (var i = 1, ci; (ci = list[i++]); ) { - level.appendChild(ci.cloneNode(false)); - level = level.firstChild; - } - elm = level; - } else { - elm = range.document.createElement(tagName); - } - if (attrs) { - domUtils.setAttributes(elm, attrs); - } - elm.appendChild(frag); - //针对嵌套span的全局样式指定,做容错处理 - if (elm.tagName == "SPAN" && attrs && attrs.style) { - utils.each(elm.getElementsByTagName("span"), function(s) { - s.style.cssText = s.style.cssText + ";" + attrs.style; - }); - } - range.insertNode(list ? top : elm); - //处理下滑线在a上的情况 - var aNode; - if ( - tagName == "span" && - attrs.style && - /text\-decoration/.test(attrs.style) && - (aNode = domUtils.findParentByTagName(elm, "a", true)) - ) { - domUtils.setAttributes(aNode, attrs); - domUtils.remove(elm, true); - elm = aNode; - } else { - domUtils.mergeSibling(elm); - domUtils.clearEmptySibling(elm); - } - //去除子节点相同的 - domUtils.mergeChild(elm, attrs); - current = domUtils.getNextDomNode(elm, false, filterFn); - domUtils.mergeToParent(elm); - if (node === end) { - break; - } - } else { - current = domUtils.getNextDomNode(current, true, filterFn); - } - } - return this.moveToBookmark(bookmark); - }, - - /** - * 移除当前选区内指定的inline标签,但保留其中的内容 - * @method removeInlineStyle - * @param { String } tagName 需要移除的标签名 - * @return { UE.dom.Range } 当前的range对象 - * @example - * ```html - * xx[xxxxyyyzz]z => range.removeInlineStyle(["em"]) => xx[xxxxyyyzz]z - * ``` - */ - - /** - * 移除当前选区内指定的一组inline标签,但保留其中的内容 - * @method removeInlineStyle - * @param { Array } tagNameArr 需要移除的标签名的数组 - * @return { UE.dom.Range } 当前的range对象 - * @see UE.dom.Range:removeInlineStyle(String) - */ - removeInlineStyle: function(tagNames) { - if (this.collapsed) return this; - tagNames = utils.isArray(tagNames) ? tagNames : [tagNames]; - this.shrinkBoundary().adjustmentBoundary(); - var start = this.startContainer, - end = this.endContainer; - while (1) { - if (start.nodeType == 1) { - if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) { - break; - } - if (start.tagName.toLowerCase() == "body") { - start = null; - break; - } - } - start = start.parentNode; - } - while (1) { - if (end.nodeType == 1) { - if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) { - break; - } - if (end.tagName.toLowerCase() == "body") { - end = null; - break; - } - } - end = end.parentNode; - } - var bookmark = this.createBookmark(), - frag, - tmpRange; - if (start) { - tmpRange = this.cloneRange() - .setEndBefore(bookmark.start) - .setStartBefore(start); - frag = tmpRange.extractContents(); - tmpRange.insertNode(frag); - domUtils.clearEmptySibling(start, true); - start.parentNode.insertBefore(bookmark.start, start); - } - if (end) { - tmpRange = this.cloneRange() - .setStartAfter(bookmark.end) - .setEndAfter(end); - frag = tmpRange.extractContents(); - tmpRange.insertNode(frag); - domUtils.clearEmptySibling(end, false, true); - end.parentNode.insertBefore(bookmark.end, end.nextSibling); - } - var current = domUtils.getNextDomNode(bookmark.start, false, function( - node - ) { - return node.nodeType == 1; - }), - next; - while (current && current !== bookmark.end) { - next = domUtils.getNextDomNode(current, true, function(node) { - return node.nodeType == 1; - }); - if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) { - domUtils.remove(current, true); - } - current = next; - } - return this.moveToBookmark(bookmark); - }, - - /** - * 获取当前选中的自闭合的节点 - * @method getClosedNode - * @return { Node | NULL } 如果当前选中的是自闭合节点, 则返回该节点, 否则返回NULL - */ - getClosedNode: function() { - var node; - if (!this.collapsed) { - var range = this.cloneRange().adjustmentBoundary().shrinkBoundary(); - if (selectOneNode(range)) { - var child = range.startContainer.childNodes[range.startOffset]; - if ( - child && - child.nodeType === 1 && - (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName]) - ) { - node = child; - } - } - } - return node; - }, - - /** - * 在页面上高亮range所表示的选区 - * @method select - * @return { UE.dom.Range } 返回当前Range对象 - */ - //这里不区分ie9以上,trace:3824 - select: browser.ie - ? function(noFillData, textRange) { - var nativeRange; - if (!this.collapsed) this.shrinkBoundary(); - var node = this.getClosedNode(); - if (node && !textRange) { - try { - nativeRange = this.document.body.createControlRange(); - nativeRange.addElement(node); - nativeRange.select(); - } catch (e) {} - return this; - } - var bookmark = this.createBookmark(), - start = bookmark.start, - end; - nativeRange = this.document.body.createTextRange(); - nativeRange.moveToElementText(start); - nativeRange.moveStart("character", 1); - if (!this.collapsed) { - var nativeRangeEnd = this.document.body.createTextRange(); - end = bookmark.end; - nativeRangeEnd.moveToElementText(end); - nativeRange.setEndPoint("EndToEnd", nativeRangeEnd); - } else { - if (!noFillData && this.startContainer.nodeType != 3) { - //使用|x固定住光标 - var tmpText = this.document.createTextNode(fillChar), - tmp = this.document.createElement("span"); - tmp.appendChild(this.document.createTextNode(fillChar)); - start.parentNode.insertBefore(tmp, start); - start.parentNode.insertBefore(tmpText, start); - //当点b,i,u时,不能清除i上边的b - removeFillData(this.document, tmpText); - fillData = tmpText; - mergeSibling(tmp, "previousSibling"); - mergeSibling(start, "nextSibling"); - nativeRange.moveStart("character", -1); - nativeRange.collapse(true); - } - } - this.moveToBookmark(bookmark); - tmp && domUtils.remove(tmp); - //IE在隐藏状态下不支持range操作,catch一下 - try { - nativeRange.select(); - } catch (e) {} - return this; - } - : function(notInsertFillData) { - function checkOffset(rng) { - function check(node, offset, dir) { - if (node.nodeType == 3 && node.nodeValue.length < offset) { - rng[dir + "Offset"] = node.nodeValue.length; - } - } - check(rng.startContainer, rng.startOffset, "start"); - check(rng.endContainer, rng.endOffset, "end"); - } - var win = domUtils.getWindow(this.document), - sel = win.getSelection(), - txtNode; - //FF下关闭自动长高时滚动条在关闭dialog时会跳 - //ff下如果不body.focus将不能定位闭合光标到编辑器内 - browser.gecko ? this.document.body.focus() : win.focus(); - if (sel) { - sel.removeAllRanges(); - // trace:870 chrome/safari后边是br对于闭合得range不能定位 所以去掉了判断 - // this.startContainer.nodeType != 3 &&! ((child = this.startContainer.childNodes[this.startOffset]) && child.nodeType == 1 && child.tagName == 'BR' - if (this.collapsed && !notInsertFillData) { - // //opear如果没有节点接着,原生的不能够定位,不能在body的第一级插入空白节点 - // if (notInsertFillData && browser.opera && !domUtils.isBody(this.startContainer) && this.startContainer.nodeType == 1) { - // var tmp = this.document.createTextNode(''); - // this.insertNode(tmp).setStart(tmp, 0).collapse(true); - // } - // - //处理光标落在文本节点的情况 - //处理以下的情况 - //|xxxx - //xxxx|xxxx - //xxxx| - var start = this.startContainer, - child = start; - if (start.nodeType == 1) { - child = start.childNodes[this.startOffset]; - } - if ( - !(start.nodeType == 3 && this.startOffset) && - (child - ? !child.previousSibling || - child.previousSibling.nodeType != 3 - : !start.lastChild || start.lastChild.nodeType != 3) - ) { - txtNode = this.document.createTextNode(fillChar); - //跟着前边走 - this.insertNode(txtNode); - removeFillData(this.document, txtNode); - mergeSibling(txtNode, "previousSibling"); - mergeSibling(txtNode, "nextSibling"); - fillData = txtNode; - this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true); - } - } - var nativeRange = this.document.createRange(); + function setEndPoint(toStart, node, offset, range) { + //如果node是自闭合标签要处理 if ( - this.collapsed && - browser.opera && - this.startContainer.nodeType == 1 + node.nodeType === 1 && + (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName]) ) { - var child = this.startContainer.childNodes[this.startOffset]; - if (!child) { - //往前靠拢 - child = this.startContainer.lastChild; - if (child && domUtils.isBr(child)) { - this.setStartBefore(child).collapse(true); - } - } else { - //向后靠拢 - while (child && domUtils.isBlockElm(child)) { - if (child.nodeType == 1 && child.childNodes[0]) { - child = child.childNodes[0]; - } else { - break; - } - } - child && this.setStartBefore(child).collapse(true); - } + offset = domUtils.getNodeIndex(node) + (toStart ? 0 : 1); + node = node.parentNode; } - //是createAddress最后一位算的不准,现在这里进行微调 - checkOffset(this); - nativeRange.setStart(this.startContainer, this.startOffset); - nativeRange.setEnd(this.endContainer, this.endOffset); - sel.addRange(nativeRange); - } - return this; - }, - - /** - * 滚动到当前range开始的位置 - * @method scrollToView - * @param { Window } win 当前range对象所属的window对象 - * @return { UE.dom.Range } 当前Range对象 - */ - - /** - * 滚动到距离当前range开始位置 offset 的位置处 - * @method scrollToView - * @param { Window } win 当前range对象所属的window对象 - * @param { Number } offset 距离range开始位置处的偏移量, 如果为正数, 则向下偏移, 反之, 则向上偏移 - * @return { UE.dom.Range } 当前Range对象 - */ - scrollToView: function(win, offset) { - win = win ? window : domUtils.getWindow(this.document); - offset = offset || (win.innerHeight - 100); - // console.log('xxx',win, offset); - var me = this, - span = me.document.createElement("span"); - //trace:717 - span.innerHTML = " "; - me.cloneRange().insertNode(span); - domUtils.scrollToView(span, win, offset); - domUtils.remove(span); - return me; - }, - - /** - * 判断当前选区内容是否占位符 - * @private - * @method inFillChar - * @return { Boolean } 如果是占位符返回true,否则返回false - */ - inFillChar: function() { - var start = this.startContainer; - if ( - this.collapsed && - start.nodeType == 3 && - start.nodeValue.replace(new RegExp("^" + domUtils.fillChar), "") - .length + - 1 == - start.nodeValue.length - ) { - return true; - } - return false; - }, - - /** - * 保存 - * @method createAddress - * @private - * @return { Boolean } 返回开始和结束的位置 - * @example - * ```html - * - *

- * aaaa - * - * - * bbbb - * - * - *

- * - * - * - * ``` - */ - createAddress: function(ignoreEnd, ignoreTxt) { - var addr = {}, - me = this; - - function getAddress(isStart) { - var node = isStart ? me.startContainer : me.endContainer; - var parents = domUtils.findParents(node, true, function(node) { - return !domUtils.isBody(node); - }), - addrs = []; - for (var i = 0, ci; (ci = parents[i++]); ) { - addrs.push(domUtils.getNodeIndex(ci, ignoreTxt)); - } - var firstIndex = 0; - - if (ignoreTxt) { - if (node.nodeType == 3) { - var tmpNode = node.previousSibling; - while (tmpNode && tmpNode.nodeType == 3) { - firstIndex += tmpNode.nodeValue.replace(fillCharReg, "").length; - tmpNode = tmpNode.previousSibling; - } - firstIndex += isStart ? me.startOffset : me.endOffset; // - (fillCharReg.test(node.nodeValue) ? 1 : 0 ) - } else { - node = node.childNodes[isStart ? me.startOffset : me.endOffset]; - if (node) { - firstIndex = domUtils.getNodeIndex(node, ignoreTxt); + if (toStart) { + range.startContainer = node; + range.startOffset = offset; + if (!range.endContainer) { + range.collapse(true); + } } else { - node = isStart ? me.startContainer : me.endContainer; - var first = node.firstChild; - while (first) { - if (domUtils.isFillChar(first)) { - first = first.nextSibling; - continue; + range.endContainer = node; + range.endOffset = offset; + if (!range.startContainer) { + range.collapse(false); } - firstIndex++; - if (first.nodeType == 3) { - while (first && first.nodeType == 3) { - first = first.nextSibling; - } - } else { - first = first.nextSibling; - } - } } - } - } else { - firstIndex = isStart - ? domUtils.isFillChar(node) ? 0 : me.startOffset - : me.endOffset; + updateCollapse(range); + return range; } - if (firstIndex < 0) { - firstIndex = 0; - } - addrs.push(firstIndex); - return addrs; - } - addr.startAddress = getAddress(true); - if (!ignoreEnd) { - addr.endAddress = me.collapsed - ? [].concat(addr.startAddress) - : getAddress(); - } - return addr; - }, - /** - * 保存 - * @method createAddress - * @private - * @return { Boolean } 返回开始和结束的位置 - * @example - * ```html - * - *

- * aaaa - * - * - * bbbb - * - * - *

- * - * - * - * ``` - */ - moveToAddress: function(addr, ignoreEnd) { - var me = this; - function getNode(address, isStart) { - var tmpNode = me.document.body, - parentNode, - offset; - for (var i = 0, ci, l = address.length; i < l; i++) { - ci = address[i]; - parentNode = tmpNode; - tmpNode = tmpNode.childNodes[ci]; - if (!tmpNode) { - offset = ci; - break; - } + function execContentsAction(range, action) { + //调整边界 + //range.includeBookmark(); + var start = range.startContainer, + end = range.endContainer, + startOffset = range.startOffset, + endOffset = range.endOffset, + doc = range.document, + frag = doc.createDocumentFragment(), + tmpStart, + tmpEnd; + if (start.nodeType == 1) { + start = + start.childNodes[startOffset] || + (tmpStart = start.appendChild(doc.createTextNode(""))); + } + if (end.nodeType == 1) { + end = + end.childNodes[endOffset] || + (tmpEnd = end.appendChild(doc.createTextNode(""))); + } + if (start === end && start.nodeType == 3) { + frag.appendChild( + doc.createTextNode( + start.substringData(startOffset, endOffset - startOffset) + ) + ); + //is not clone + if (action) { + start.deleteData(startOffset, endOffset - startOffset); + range.collapse(true); + } + return frag; + } + var current, + currentLevel, + clone = frag, + startParents = domUtils.findParents(start, true), + endParents = domUtils.findParents(end, true); + for (var i = 0; startParents[i] == endParents[i];) { + i++; + } + for (var j = i, si; (si = startParents[j]); j++) { + current = si.nextSibling; + if (si == start) { + if (!tmpStart) { + if (range.startContainer.nodeType == 3) { + clone.appendChild( + doc.createTextNode(start.nodeValue.slice(startOffset)) + ); + //is not clone + if (action) { + start.deleteData( + startOffset, + start.nodeValue.length - startOffset + ); + } + } else { + clone.appendChild(!action ? start.cloneNode(true) : start); + } + } + } else { + currentLevel = si.cloneNode(false); + clone.appendChild(currentLevel); + } + while (current) { + if (current === end || current === endParents[j]) { + break; + } + si = current.nextSibling; + clone.appendChild(!action ? current.cloneNode(true) : current); + current = si; + } + clone = currentLevel; + } + clone = frag; + if (!startParents[i]) { + clone.appendChild(startParents[i - 1].cloneNode(false)); + clone = clone.firstChild; + } + for (var j = i, ei; (ei = endParents[j]); j++) { + current = ei.previousSibling; + if (ei == end) { + if (!tmpEnd && range.endContainer.nodeType == 3) { + clone.appendChild( + doc.createTextNode(end.substringData(0, endOffset)) + ); + //is not clone + if (action) { + end.deleteData(0, endOffset); + } + } + } else { + currentLevel = ei.cloneNode(false); + clone.appendChild(currentLevel); + } + //如果两端同级,右边第一次已经被开始做了 + if (j != i || !startParents[i]) { + while (current) { + if (current === start) { + break; + } + ei = current.previousSibling; + clone.insertBefore( + !action ? current.cloneNode(true) : current, + clone.firstChild + ); + current = ei; + } + } + clone = currentLevel; + } + if (action) { + range + .setStartBefore( + !endParents[i] + ? endParents[i - 1] + : !startParents[i] ? startParents[i - 1] : endParents[i] + ) + .collapse(true); + } + tmpStart && domUtils.remove(tmpStart); + tmpEnd && domUtils.remove(tmpEnd); + return frag; } - if (isStart) { - if (tmpNode) { - me.setStartBefore(tmpNode); - } else { - me.setStart(parentNode, offset); - } - } else { - if (tmpNode) { - me.setEndBefore(tmpNode); - } else { - me.setEnd(parentNode, offset); - } - } - } - getNode(addr.startAddress, true); - !ignoreEnd && addr.endAddress && getNode(addr.endAddress); - return me; - }, - /** - * 判断给定的Range对象是否和当前Range对象表示的是同一个选区 - * @method equals - * @param { UE.dom.Range } 需要判断的Range对象 - * @return { Boolean } 如果给定的Range对象与当前Range对象表示的是同一个选区, 则返回true, 否则返回false - */ - equals: function(rng) { - for (var p in this) { - if (this.hasOwnProperty(p)) { - if (this[p] !== rng[p]) return false; - } - } - return true; - }, - - /** - * 遍历range内的节点。每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 - * 作为其参数。 - * @method traversal - * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 - * @return { UE.dom.Range } 当前range对象 - * @example - * ```html - * - * - * - * - * - * - * - * - * - * - * ``` + /** + * 创建一个跟document绑定的空的Range实例 + * @constructor + * @param { Document } document 新建的选区所属的文档对象 */ - /** - * 遍历range内的节点。 - * 每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 - * 作为其参数。 - * 可以通过参数项 filterFn 来指定一个过滤器, 只有符合该过滤器过滤规则的节点才会触 - * 发doFn函数的执行 - * @method traversal - * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 - * @param { Function } filterFn 过滤器, 该函数接受当前遍历的节点作为参数, 如果该节点满足过滤 - * 规则, 请返回true, 该节点会触发doFn, 否则, 请返回false, 则该节点不 - * 会触发doFn。 - * @return { UE.dom.Range } 当前range对象 - * @see UE.dom.Range:traversal(Function) - * @example - * ```html - * - * - * - * - * - * - * - * - * - * - * ``` + /** + * @property { Node } startContainer 当前Range的开始边界的容器节点, 可以是一个元素节点或者是文本节点 */ - traversal: function(doFn, filterFn) { - if (this.collapsed) return this; - var bookmark = this.createBookmark(), - end = bookmark.end, - current = domUtils.getNextDomNode(bookmark.start, false, filterFn); - while ( - current && - current !== end && - domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING - ) { - var tmpNode = domUtils.getNextDomNode(current, false, filterFn); - doFn(current); - current = tmpNode; - } - return this.moveToBookmark(bookmark); - } - }; -})(); + + /** + * @property { Node } startOffset 当前Range的开始边界容器节点的偏移量, 如果是元素节点, + * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符 + */ + + /** + * @property { Node } endContainer 当前Range的结束边界的容器节点, 可以是一个元素节点或者是文本节点 + */ + + /** + * @property { Node } endOffset 当前Range的结束边界容器节点的偏移量, 如果是元素节点, + * 该值就是childNodes中的第几个节点, 如果是文本节点就是文本内容的第几个字符 + */ + + /** + * @property { Boolean } collapsed 当前Range是否闭合 + * @default true + * @remind Range是闭合的时候, startContainer === endContainer && startOffset === endOffset + */ + + /** + * @property { Document } document 当前Range所属的Document对象 + * @remind 不同range的的document属性可以是不同的 + */ + var Range = (dom.Range = function (document) { + var me = this; + me.startContainer = me.startOffset = me.endContainer = me.endOffset = null; + me.document = document; + me.collapsed = true; + }); + + /** + * 删除fillData + * @param doc + * @param excludeNode + */ + function removeFillData(doc, excludeNode) { + try { + if (fillData && domUtils.inDoc(fillData, doc)) { + if (!fillData.nodeValue.replace(fillCharReg, "").length) { + var tmpNode = fillData.parentNode; + domUtils.remove(fillData); + while ( + tmpNode && + domUtils.isEmptyInlineElement(tmpNode) && + //safari的contains有bug + (browser.safari + ? !( + domUtils.getPosition(tmpNode, excludeNode) & + domUtils.POSITION_CONTAINS + ) + : !tmpNode.contains(excludeNode)) + ) { + fillData = tmpNode.parentNode; + domUtils.remove(tmpNode); + tmpNode = fillData; + } + } else { + fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, ""); + } + } + } catch (e) { + } + } + + /** + * @param node + * @param dir + */ + function mergeSibling(node, dir) { + var tmpNode; + node = node[dir]; + while (node && domUtils.isFillChar(node)) { + tmpNode = node[dir]; + domUtils.remove(node); + node = tmpNode; + } + } + + Range.prototype = { + /** + * 克隆选区的内容到一个DocumentFragment里 + * @method cloneContents + * @return { DocumentFragment | NULL } 如果选区是闭合的将返回null, 否则, 返回包含所clone内容的DocumentFragment元素 + * @example + * ```html + * + * + * xx[xxx]x + * + * + * + * ``` + */ + cloneContents: function () { + return this.collapsed ? null : execContentsAction(this, 0); + }, + + /** + * 删除当前选区范围中的所有内容 + * @method deleteContents + * @remind 执行完该操作后, 当前Range对象变成了闭合状态 + * @return { UE.dom.Range } 当前操作的Range对象 + * @example + * ```html + * + * + * xx[xxx]x + * + * + * + * ``` + */ + deleteContents: function () { + var txt; + if (!this.collapsed) { + execContentsAction(this, 1); + } + if (browser.webkit) { + txt = this.startContainer; + if (txt.nodeType == 3 && !txt.nodeValue.length) { + this.setStartBefore(txt).collapse(true); + domUtils.remove(txt); + } + } + return this; + }, + + /** + * 将当前选区的内容提取到一个DocumentFragment里 + * @method extractContents + * @remind 执行该操作后, 选区将变成闭合状态 + * @warning 执行该操作后, 原来选区所选中的内容将从dom树上剥离出来 + * @return { DocumentFragment } 返回包含所提取内容的DocumentFragment对象 + * @example + * ```html + * + * + * xx[xxx]x + * + * + * + */ + extractContents: function () { + return this.collapsed ? null : execContentsAction(this, 2); + }, + + /** + * 设置Range的开始容器节点和偏移量 + * @method setStart + * @remind 如果给定的节点是元素节点,那么offset指的是其子元素中索引为offset的元素, + * 如果是文本节点,那么offset指的是其文本内容的第offset个字符 + * @remind 如果提供的容器节点是一个不能包含子元素的节点, 则该选区的开始容器将被设置 + * 为该节点的父节点, 此时, 其距离开始容器的偏移量也变成了该节点在其父节点 + * 中的索引 + * @param { Node } node 将被设为当前选区开始边界容器的节点对象 + * @param { int } offset 选区的开始位置偏移量 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * xxxxxxxxxxxxx[xxx] + * + * + * ``` + * @example + * ```html + * + * xxx[xx]x + * + * + * ``` + */ + setStart: function (node, offset) { + return setEndPoint(true, node, offset, this); + }, + + /** + * 设置Range的结束容器和偏移量 + * @method setEnd + * @param { Node } node 作为当前选区结束边界容器的节点对象 + * @param { int } offset 结束边界的偏移量 + * @see UE.dom.Range:setStart(Node,int) + * @return { UE.dom.Range } 当前range对象 + */ + setEnd: function (node, offset) { + return setEndPoint(false, node, offset, this); + }, + + /** + * 将Range开始位置设置到node节点之后 + * @method setStartAfter + * @remind 该操作将会把给定节点的父节点作为range的开始容器, 且偏移量是该节点在其父节点中的位置索引+1 + * @param { Node } node 选区的开始边界将紧接着该节点之后 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * xxxxxxx[xxxx] + * + * + * ``` + */ + setStartAfter: function (node) { + return this.setStart(node.parentNode, domUtils.getNodeIndex(node) + 1); + }, + + /** + * 将Range开始位置设置到node节点之前 + * @method setStartBefore + * @remind 该操作将会把给定节点的父节点作为range的开始容器, 且偏移量是该节点在其父节点中的位置索引 + * @param { Node } node 新的选区开始位置在该节点之前 + * @see UE.dom.Range:setStartAfter(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setStartBefore: function (node) { + return this.setStart(node.parentNode, domUtils.getNodeIndex(node)); + }, + + /** + * 将Range结束位置设置到node节点之后 + * @method setEndAfter + * @remind 该操作将会把给定节点的父节点作为range的结束容器, 且偏移量是该节点在其父节点中的位置索引+1 + * @param { Node } node 目标节点 + * @see UE.dom.Range:setStartAfter(Node) + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * [xxxxxxx]xxxx + * + * + * ``` + */ + setEndAfter: function (node) { + return this.setEnd(node.parentNode, domUtils.getNodeIndex(node) + 1); + }, + + /** + * 将Range结束位置设置到node节点之前 + * @method setEndBefore + * @remind 该操作将会把给定节点的父节点作为range的结束容器, 且偏移量是该节点在其父节点中的位置索引 + * @param { Node } node 目标节点 + * @see UE.dom.Range:setEndAfter(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setEndBefore: function (node) { + return this.setEnd(node.parentNode, domUtils.getNodeIndex(node)); + }, + + /** + * 设置Range的开始位置到node节点内的第一个子节点之前 + * @method setStartAtFirst + * @remind 选区的开始容器将变成给定的节点, 且偏移量为0 + * @remind 如果给定的节点是元素节点, 则该节点必须是允许包含子节点的元素。 + * @param { Node } node 目标节点 + * @see UE.dom.Range:setStartBefore(Node) + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + setStartAtFirst: function (node) { + return this.setStart(node, 0); + }, + + /** + * 设置Range的开始位置到node节点内的最后一个节点之后 + * @method setStartAtLast + * @remind 选区的开始容器将变成给定的节点, 且偏移量为该节点的子节点数 + * @remind 如果给定的节点是元素节点, 则该节点必须是允许包含子节点的元素。 + * @param { Node } node 目标节点 + * @see UE.dom.Range:setStartAtFirst(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setStartAtLast: function (node) { + return this.setStart( + node, + node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length + ); + }, + + /** + * 设置Range的结束位置到node节点内的第一个节点之前 + * @method setEndAtFirst + * @param { Node } node 目标节点 + * @remind 选区的结束容器将变成给定的节点, 且偏移量为0 + * @remind node必须是一个元素节点, 且必须是允许包含子节点的元素。 + * @see UE.dom.Range:setStartAtFirst(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setEndAtFirst: function (node) { + return this.setEnd(node, 0); + }, + + /** + * 设置Range的结束位置到node节点内的最后一个节点之后 + * @method setEndAtLast + * @param { Node } node 目标节点 + * @remind 选区的结束容器将变成给定的节点, 且偏移量为该节点的子节点数量 + * @remind node必须是一个元素节点, 且必须是允许包含子节点的元素。 + * @see UE.dom.Range:setStartAtFirst(Node) + * @return { UE.dom.Range } 当前range对象 + */ + setEndAtLast: function (node) { + return this.setEnd( + node, + node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length + ); + }, + + /** + * 选中给定节点 + * @method selectNode + * @remind 此时, 选区的开始容器和结束容器都是该节点的父节点, 其startOffset是该节点在父节点中的位置索引, + * 而endOffset为startOffset+1 + * @param { Node } node 需要选中的节点 + * @return { UE.dom.Range } 当前range对象,此时的range仅包含当前给定的节点对象 + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + selectNode: function (node) { + return this.setStartBefore(node).setEndAfter(node); + }, + + /** + * 选中给定节点内部的所有节点 + * @method selectNodeContents + * @remind 此时, 选区的开始容器和结束容器都是该节点, 其startOffset为0, + * 而endOffset是该节点的子节点数。 + * @param { Node } node 目标节点, 当前range将包含该节点内的所有节点 + * @return { UE.dom.Range } 当前range对象, 此时range仅包含给定节点的所有子节点 + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + selectNodeContents: function (node) { + return this.setStart(node, 0).setEndAtLast(node); + }, + + /** + * clone当前Range对象 + * @method cloneRange + * @remind 返回的range是一个全新的range对象, 其内部所有属性与当前被clone的range相同。 + * @return { UE.dom.Range } 当前range对象的一个副本 + */ + cloneRange: function () { + var me = this; + return new Range(me.document) + .setStart(me.startContainer, me.startOffset) + .setEnd(me.endContainer, me.endOffset); + }, + + /** + * 向当前选区的结束处闭合选区 + * @method collapse + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + + /** + * 闭合当前选区,根据给定的toStart参数项决定是向当前选区开始处闭合还是向结束处闭合, + * 如果toStart的值为true,则向开始位置闭合, 反之,向结束位置闭合。 + * @method collapse + * @param { Boolean } toStart 是否向选区开始处闭合 + * @return { UE.dom.Range } 当前range对象,此时range对象处于闭合状态 + * @see UE.dom.Range:collapse() + * @example + * ```html + * + * xxxxx[xx]xxxx + * + * + * ``` + */ + collapse: function (toStart) { + var me = this; + if (toStart) { + me.endContainer = me.startContainer; + me.endOffset = me.startOffset; + } else { + me.startContainer = me.endContainer; + me.startOffset = me.endOffset; + } + me.collapsed = true; + return me; + }, + + /** + * 调整range的开始位置和结束位置,使其"收缩"到最小的位置 + * @method shrinkBoundary + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * xxxx[xxxxx] => xxxx[xxxxx] + * ``` + * + * @example + * ```html + * + * x[xx]xxx + * + * + * ``` + * + * @example + * ```html + * [xxxxxxxxxxx] => [xxxxxxxxxxx] + * ``` + */ + + /** + * 调整range的开始位置和结束位置,使其"收缩"到最小的位置, + * 如果ignoreEnd的值为true,则忽略对结束位置的调整 + * @method shrinkBoundary + * @param { Boolean } ignoreEnd 是否忽略对结束位置的调整 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.domUtils.Range:shrinkBoundary() + */ + shrinkBoundary: function (ignoreEnd) { + var me = this, + child, + collapsed = me.collapsed; + + function check(node) { + return ( + node.nodeType == 1 && + !domUtils.isBookmarkNode(node) && + !dtd.$empty[node.tagName] && + !dtd.$nonChild[node.tagName] + ); + } + + while ( + me.startContainer.nodeType == 1 && //是element + (child = me.startContainer.childNodes[me.startOffset]) && //子节点也是element + check(child) + ) { + me.setStart(child, 0); + } + if (collapsed) { + return me.collapse(true); + } + if (!ignoreEnd) { + while ( + me.endContainer.nodeType == 1 && //是element + me.endOffset > 0 && //如果是空元素就退出 endOffset=0那么endOffst-1为负值,childNodes[endOffset]报错 + (child = me.endContainer.childNodes[me.endOffset - 1]) && //子节点也是element + check(child) + ) { + me.setEnd(child, child.childNodes.length); + } + } + return me; + }, + + /** + * 获取离当前选区内包含的所有节点最近的公共祖先节点, + * @method getCommonAncestor + * @remind 返回的公共祖先节点一定不是range自身的容器节点, 但有可能是一个文本节点 + * @return { Node } 当前range对象内所有节点的公共祖先节点 + * @example + * ```html + * //选区示例 + * xxxx[xxx]xxxxxx + * + * ``` + */ + + /** + * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到 + * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf + * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点 + * @method getCommonAncestor + * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点 + * @return { Node } 当前range对象内所有节点的公共祖先节点 + * @see UE.dom.Range:getCommonAncestor() + * @example + * ```html + * + * + * + * xxxxxxxxx[xxx]xxxxxxxx + * + * + * + * + * ``` + */ + + /** + * 获取当前选区所包含的所有节点的公共祖先节点, 可以根据给定的参数 includeSelf 决定获取到 + * 的公共祖先节点是否可以是当前选区的startContainer或endContainer节点, 如果 includeSelf + * 的取值为true, 则返回的节点可以是自身的容器节点, 否则, 则不能是容器节点; 同时可以根据 + * ignoreTextNode 参数的取值决定是否忽略类型为文本节点的祖先节点。 + * @method getCommonAncestor + * @param { Boolean } includeSelf 是否允许获取到的公共祖先节点是当前range对象的容器节点 + * @param { Boolean } ignoreTextNode 获取祖先节点的过程中是否忽略类型为文本节点的祖先节点 + * @return { Node } 当前range对象内所有节点的公共祖先节点 + * @see UE.dom.Range:getCommonAncestor() + * @see UE.dom.Range:getCommonAncestor(Boolean) + * @example + * ```html + * + * + * + * xxxxxxxx[x]xxxxxxxxxxx + * + * + * + * + * ``` + */ + getCommonAncestor: function (includeSelf, ignoreTextNode) { + var me = this, + start = me.startContainer, + end = me.endContainer; + if (start === end) { + if (includeSelf && selectOneNode(this)) { + start = start.childNodes[me.startOffset]; + if (start.nodeType == 1) return start; + } + //只有在上来就相等的情况下才会出现是文本的情况 + return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start; + } + return domUtils.getCommonAncestor(start, end); + }, + + /** + * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上 + * @method trimBoundary + * @remind 该操作有可能会引起文本节点被切开 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * //选区示例 + * xxx[xxxxx]xxx + * + * + * ``` + */ + + /** + * 调整当前Range的开始和结束边界容器,如果是容器节点是文本节点,就调整到包含该文本节点的父节点上, + * 可以根据 ignoreEnd 参数的值决定是否调整对结束边界的调整 + * @method trimBoundary + * @param { Boolean } ignoreEnd 是否忽略对结束边界的调整 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * //选区示例 + * xxx[xxxxx]xxx + * + * + * ``` + */ + trimBoundary: function (ignoreEnd) { + this.txtToElmBoundary(); + var start = this.startContainer, + offset = this.startOffset, + collapsed = this.collapsed, + end = this.endContainer; + if (start.nodeType == 3) { + if (offset == 0) { + this.setStartBefore(start); + } else { + if (offset >= start.nodeValue.length) { + this.setStartAfter(start); + } else { + var textNode = domUtils.split(start, offset); + //跟新结束边界 + if (start === end) { + this.setEnd(textNode, this.endOffset - offset); + } else if (start.parentNode === end) { + this.endOffset += 1; + } + this.setStartBefore(textNode); + } + } + if (collapsed) { + return this.collapse(true); + } + } + if (!ignoreEnd) { + offset = this.endOffset; + end = this.endContainer; + if (end.nodeType == 3) { + if (offset == 0) { + this.setEndBefore(end); + } else { + offset < end.nodeValue.length && domUtils.split(end, offset); + this.setEndAfter(end); + } + } + } + return this; + }, + + /** + * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则什么也不做 + * @method txtToElmBoundary + * @remind 该操作不会修改dom节点 + * @return { UE.dom.Range } 当前range对象 + */ + + /** + * 如果选区在文本的边界上,就扩展选区到文本的父节点上, 如果当前选区是闭合的, 则根据参数项 + * ignoreCollapsed 的值决定是否执行该调整 + * @method txtToElmBoundary + * @param { Boolean } ignoreCollapsed 是否忽略选区的闭合状态, 如果该参数取值为true, 则 + * 不论选区是否闭合, 都会执行该操作, 反之, 则不会对闭合的选区执行该操作 + * @return { UE.dom.Range } 当前range对象 + */ + txtToElmBoundary: function (ignoreCollapsed) { + function adjust(r, c) { + var container = r[c + "Container"], + offset = r[c + "Offset"]; + if (container.nodeType == 3) { + if (!offset) { + r[ + "set" + + c.replace(/(\w)/, function (a) { + return a.toUpperCase(); + }) + + "Before" + ](container); + } else if (offset >= container.nodeValue.length) { + r[ + "set" + + c.replace(/(\w)/, function (a) { + return a.toUpperCase(); + }) + + "After" + ](container); + } + } + } + + if (ignoreCollapsed || !this.collapsed) { + adjust(this, "start"); + adjust(this, "end"); + } + return this; + }, + + /** + * 在当前选区的开始位置前插入节点,新插入的节点会被该range包含 + * @method insertNode + * @param { Node } node 需要插入的节点 + * @remind 插入的节点可以是一个DocumentFragment依次插入多个节点 + * @return { UE.dom.Range } 当前range对象 + */ + insertNode: function (node) { + var first = node, + length = 1; + if (node.nodeType == 11) { + first = node.firstChild; + length = node.childNodes.length; + } + this.trimBoundary(true); + var start = this.startContainer, + offset = this.startOffset; + var nextNode = start.childNodes[offset]; + if (nextNode) { + start.insertBefore(node, nextNode); + } else { + start.appendChild(node); + } + if (first.parentNode === this.endContainer) { + this.endOffset = this.endOffset + length; + } + return this.setStartBefore(first); + }, + + /** + * 闭合选区到当前选区的开始位置, 并且定位光标到闭合后的位置 + * @method setCursor + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:collapse() + */ + + /** + * 闭合选区,可以根据参数toEnd的值控制选区是向前闭合还是向后闭合, 并且定位光标到闭合后的位置。 + * @method setCursor + * @param { Boolean } toEnd 是否向后闭合, 如果为true, 则闭合选区时, 将向结束容器方向闭合, + * 反之,则向开始容器方向闭合 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:collapse(Boolean) + */ + setCursor: function (toEnd, noFillData) { + return this.collapse(!toEnd).select(noFillData); + }, + + /** + * 创建当前range的一个书签,记录下当前range的位置,方便当dom树改变时,还能找回原来的选区位置 + * @method createBookmark + * @param { Boolean } serialize 控制返回的标记位置是对当前位置的引用还是ID,如果该值为true,则 + * 返回标记位置的ID, 反之则返回标记位置节点的引用 + * @return { Object } 返回一个书签记录键值对, 其包含的key有: start => 开始标记的ID或者引用, + * end => 结束标记的ID或引用, id => 当前标记的类型, 如果为true,则表示 + * 返回的记录的类型为ID, 反之则为引用 + */ + createBookmark: function (serialize, same) { + var endNode, + startNode = this.document.createElement("span"); + startNode.style.cssText = "display:none;line-height:0px;"; + startNode.appendChild(this.document.createTextNode("\u200D")); + startNode.id = "_baidu_bookmark_start_" + (same ? "" : guid++); + + if (!this.collapsed) { + endNode = startNode.cloneNode(true); + endNode.id = "_baidu_bookmark_end_" + (same ? "" : guid++); + } + this.insertNode(startNode); + if (endNode) { + this.collapse().insertNode(endNode).setEndBefore(endNode); + } + this.setStartAfter(startNode); + return { + start: serialize ? startNode.id : startNode, + end: endNode ? (serialize ? endNode.id : endNode) : null, + id: serialize + }; + }, + + /** + * 调整当前range的边界到书签位置,并删除该书签对象所标记的位置内的节点 + * @method moveToBookmark + * @param { BookMark } bookmark createBookmark所创建的标签对象 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:createBookmark(Boolean) + */ + moveToBookmark: function (bookmark) { + var start = bookmark.id + ? this.document.getElementById(bookmark.start) + : bookmark.start, + end = bookmark.end && bookmark.id + ? this.document.getElementById(bookmark.end) + : bookmark.end; + this.setStartBefore(start); + domUtils.remove(start); + if (end) { + this.setEndBefore(end); + domUtils.remove(end); + } else { + this.collapse(true); + } + return this; + }, + + /** + * 调整range的边界,使其"放大"到最近的父节点 + * @method enlarge + * @remind 会引起选区的变化 + * @return { UE.dom.Range } 当前range对象 + */ + + /** + * 调整range的边界,使其"放大"到最近的父节点,根据参数 toBlock 的取值, 可以 + * 要求扩大之后的父节点是block节点 + * @method enlarge + * @param { Boolean } toBlock 是否要求扩大之后的父节点必须是block节点 + * @return { UE.dom.Range } 当前range对象 + */ + enlarge: function (toBlock, stopFn) { + var isBody = domUtils.isBody, + pre, + node, + tmp = this.document.createTextNode(""); + if (toBlock) { + node = this.startContainer; + if (node.nodeType == 1) { + if (node.childNodes[this.startOffset]) { + pre = node = node.childNodes[this.startOffset]; + } else { + node.appendChild(tmp); + pre = node = tmp; + } + } else { + pre = node; + } + while (1) { + if (domUtils.isBlockElm(node)) { + node = pre; + while ((pre = node.previousSibling) && !domUtils.isBlockElm(pre)) { + node = pre; + } + this.setStartBefore(node); + break; + } + pre = node; + node = node.parentNode; + } + node = this.endContainer; + if (node.nodeType == 1) { + if ((pre = node.childNodes[this.endOffset])) { + node.insertBefore(tmp, pre); + } else { + node.appendChild(tmp); + } + pre = node = tmp; + } else { + pre = node; + } + while (1) { + if (domUtils.isBlockElm(node)) { + node = pre; + while ((pre = node.nextSibling) && !domUtils.isBlockElm(pre)) { + node = pre; + } + this.setEndAfter(node); + break; + } + pre = node; + node = node.parentNode; + } + if (tmp.parentNode === this.endContainer) { + this.endOffset--; + } + domUtils.remove(tmp); + } + + // 扩展边界到最大 + if (!this.collapsed) { + while (this.startOffset == 0) { + if (stopFn && stopFn(this.startContainer)) { + break; + } + if (isBody(this.startContainer)) { + break; + } + this.setStartBefore(this.startContainer); + } + while ( + this.endOffset == + (this.endContainer.nodeType == 1 + ? this.endContainer.childNodes.length + : this.endContainer.nodeValue.length) + ) { + if (stopFn && stopFn(this.endContainer)) { + break; + } + if (isBody(this.endContainer)) { + break; + } + this.setEndAfter(this.endContainer); + } + } + return this; + }, + enlargeToBlockElm: function (ignoreEnd) { + while (!domUtils.isBlockElm(this.startContainer)) { + this.setStartBefore(this.startContainer); + } + if (!ignoreEnd) { + while (!domUtils.isBlockElm(this.endContainer)) { + this.setEndAfter(this.endContainer); + } + } + return this; + }, + /** + * 调整Range的边界,使其"缩小"到最合适的位置 + * @method adjustmentBoundary + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:shrinkBoundary() + */ + adjustmentBoundary: function () { + if (!this.collapsed) { + while ( + !domUtils.isBody(this.startContainer) && + this.startOffset == + this.startContainer[ + this.startContainer.nodeType == 3 ? "nodeValue" : "childNodes" + ].length && + this.startContainer[ + this.startContainer.nodeType == 3 ? "nodeValue" : "childNodes" + ].length + ) { + this.setStartAfter(this.startContainer); + } + while ( + !domUtils.isBody(this.endContainer) && + !this.endOffset && + this.endContainer[ + this.endContainer.nodeType == 3 ? "nodeValue" : "childNodes" + ].length + ) { + this.setEndBefore(this.endContainer); + } + } + return this; + }, + + /** + * 给range选区中的内容添加给定的inline标签 + * @method applyInlineStyle + * @param { String } tagName 需要添加的标签名 + * @example + * ```html + *

xxxx[xxxx]x

==> range.applyInlineStyle("strong") ==>

xxxx[xxxx]x

+ * ``` + */ + + /** + * 给range选区中的内容添加给定的inline标签, 并且为标签附加上一些初始化属性。 + * @method applyInlineStyle + * @param { String } tagName 需要添加的标签名 + * @param { Object } attrs 跟随新添加的标签的属性 + * @return { UE.dom.Range } 当前选区 + * @example + * ```html + *

xxxx[xxxx]x

+ * + * ==> + * + * + * range.applyInlineStyle("strong",{"style":"font-size:12px"}) + * + * ==> + * + *

xxxx[xxxx]x

+ * ``` + */ + applyInlineStyle: function (tagName, attrs, list) { + if (this.collapsed) return this; + this.trimBoundary() + .enlarge(false, function (node) { + return node.nodeType == 1 && domUtils.isBlockElm(node); + }) + .adjustmentBoundary(); + var bookmark = this.createBookmark(), + end = bookmark.end, + filterFn = function (node) { + return node.nodeType == 1 + ? node.tagName.toLowerCase() != "br" + : !domUtils.isWhitespace(node); + }, + current = domUtils.getNextDomNode(bookmark.start, false, filterFn), + node, + pre, + range = this.cloneRange(); + while ( + current && + domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING + ) { + if (current.nodeType == 3 || dtd[tagName][current.tagName]) { + range.setStartBefore(current); + node = current; + while ( + node && + (node.nodeType == 3 || dtd[tagName][node.tagName]) && + node !== end + ) { + pre = node; + node = domUtils.getNextDomNode( + node, + node.nodeType == 1, + null, + function (parent) { + return dtd[tagName][parent.tagName]; + } + ); + } + var frag = range.setEndAfter(pre).extractContents(), + elm; + if (list && list.length > 0) { + var level, top; + top = level = list[0].cloneNode(false); + for (var i = 1, ci; (ci = list[i++]);) { + level.appendChild(ci.cloneNode(false)); + level = level.firstChild; + } + elm = level; + } else { + elm = range.document.createElement(tagName); + } + if (attrs) { + domUtils.setAttributes(elm, attrs); + } + elm.appendChild(frag); + //针对嵌套span的全局样式指定,做容错处理 + if (elm.tagName == "SPAN" && attrs && attrs.style) { + utils.each(elm.getElementsByTagName("span"), function (s) { + s.style.cssText = s.style.cssText + ";" + attrs.style; + }); + } + range.insertNode(list ? top : elm); + //处理下滑线在a上的情况 + var aNode; + if ( + tagName == "span" && + attrs.style && + /text\-decoration/.test(attrs.style) && + (aNode = domUtils.findParentByTagName(elm, "a", true)) + ) { + domUtils.setAttributes(aNode, attrs); + domUtils.remove(elm, true); + elm = aNode; + } else { + domUtils.mergeSibling(elm); + domUtils.clearEmptySibling(elm); + } + //去除子节点相同的 + domUtils.mergeChild(elm, attrs); + current = domUtils.getNextDomNode(elm, false, filterFn); + domUtils.mergeToParent(elm); + if (node === end) { + break; + } + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return this.moveToBookmark(bookmark); + }, + + /** + * 移除当前选区内指定的inline标签,但保留其中的内容 + * @method removeInlineStyle + * @param { String } tagName 需要移除的标签名 + * @return { UE.dom.Range } 当前的range对象 + * @example + * ```html + * xx[xxxxyyyzz]z => range.removeInlineStyle(["em"]) => xx[xxxxyyyzz]z + * ``` + */ + + /** + * 移除当前选区内指定的一组inline标签,但保留其中的内容 + * @method removeInlineStyle + * @param { Array } tagNameArr 需要移除的标签名的数组 + * @return { UE.dom.Range } 当前的range对象 + * @see UE.dom.Range:removeInlineStyle(String) + */ + removeInlineStyle: function (tagNames) { + if (this.collapsed) return this; + tagNames = utils.isArray(tagNames) ? tagNames : [tagNames]; + this.shrinkBoundary().adjustmentBoundary(); + var start = this.startContainer, + end = this.endContainer; + while (1) { + if (start.nodeType == 1) { + if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) { + break; + } + if (start.tagName.toLowerCase() == "body") { + start = null; + break; + } + } + start = start.parentNode; + } + while (1) { + if (end.nodeType == 1) { + if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) { + break; + } + if (end.tagName.toLowerCase() == "body") { + end = null; + break; + } + } + end = end.parentNode; + } + var bookmark = this.createBookmark(), + frag, + tmpRange; + if (start) { + tmpRange = this.cloneRange() + .setEndBefore(bookmark.start) + .setStartBefore(start); + frag = tmpRange.extractContents(); + tmpRange.insertNode(frag); + domUtils.clearEmptySibling(start, true); + start.parentNode.insertBefore(bookmark.start, start); + } + if (end) { + tmpRange = this.cloneRange() + .setStartAfter(bookmark.end) + .setEndAfter(end); + frag = tmpRange.extractContents(); + tmpRange.insertNode(frag); + domUtils.clearEmptySibling(end, false, true); + end.parentNode.insertBefore(bookmark.end, end.nextSibling); + } + var current = domUtils.getNextDomNode(bookmark.start, false, function ( + node + ) { + return node.nodeType == 1; + }), + next; + while (current && current !== bookmark.end) { + next = domUtils.getNextDomNode(current, true, function (node) { + return node.nodeType == 1; + }); + if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) { + domUtils.remove(current, true); + } + current = next; + } + return this.moveToBookmark(bookmark); + }, + + /** + * 获取当前选中的自闭合的节点 + * @method getClosedNode + * @return { Node | NULL } 如果当前选中的是自闭合节点, 则返回该节点, 否则返回NULL + */ + getClosedNode: function () { + var node; + if (!this.collapsed) { + var range = this.cloneRange().adjustmentBoundary().shrinkBoundary(); + if (selectOneNode(range)) { + var child = range.startContainer.childNodes[range.startOffset]; + if ( + child && + child.nodeType === 1 && + (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName]) + ) { + node = child; + } + } + } + return node; + }, + + /** + * 在页面上高亮range所表示的选区 + * @method select + * @return { UE.dom.Range } 返回当前Range对象 + */ + //这里不区分ie9以上,trace:3824 + select: browser.ie + ? function (noFillData, textRange) { + var nativeRange; + if (!this.collapsed) this.shrinkBoundary(); + var node = this.getClosedNode(); + if (node && !textRange) { + try { + nativeRange = this.document.body.createControlRange(); + nativeRange.addElement(node); + nativeRange.select(); + } catch (e) { + } + return this; + } + var bookmark = this.createBookmark(), + start = bookmark.start, + end; + nativeRange = this.document.body.createTextRange(); + nativeRange.moveToElementText(start); + nativeRange.moveStart("character", 1); + if (!this.collapsed) { + var nativeRangeEnd = this.document.body.createTextRange(); + end = bookmark.end; + nativeRangeEnd.moveToElementText(end); + nativeRange.setEndPoint("EndToEnd", nativeRangeEnd); + } else { + if (!noFillData && this.startContainer.nodeType != 3) { + //使用|x固定住光标 + var tmpText = this.document.createTextNode(fillChar), + tmp = this.document.createElement("span"); + tmp.appendChild(this.document.createTextNode(fillChar)); + start.parentNode.insertBefore(tmp, start); + start.parentNode.insertBefore(tmpText, start); + //当点b,i,u时,不能清除i上边的b + removeFillData(this.document, tmpText); + fillData = tmpText; + mergeSibling(tmp, "previousSibling"); + mergeSibling(start, "nextSibling"); + nativeRange.moveStart("character", -1); + nativeRange.collapse(true); + } + } + this.moveToBookmark(bookmark); + tmp && domUtils.remove(tmp); + //IE在隐藏状态下不支持range操作,catch一下 + try { + nativeRange.select(); + } catch (e) { + } + return this; + } + : function (notInsertFillData) { + function checkOffset(rng) { + function check(node, offset, dir) { + if (node.nodeType == 3 && node.nodeValue.length < offset) { + rng[dir + "Offset"] = node.nodeValue.length; + } + } + + check(rng.startContainer, rng.startOffset, "start"); + check(rng.endContainer, rng.endOffset, "end"); + } + + var win = domUtils.getWindow(this.document), + sel = win.getSelection(), + txtNode; + //FF下关闭自动长高时滚动条在关闭dialog时会跳 + //ff下如果不body.focus将不能定位闭合光标到编辑器内 + browser.gecko ? this.document.body.focus() : win.focus(); + if (sel) { + sel.removeAllRanges(); + // trace:870 chrome/safari后边是br对于闭合得range不能定位 所以去掉了判断 + // this.startContainer.nodeType != 3 &&! ((child = this.startContainer.childNodes[this.startOffset]) && child.nodeType == 1 && child.tagName == 'BR' + if (this.collapsed && !notInsertFillData) { + // //opear如果没有节点接着,原生的不能够定位,不能在body的第一级插入空白节点 + // if (notInsertFillData && browser.opera && !domUtils.isBody(this.startContainer) && this.startContainer.nodeType == 1) { + // var tmp = this.document.createTextNode(''); + // this.insertNode(tmp).setStart(tmp, 0).collapse(true); + // } + // + //处理光标落在文本节点的情况 + //处理以下的情况 + //|xxxx + //xxxx|xxxx + //xxxx| + var start = this.startContainer, + child = start; + if (start.nodeType == 1) { + child = start.childNodes[this.startOffset]; + } + if ( + !(start.nodeType == 3 && this.startOffset) && + (child + ? !child.previousSibling || + child.previousSibling.nodeType != 3 + : !start.lastChild || start.lastChild.nodeType != 3) + ) { + txtNode = this.document.createTextNode(fillChar); + //跟着前边走 + this.insertNode(txtNode); + removeFillData(this.document, txtNode); + mergeSibling(txtNode, "previousSibling"); + mergeSibling(txtNode, "nextSibling"); + fillData = txtNode; + this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true); + } + } + var nativeRange = this.document.createRange(); + if ( + this.collapsed && + browser.opera && + this.startContainer.nodeType == 1 + ) { + var child = this.startContainer.childNodes[this.startOffset]; + if (!child) { + //往前靠拢 + child = this.startContainer.lastChild; + if (child && domUtils.isBr(child)) { + this.setStartBefore(child).collapse(true); + } + } else { + //向后靠拢 + while (child && domUtils.isBlockElm(child)) { + if (child.nodeType == 1 && child.childNodes[0]) { + child = child.childNodes[0]; + } else { + break; + } + } + child && this.setStartBefore(child).collapse(true); + } + } + //是createAddress最后一位算的不准,现在这里进行微调 + checkOffset(this); + nativeRange.setStart(this.startContainer, this.startOffset); + nativeRange.setEnd(this.endContainer, this.endOffset); + sel.addRange(nativeRange); + } + return this; + }, + + /** + * 滚动到当前range开始的位置 + * @method scrollToView + * @param { Window } win 当前range对象所属的window对象 + * @return { UE.dom.Range } 当前Range对象 + */ + + /** + * 滚动到距离当前range开始位置 offset 的位置处 + * @method scrollToView + * @param { Window } win 当前range对象所属的window对象 + * @param { Number } offset 距离range开始位置处的偏移量, 如果为正数, 则向下偏移, 反之, 则向上偏移 + * @return { UE.dom.Range } 当前Range对象 + */ + scrollToView: function (win, offset) { + win = win ? window : domUtils.getWindow(this.document); + offset = offset || (win.innerHeight - 100); + // console.log('xxx',win, offset); + var me = this, + span = me.document.createElement("span"); + //trace:717 + span.innerHTML = " "; + me.cloneRange().insertNode(span); + domUtils.scrollToView(span, win, offset); + domUtils.remove(span); + return me; + }, + + /** + * 判断当前选区内容是否占位符 + * @private + * @method inFillChar + * @return { Boolean } 如果是占位符返回true,否则返回false + */ + inFillChar: function () { + var start = this.startContainer; + if ( + this.collapsed && + start.nodeType == 3 && + start.nodeValue.replace(new RegExp("^" + domUtils.fillChar), "") + .length + + 1 == + start.nodeValue.length + ) { + return true; + } + return false; + }, + + /** + * 保存 + * @method createAddress + * @private + * @return { Boolean } 返回开始和结束的位置 + * @example + * ```html + * + *

+ * aaaa + * + * + * bbbb + * + * + *

+ * + * + * + * ``` + */ + createAddress: function (ignoreEnd, ignoreTxt) { + var addr = {}, + me = this; + + function getAddress(isStart) { + var node = isStart ? me.startContainer : me.endContainer; + var parents = domUtils.findParents(node, true, function (node) { + return !domUtils.isBody(node); + }), + addrs = []; + for (var i = 0, ci; (ci = parents[i++]);) { + addrs.push(domUtils.getNodeIndex(ci, ignoreTxt)); + } + var firstIndex = 0; + + if (ignoreTxt) { + if (node.nodeType == 3) { + var tmpNode = node.previousSibling; + while (tmpNode && tmpNode.nodeType == 3) { + firstIndex += tmpNode.nodeValue.replace(fillCharReg, "").length; + tmpNode = tmpNode.previousSibling; + } + firstIndex += isStart ? me.startOffset : me.endOffset; // - (fillCharReg.test(node.nodeValue) ? 1 : 0 ) + } else { + node = node.childNodes[isStart ? me.startOffset : me.endOffset]; + if (node) { + firstIndex = domUtils.getNodeIndex(node, ignoreTxt); + } else { + node = isStart ? me.startContainer : me.endContainer; + var first = node.firstChild; + while (first) { + if (domUtils.isFillChar(first)) { + first = first.nextSibling; + continue; + } + firstIndex++; + if (first.nodeType == 3) { + while (first && first.nodeType == 3) { + first = first.nextSibling; + } + } else { + first = first.nextSibling; + } + } + } + } + } else { + firstIndex = isStart + ? domUtils.isFillChar(node) ? 0 : me.startOffset + : me.endOffset; + } + if (firstIndex < 0) { + firstIndex = 0; + } + addrs.push(firstIndex); + return addrs; + } + + addr.startAddress = getAddress(true); + if (!ignoreEnd) { + addr.endAddress = me.collapsed + ? [].concat(addr.startAddress) + : getAddress(); + } + return addr; + }, + + /** + * 保存 + * @method createAddress + * @private + * @return { Boolean } 返回开始和结束的位置 + * @example + * ```html + * + *

+ * aaaa + * + * + * bbbb + * + * + *

+ * + * + * + * ``` + */ + moveToAddress: function (addr, ignoreEnd) { + var me = this; + + function getNode(address, isStart) { + var tmpNode = me.document.body, + parentNode, + offset; + for (var i = 0, ci, l = address.length; i < l; i++) { + ci = address[i]; + parentNode = tmpNode; + tmpNode = tmpNode.childNodes[ci]; + if (!tmpNode) { + offset = ci; + break; + } + } + if (isStart) { + if (tmpNode) { + me.setStartBefore(tmpNode); + } else { + me.setStart(parentNode, offset); + } + } else { + if (tmpNode) { + me.setEndBefore(tmpNode); + } else { + me.setEnd(parentNode, offset); + } + } + } + + getNode(addr.startAddress, true); + !ignoreEnd && addr.endAddress && getNode(addr.endAddress); + return me; + }, + + /** + * 判断给定的Range对象是否和当前Range对象表示的是同一个选区 + * @method equals + * @param { UE.dom.Range } 需要判断的Range对象 + * @return { Boolean } 如果给定的Range对象与当前Range对象表示的是同一个选区, 则返回true, 否则返回false + */ + equals: function (rng) { + for (var p in this) { + if (this.hasOwnProperty(p)) { + if (this[p] !== rng[p]) return false; + } + } + return true; + }, + + /** + * 遍历range内的节点。每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 + * 作为其参数。 + * @method traversal + * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 + * @return { UE.dom.Range } 当前range对象 + * @example + * ```html + * + * + * + * + * + * + * + * + * + * + * ``` + */ + + /** + * 遍历range内的节点。 + * 每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 + * 作为其参数。 + * 可以通过参数项 filterFn 来指定一个过滤器, 只有符合该过滤器过滤规则的节点才会触 + * 发doFn函数的执行 + * @method traversal + * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 + * @param { Function } filterFn 过滤器, 该函数接受当前遍历的节点作为参数, 如果该节点满足过滤 + * 规则, 请返回true, 该节点会触发doFn, 否则, 请返回false, 则该节点不 + * 会触发doFn。 + * @return { UE.dom.Range } 当前range对象 + * @see UE.dom.Range:traversal(Function) + * @example + * ```html + * + * + * + * + * + * + * + * + * + * + * ``` + */ + traversal: function (doFn, filterFn) { + if (this.collapsed) return this; + var bookmark = this.createBookmark(), + end = bookmark.end, + current = domUtils.getNextDomNode(bookmark.start, false, filterFn); + while ( + current && + current !== end && + domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING + ) { + var tmpNode = domUtils.getNextDomNode(current, false, filterFn); + doFn(current); + current = tmpNode; + } + return this.moveToBookmark(bookmark); + } + }; + })(); // core/Selection.js -/** - * 选集 - * @file - * @module UE.dom - * @class Selection - * @since 1.2.6.1 - */ - -/** - * 选区集合 - * @unfile - * @module UE.dom - * @class Selection - */ -(function() { - function getBoundaryInformation(range, start) { - var getIndex = domUtils.getNodeIndex; - range = range.duplicate(); - range.collapse(start); - var parent = range.parentElement(); - //如果节点里没有子节点,直接退出 - if (!parent.hasChildNodes()) { - return { container: parent, offset: 0 }; - } - var siblings = parent.children, - child, - testRange = range.duplicate(), - startIndex = 0, - endIndex = siblings.length - 1, - index = -1, - distance; - while (startIndex <= endIndex) { - index = Math.floor((startIndex + endIndex) / 2); - child = siblings[index]; - testRange.moveToElementText(child); - var position = testRange.compareEndPoints("StartToStart", range); - if (position > 0) { - endIndex = index - 1; - } else if (position < 0) { - startIndex = index + 1; - } else { - //trace:1043 - return { container: parent, offset: getIndex(child) }; - } - } - if (index == -1) { - testRange.moveToElementText(parent); - testRange.setEndPoint("StartToStart", range); - distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length; - siblings = parent.childNodes; - if (!distance) { - child = siblings[siblings.length - 1]; - return { container: child, offset: child.nodeValue.length }; - } - - var i = siblings.length; - while (distance > 0) { - distance -= siblings[--i].nodeValue.length; - } - return { container: siblings[i], offset: -distance }; - } - testRange.collapse(position > 0); - testRange.setEndPoint(position > 0 ? "StartToStart" : "EndToStart", range); - distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length; - if (!distance) { - return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] - ? { - container: parent, - offset: getIndex(child) + (position > 0 ? 0 : 1) - } - : { - container: child, - offset: position > 0 ? 0 : child.childNodes.length - }; - } - while (distance > 0) { - try { - var pre = child; - child = child[position > 0 ? "previousSibling" : "nextSibling"]; - distance -= child.nodeValue.length; - } catch (e) { - return { container: parent, offset: getIndex(pre) }; - } - } - return { - container: child, - offset: position > 0 ? -distance : child.nodeValue.length + distance - }; - } - - /** - * 将ieRange转换为Range对象 - * @param {Range} ieRange ieRange对象 - * @param {Range} range Range对象 - * @return {Range} range 返回转换后的Range对象 + /** + * 选集 + * @file + * @module UE.dom + * @class Selection + * @since 1.2.6.1 */ - function transformIERangeToRange(ieRange, range) { - if (ieRange.item) { - range.selectNode(ieRange.item(0)); - } else { - var bi = getBoundaryInformation(ieRange, true); - range.setStart(bi.container, bi.offset); - if (ieRange.compareEndPoints("StartToEnd", ieRange) != 0) { - bi = getBoundaryInformation(ieRange, false); - range.setEnd(bi.container, bi.offset); - } - } - return range; - } - - /** - * 获得ieRange - * @param {Selection} sel Selection对象 - * @return {ieRange} 得到ieRange - */ - function _getIERange(sel) { - var ieRange; - //ie下有可能报错 - try { - ieRange = sel.getNative().createRange(); - } catch (e) { - return null; - } - var el = ieRange.item ? ieRange.item(0) : ieRange.parentElement(); - if ((el.ownerDocument || el) === sel.document) { - return ieRange; - } - return null; - } - - var Selection = (dom.Selection = function(doc) { - var me = this, - iframe; - me.document = doc; - if (browser.ie9below) { - iframe = domUtils.getWindow(doc).frameElement; - domUtils.on(iframe, "beforedeactivate", function() { - me._bakIERange = me.getIERange(); - }); - domUtils.on(iframe, "activate", function() { - try { - if (!_getIERange(me) && me._bakIERange) { - me._bakIERange.select(); - } - } catch (ex) {} - me._bakIERange = null; - }); - } - iframe = doc = null; - }); - - Selection.prototype = { - rangeInBody: function(rng, txtRange) { - var node = browser.ie9below || txtRange - ? rng.item ? rng.item() : rng.parentElement() - : rng.startContainer; - - return node === this.document.body || domUtils.inDoc(node, this.document); - }, /** - * 获取原生seleciton对象 - * @method getNative - * @return { Object } 获得selection对象 - * @example - * ```javascript - * editor.selection.getNative(); - * ``` + * 选区集合 + * @unfile + * @module UE.dom + * @class Selection + */ + (function () { + function getBoundaryInformation(range, start) { + var getIndex = domUtils.getNodeIndex; + range = range.duplicate(); + range.collapse(start); + var parent = range.parentElement(); + //如果节点里没有子节点,直接退出 + if (!parent.hasChildNodes()) { + return {container: parent, offset: 0}; + } + var siblings = parent.children, + child, + testRange = range.duplicate(), + startIndex = 0, + endIndex = siblings.length - 1, + index = -1, + distance; + while (startIndex <= endIndex) { + index = Math.floor((startIndex + endIndex) / 2); + child = siblings[index]; + testRange.moveToElementText(child); + var position = testRange.compareEndPoints("StartToStart", range); + if (position > 0) { + endIndex = index - 1; + } else if (position < 0) { + startIndex = index + 1; + } else { + //trace:1043 + return {container: parent, offset: getIndex(child)}; + } + } + if (index == -1) { + testRange.moveToElementText(parent); + testRange.setEndPoint("StartToStart", range); + distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length; + siblings = parent.childNodes; + if (!distance) { + child = siblings[siblings.length - 1]; + return {container: child, offset: child.nodeValue.length}; + } + + var i = siblings.length; + while (distance > 0) { + distance -= siblings[--i].nodeValue.length; + } + return {container: siblings[i], offset: -distance}; + } + testRange.collapse(position > 0); + testRange.setEndPoint(position > 0 ? "StartToStart" : "EndToStart", range); + distance = testRange.text.replace(/(\r\n|\r)/g, "\n").length; + if (!distance) { + return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] + ? { + container: parent, + offset: getIndex(child) + (position > 0 ? 0 : 1) + } + : { + container: child, + offset: position > 0 ? 0 : child.childNodes.length + }; + } + while (distance > 0) { + try { + var pre = child; + child = child[position > 0 ? "previousSibling" : "nextSibling"]; + distance -= child.nodeValue.length; + } catch (e) { + return {container: parent, offset: getIndex(pre)}; + } + } + return { + container: child, + offset: position > 0 ? -distance : child.nodeValue.length + distance + }; + } + + /** + * 将ieRange转换为Range对象 + * @param {Range} ieRange ieRange对象 + * @param {Range} range Range对象 + * @return {Range} range 返回转换后的Range对象 */ - getNative: function() { - var doc = this.document; - try { - return !doc - ? null - : browser.ie9below - ? doc.selection - : domUtils.getWindow(doc).getSelection(); - } catch (e) { - return null; - } - }, + function transformIERangeToRange(ieRange, range) { + if (ieRange.item) { + range.selectNode(ieRange.item(0)); + } else { + var bi = getBoundaryInformation(ieRange, true); + range.setStart(bi.container, bi.offset); + if (ieRange.compareEndPoints("StartToEnd", ieRange) != 0) { + bi = getBoundaryInformation(ieRange, false); + range.setEnd(bi.container, bi.offset); + } + } + return range; + } - /** + /** * 获得ieRange - * @method getIERange - * @return { Object } 返回ie原生的Range - * @example - * ```javascript - * editor.selection.getIERange(); - * ``` + * @param {Selection} sel Selection对象 + * @return {ieRange} 得到ieRange */ - getIERange: function() { - var ieRange = _getIERange(this); - if (!ieRange) { - if (this._bakIERange) { - return this._bakIERange; + function _getIERange(sel) { + var ieRange; + //ie下有可能报错 + try { + ieRange = sel.getNative().createRange(); + } catch (e) { + return null; + } + var el = ieRange.item ? ieRange.item(0) : ieRange.parentElement(); + if ((el.ownerDocument || el) === sel.document) { + return ieRange; + } + return null; } - } - return ieRange; - }, - /** - * 缓存当前选区的range和选区的开始节点 - * @method cache - */ - cache: function() { - this.clear(); - this._cachedRange = this.getRange(); - this._cachedStartElement = this.getStart(); - this._cachedStartElementPath = this.getStartElementPath(); - }, + var Selection = (dom.Selection = function (doc) { + var me = this, + iframe; + me.document = doc; + if (browser.ie9below) { + iframe = domUtils.getWindow(doc).frameElement; + domUtils.on(iframe, "beforedeactivate", function () { + me._bakIERange = me.getIERange(); + }); + domUtils.on(iframe, "activate", function () { + try { + if (!_getIERange(me) && me._bakIERange) { + me._bakIERange.select(); + } + } catch (ex) { + } + me._bakIERange = null; + }); + } + iframe = doc = null; + }); - /** - * 获取选区开始位置的父节点到body - * @method getStartElementPath - * @return { Array } 返回父节点集合 - * @example - * ```javascript - * editor.selection.getStartElementPath(); - * ``` - */ - getStartElementPath: function() { - if (this._cachedStartElementPath) { - return this._cachedStartElementPath; - } - var start = this.getStart(); - if (start) { - return domUtils.findParents(start, true, null, true); - } - return []; - }, + Selection.prototype = { + rangeInBody: function (rng, txtRange) { + var node = browser.ie9below || txtRange + ? rng.item ? rng.item() : rng.parentElement() + : rng.startContainer; - /** - * 清空缓存 - * @method clear - */ - clear: function() { - this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null; - }, + return node === this.document.body || domUtils.inDoc(node, this.document); + }, - /** - * 编辑器是否得到了选区 - * @method isFocus - */ - isFocus: function() { - try { - if (browser.ie9below) { - var nativeRange = _getIERange(this); - return !!(nativeRange && this.rangeInBody(nativeRange)); - } else { - return !!this.getNative().rangeCount; - } - } catch (e) { - return false; - } - }, + /** + * 获取原生seleciton对象 + * @method getNative + * @return { Object } 获得selection对象 + * @example + * ```javascript + * editor.selection.getNative(); + * ``` + */ + getNative: function () { + var doc = this.document; + try { + return !doc + ? null + : browser.ie9below + ? doc.selection + : domUtils.getWindow(doc).getSelection(); + } catch (e) { + return null; + } + }, - /** - * 获取选区对应的Range - * @method getRange - * @return { Object } 得到Range对象 - * @example - * ```javascript - * editor.selection.getRange(); - * ``` - */ - getRange: function() { - var me = this; - function optimze(range) { - var child = me.document.body.firstChild, - collapsed = range.collapsed; - while (child && child.firstChild) { - range.setStart(child, 0); - child = child.firstChild; - } - if (!range.startContainer) { - range.setStart(me.document.body, 0); - } - if (collapsed) { - range.collapse(true); - } - } + /** + * 获得ieRange + * @method getIERange + * @return { Object } 返回ie原生的Range + * @example + * ```javascript + * editor.selection.getIERange(); + * ``` + */ + getIERange: function () { + var ieRange = _getIERange(this); + if (!ieRange) { + if (this._bakIERange) { + return this._bakIERange; + } + } + return ieRange; + }, - if (me._cachedRange != null) { - return this._cachedRange; - } - var range = new baidu.editor.dom.Range(me.document); + /** + * 缓存当前选区的range和选区的开始节点 + * @method cache + */ + cache: function () { + this.clear(); + this._cachedRange = this.getRange(); + this._cachedStartElement = this.getStart(); + this._cachedStartElementPath = this.getStartElementPath(); + }, - if (browser.ie9below) { - var nativeRange = me.getIERange(); - if (nativeRange) { - //备份的_bakIERange可能已经实效了,dom树发生了变化比如从源码模式切回来,所以try一下,实效就放到body开始位置 - try { - transformIERangeToRange(nativeRange, range); - } catch (e) { - optimze(range); - } - } else { - optimze(range); - } - } else { - var sel = me.getNative(); - if (sel && sel.rangeCount) { - var firstRange = sel.getRangeAt(0); - var lastRange = sel.getRangeAt(sel.rangeCount - 1); - range - .setStart(firstRange.startContainer, firstRange.startOffset) - .setEnd(lastRange.endContainer, lastRange.endOffset); - if ( - range.collapsed && - domUtils.isBody(range.startContainer) && - !range.startOffset - ) { - optimze(range); - } - } else { - //trace:1734 有可能已经不在dom树上了,标识的节点 - if ( - this._bakRange && - domUtils.inDoc(this._bakRange.startContainer, this.document) - ) { - return this._bakRange; - } - optimze(range); - } - } - return (this._bakRange = range); - }, + /** + * 获取选区开始位置的父节点到body + * @method getStartElementPath + * @return { Array } 返回父节点集合 + * @example + * ```javascript + * editor.selection.getStartElementPath(); + * ``` + */ + getStartElementPath: function () { + if (this._cachedStartElementPath) { + return this._cachedStartElementPath; + } + var start = this.getStart(); + if (start) { + return domUtils.findParents(start, true, null, true); + } + return []; + }, - /** - * 获取开始元素,用于状态反射 - * @method getStart - * @return { Element } 获得开始元素 - * @example - * ```javascript - * editor.selection.getStart(); - * ``` - */ - getStart: function() { - if (this._cachedStartElement) { - return this._cachedStartElement; - } - var range = browser.ie9below ? this.getIERange() : this.getRange(), - tmpRange, - start, - tmp, - parent; - if (browser.ie9below) { - if (!range) { - //todo 给第一个值可能会有问题 - return this.document.body.firstChild; - } - //control元素 - if (range.item) { - return range.item(0); - } - tmpRange = range.duplicate(); - //修正ie下x[xx] 闭合后 x|xx - tmpRange.text.length > 0 && tmpRange.moveStart("character", 1); - tmpRange.collapse(1); - start = tmpRange.parentElement(); - parent = tmp = range.parentElement(); - while ((tmp = tmp.parentNode)) { - if (tmp == start) { - start = parent; - break; - } - } - } else { - range.shrinkBoundary(); - start = range.startContainer; - if (start.nodeType == 1 && start.hasChildNodes()) { - start = - start.childNodes[ - Math.min(start.childNodes.length - 1, range.startOffset) - ]; - } - if (start.nodeType == 3) { - return start.parentNode; - } - } - return start; - }, + /** + * 清空缓存 + * @method clear + */ + clear: function () { + this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null; + }, - /** - * 得到选区中的文本 - * @method getText - * @return { String } 选区中包含的文本 - * @example - * ```javascript - * editor.selection.getText(); - * ``` - */ - getText: function() { - var nativeSel, nativeRange; - if (this.isFocus() && (nativeSel = this.getNative())) { - nativeRange = browser.ie9below - ? nativeSel.createRange() - : nativeSel.getRangeAt(0); - return browser.ie9below ? nativeRange.text : nativeRange.toString(); - } - return ""; - }, + /** + * 编辑器是否得到了选区 + * @method isFocus + */ + isFocus: function () { + try { + if (browser.ie9below) { + var nativeRange = _getIERange(this); + return !!(nativeRange && this.rangeInBody(nativeRange)); + } else { + return !!this.getNative().rangeCount; + } + } catch (e) { + return false; + } + }, - /** - * 清除选区 - * @method clearRange - * @example - * ```javascript - * editor.selection.clearRange(); - * ``` - */ - clearRange: function() { - this.getNative()[browser.ie9below ? "empty" : "removeAllRanges"](); - } - }; -})(); + /** + * 获取选区对应的Range + * @method getRange + * @return { Object } 得到Range对象 + * @example + * ```javascript + * editor.selection.getRange(); + * ``` + */ + getRange: function () { + var me = this; + + function optimze(range) { + var child = me.document.body.firstChild, + collapsed = range.collapsed; + while (child && child.firstChild) { + range.setStart(child, 0); + child = child.firstChild; + } + if (!range.startContainer) { + range.setStart(me.document.body, 0); + } + if (collapsed) { + range.collapse(true); + } + } + + if (me._cachedRange != null) { + return this._cachedRange; + } + var range = new baidu.editor.dom.Range(me.document); + + if (browser.ie9below) { + var nativeRange = me.getIERange(); + if (nativeRange) { + //备份的_bakIERange可能已经实效了,dom树发生了变化比如从源码模式切回来,所以try一下,实效就放到body开始位置 + try { + transformIERangeToRange(nativeRange, range); + } catch (e) { + optimze(range); + } + } else { + optimze(range); + } + } else { + var sel = me.getNative(); + if (sel && sel.rangeCount) { + var firstRange = sel.getRangeAt(0); + var lastRange = sel.getRangeAt(sel.rangeCount - 1); + range + .setStart(firstRange.startContainer, firstRange.startOffset) + .setEnd(lastRange.endContainer, lastRange.endOffset); + if ( + range.collapsed && + domUtils.isBody(range.startContainer) && + !range.startOffset + ) { + optimze(range); + } + } else { + //trace:1734 有可能已经不在dom树上了,标识的节点 + if ( + this._bakRange && + domUtils.inDoc(this._bakRange.startContainer, this.document) + ) { + return this._bakRange; + } + optimze(range); + } + } + return (this._bakRange = range); + }, + + /** + * 获取开始元素,用于状态反射 + * @method getStart + * @return { Element } 获得开始元素 + * @example + * ```javascript + * editor.selection.getStart(); + * ``` + */ + getStart: function () { + if (this._cachedStartElement) { + return this._cachedStartElement; + } + var range = browser.ie9below ? this.getIERange() : this.getRange(), + tmpRange, + start, + tmp, + parent; + if (browser.ie9below) { + if (!range) { + //todo 给第一个值可能会有问题 + return this.document.body.firstChild; + } + //control元素 + if (range.item) { + return range.item(0); + } + tmpRange = range.duplicate(); + //修正ie下x[xx] 闭合后 x|xx + tmpRange.text.length > 0 && tmpRange.moveStart("character", 1); + tmpRange.collapse(1); + start = tmpRange.parentElement(); + parent = tmp = range.parentElement(); + while ((tmp = tmp.parentNode)) { + if (tmp == start) { + start = parent; + break; + } + } + } else { + range.shrinkBoundary(); + start = range.startContainer; + if (start.nodeType == 1 && start.hasChildNodes()) { + start = + start.childNodes[ + Math.min(start.childNodes.length - 1, range.startOffset) + ]; + } + if (start.nodeType == 3) { + return start.parentNode; + } + } + return start; + }, + + /** + * 得到选区中的文本 + * @method getText + * @return { String } 选区中包含的文本 + * @example + * ```javascript + * editor.selection.getText(); + * ``` + */ + getText: function () { + var nativeSel, nativeRange; + if (this.isFocus() && (nativeSel = this.getNative())) { + nativeRange = browser.ie9below + ? nativeSel.createRange() + : nativeSel.getRangeAt(0); + return browser.ie9below ? nativeRange.text : nativeRange.toString(); + } + return ""; + }, + + /** + * 清除选区 + * @method clearRange + * @example + * ```javascript + * editor.selection.clearRange(); + * ``` + */ + clearRange: function () { + this.getNative()[browser.ie9below ? "empty" : "removeAllRanges"](); + } + }; + })(); // core/Editor.js -/** - * 编辑器主类,包含编辑器提供的大部分公用接口 - * @file - * @module UE - * @class Editor - * @since 1.2.6.1 - */ - -/** - * UEditor公用空间,UEditor所有的功能都挂载在该空间下 - * @unfile - * @module UE - */ - -/** - * UEditor的核心类,为用户提供与编辑器交互的接口。 - * @unfile - * @module UE - * @class Editor - */ - -(function() { - var uid = 0, - _selectionChangeTimer; - - /** - * 获取编辑器的html内容,赋值到编辑器所在表单的textarea文本域里面 - * @private - * @method setValue - * @param { UE.Editor } editor 编辑器事例 - */ - function setValue(form, editor) { - var textarea; - if (editor.options.textarea) { - if (utils.isString(editor.options.textarea)) { - for ( - var i = 0, ti, tis = domUtils.getElementsByTagName(form, "textarea"); - (ti = tis[i++]); - - ) { - if (ti.id == "ueditor_textarea_" + editor.options.textarea) { - textarea = ti; - break; - } - } - } else { - textarea = editor.textarea; - } - } - if (!textarea) { - form.appendChild( - (textarea = domUtils.createElement(document, "textarea", { - name: editor.options.textarea, - id: "ueditor_textarea_" + editor.options.textarea, - style: "display:none" - })) - ); - //不要产生多个textarea - editor.textarea = textarea; - } - !textarea.getAttribute("name") && - textarea.setAttribute("name", editor.options.textarea); - textarea.value = editor.hasContents() - ? editor.options.allHtmlEnabled - ? editor.getAllHtml() - : editor.getContent(null, null, true) - : ""; - } - function loadPlugins(me) { - //初始化插件 - for (var pi in UE.plugins) { - UE.plugins[pi].call(me); - } - } - function checkCurLang(I18N) { - for (var lang in I18N) { - return lang; - } - } - - function langReadied(me) { - me.langIsReady = true; - - me.fireEvent("langReady"); - } - - /** - * 编辑器准备就绪后会触发该事件 - * @module UE - * @class Editor - * @event ready - * @remind render方法执行完成之后,会触发该事件 - * @remind - * @example - * ```javascript - * editor.addListener( 'ready', function( editor ) { - * editor.execCommand( 'focus' ); //编辑器家在完成后,让编辑器拿到焦点 - * } ); - * ``` - */ - /** - * 执行destroy方法,会触发该事件 - * @module UE - * @class Editor - * @event destroy - * @see UE.Editor:destroy() - */ - /** - * 执行reset方法,会触发该事件 - * @module UE - * @class Editor - * @event reset - * @see UE.Editor:reset() - */ - /** - * 执行focus方法,会触发该事件 - * @module UE - * @class Editor - * @event focus - * @see UE.Editor:focus(Boolean) - */ - /** - * 语言加载完成会触发该事件 - * @module UE - * @class Editor - * @event langReady - */ - /** - * 运行命令之后会触发该命令 - * @module UE - * @class Editor - * @event beforeExecCommand - */ - /** - * 运行命令之后会触发该命令 - * @module UE - * @class Editor - * @event afterExecCommand - */ - /** - * 运行命令之前会触发该命令 - * @module UE - * @class Editor - * @event firstBeforeExecCommand - */ - /** - * 在getContent方法执行之前会触发该事件 - * @module UE - * @class Editor - * @event beforeGetContent - * @see UE.Editor:getContent() - */ - /** - * 在getContent方法执行之后会触发该事件 - * @module UE - * @class Editor - * @event afterGetContent - * @see UE.Editor:getContent() - */ - /** - * 在getAllHtml方法执行时会触发该事件 - * @module UE - * @class Editor - * @event getAllHtml - * @see UE.Editor:getAllHtml() - */ - /** - * 在setContent方法执行之前会触发该事件 - * @module UE - * @class Editor - * @event beforeSetContent - * @see UE.Editor:setContent(String) - */ - /** - * 在setContent方法执行之后会触发该事件 - * @module UE - * @class Editor - * @event afterSetContent - * @see UE.Editor:setContent(String) - */ - /** - * 每当编辑器内部选区发生改变时,将触发该事件 - * @event selectionchange - * @warning 该事件的触发非常频繁,不建议在该事件的处理过程中做重量级的处理 - * @example - * ```javascript - * editor.addListener( 'selectionchange', function( editor ) { - * console.log('选区发生改变'); - * } - */ - /** - * 在所有selectionchange的监听函数执行之前,会触发该事件 - * @module UE - * @class Editor - * @event beforeSelectionChange - * @see UE.Editor:selectionchange - */ - /** - * 在所有selectionchange的监听函数执行完之后,会触发该事件 - * @module UE - * @class Editor - * @event afterSelectionChange - * @see UE.Editor:selectionchange - */ - /** - * 编辑器内容发生改变时会触发该事件 - * @module UE - * @class Editor - * @event contentChange - */ - - /** - * 以默认参数构建一个编辑器实例 - * @constructor - * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面 - * @example - * ```javascript - * var editor = new UE.Editor(); - * editor.execCommand('blod'); - * ``` - * @see UE.Config - */ - - /** - * 以给定的参数集合创建一个编辑器实例,对于未指定的参数,将应用默认参数。 - * @constructor - * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面 - * @param { Object } setting 创建编辑器的参数 - * @example - * ```javascript - * var editor = new UE.Editor(); - * editor.execCommand('blod'); - * ``` - * @see UE.Config - */ - var Editor = (UE.Editor = function(options) { - var me = this; - me.uid = uid++; - EventBase.call(me); - me.commands = {}; - me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true); - me.shortcutkeys = {}; - me.inputRules = []; - me.outputRules = []; - //设置默认的常用属性 - me.setOpt(Editor.defaultOptions(me)); - - /* 尝试异步加载后台配置 */ - me.loadServerConfig(); - - if (!utils.isEmptyObject(UE.I18N)) { - //修改默认的语言类型 - me.options.lang = checkCurLang(UE.I18N); - UE.plugin.load(me); - langReadied(me); - } else { - utils.loadFile( - document, - { - src: - me.options.langPath + - me.options.lang + - "/" + - me.options.lang + - ".js?20230921", - tag: "script", - type: "text/javascript", - defer: "defer" - }, - function() { - UE.plugin.load(me); - langReadied(me); - } - ); - } - - UE.instants["ueditorInstant" + me.uid] = me; - }); - Editor.prototype = { - registerCommand: function(name, obj) { - this.commands[name] = obj; - }, /** - * 编辑器对外提供的监听ready事件的接口, 通过调用该方法,达到的效果与监听ready事件是一致的 - * @method ready - * @param { Function } fn 编辑器ready之后所执行的回调, 如果在注册事件之前编辑器已经ready,将会 - * 立即触发该回调。 - * @remind 需要等待编辑器加载完成后才能执行的代码,可以使用该方法传入 - * @example - * ```javascript - * editor.ready( function( editor ) { - * editor.setContent('初始化完毕'); - * } ); - * ``` - * @see UE.Editor.event:ready - */ - ready: function(fn) { - var me = this; - if (fn) { - me.isReady ? fn.apply(me) : me.addListener("ready", fn); - } - }, + * 编辑器主类,包含编辑器提供的大部分公用接口 + * @file + * @module UE + * @class Editor + * @since 1.2.6.1 + */ /** - * 该方法是提供给插件里面使用,设置配置项默认值 - * @method setOpt - * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置 - * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。 - * @param { String } key 编辑器的可接受的选项名称 - * @param { * } val 该选项可接受的值 - * @example - * ```javascript - * editor.setOpt( 'initContent', '欢迎使用编辑器' ); - * ``` - */ + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @unfile + * @module UE + */ /** - * 该方法是提供给插件里面使用,以{key:value}集合的方式设置插件内用到的配置项默认值 - * @method setOpt - * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置 - * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。 - * @param { Object } options 将要设置的选项的键值对对象 - * @example - * ```javascript - * editor.setOpt( { - * 'initContent': '欢迎使用编辑器' - * } ); - * ``` - */ - setOpt: function(key, val) { - var obj = {}; - if (utils.isString(key)) { - obj[key] = val; - } else { - obj = key; - } - utils.extend(this.options, obj, true); - }, - getOpt: function(key) { - return this.options[key]; - }, - /** - * 销毁编辑器实例,使用textarea代替 - * @method destroy - * @example - * ```javascript - * editor.destroy(); - * ``` - */ - destroy: function() { - var me = this; - me.fireEvent("destroy"); - var container = me.container.parentNode; - var textarea = me.textarea; - if (!textarea) { - textarea = document.createElement("textarea"); - container.parentNode.insertBefore(textarea, container); - } else { - textarea.style.display = ""; - } + * UEditor的核心类,为用户提供与编辑器交互的接口。 + * @unfile + * @module UE + * @class Editor + */ - textarea.style.width = me.iframe.offsetWidth + "px"; - textarea.style.height = me.iframe.offsetHeight + "px"; - textarea.value = me.getContent(); - textarea.id = me.key; - container.innerHTML = ""; - domUtils.remove(container); - var key = me.key; - //trace:2004 - for (var p in me) { - if (me.hasOwnProperty(p)) { - delete this[p]; - } - } - UE.delEditor(key); - }, + (function () { + var uid = 0, + _selectionChangeTimer; - /** - * 渲染编辑器的DOM到指定容器 - * @method render - * @param { String } containerId 指定一个容器ID - * @remind 执行该方法,会触发ready事件 - * @warning 必须且只能调用一次 - */ - - /** - * 渲染编辑器的DOM到指定容器 - * @method render - * @param { Element } containerDom 直接指定容器对象 - * @remind 执行该方法,会触发ready事件 - * @warning 必须且只能调用一次 - */ - render: function(container) { - var me = this, - options = me.options, - getStyleValue = function(attr) { - return parseInt(domUtils.getComputedStyle(container, attr)); - }; - if (utils.isString(container)) { - container = document.getElementById(container); - } - if (container) { - if (options.initialFrameWidth) { - options.minFrameWidth = options.initialFrameWidth; - } else { - options.minFrameWidth = options.initialFrameWidth = - container.offsetWidth; - } - if (options.initialFrameHeight) { - options.minFrameHeight = options.initialFrameHeight; - } else { - options.initialFrameHeight = options.minFrameHeight = - container.offsetHeight; - } - - container.style.width = /%$/.test(options.initialFrameWidth) - ? "100%" - : options.initialFrameWidth - - getStyleValue("padding-left") - - getStyleValue("padding-right") + - "px"; - container.style.height = /%$/.test(options.initialFrameHeight) - ? "100%" - : options.initialFrameHeight - - getStyleValue("padding-top") - - getStyleValue("padding-bottom") + - "px"; - - container.style.zIndex = options.zIndex; - var additionCssHtml = []; - for(var i of options.iframeCssUrlsAddition){ - additionCssHtml.push("") - } - var html = - (ie && browser.version < 9 ? "" : "") + - "" + - "" + - "" + - (options.iframeCssUrl - ? "" - : "") + - (options.initialStyle - ? "" - : "") + - additionCssHtml.join("") + - "" + - "" + - "" + - (options.iframeJsUrl - ? "" - : "") + - ""; - - container.appendChild( - domUtils.createElement(document, "iframe", { - id: "ueditor_" + me.uid, - width: "100%", - height: "100%", - frameborder: "0", - //先注释掉了,加的原因忘记了,但开启会直接导致全屏模式下内容多时不会出现滚动条 - // scrolling :'no', - src: - "javascript:void(function(){document.open();" + - (options.customDomain && document.domain != location.hostname - ? 'document.domain="' + document.domain + '";' - : "") + - 'document.write("' + - html + - '");document.close();}())' - }) - ); - container.style.overflow = "hidden"; - //解决如果是给定的百分比,会导致高度算不对的问题 - setTimeout(function() { - if (/%$/.test(options.initialFrameWidth)) { - options.minFrameWidth = options.initialFrameWidth = - container.offsetWidth; - //如果这里给定宽度,会导致ie在拖动窗口大小时,编辑区域不随着变化 - // container.style.width = options.initialFrameWidth + 'px'; - } - if (/%$/.test(options.initialFrameHeight)) { - options.minFrameHeight = options.initialFrameHeight = - container.offsetHeight; - container.style.height = options.initialFrameHeight + "px"; - } - }); - } - }, - - /** - * 编辑器初始化 - * @method _setup + /** + * 获取编辑器的html内容,赋值到编辑器所在表单的textarea文本域里面 * @private - * @param { Element } doc 编辑器Iframe中的文档对象 + * @method setValue + * @param { UE.Editor } editor 编辑器事例 */ - _setup: function(doc) { - var me = this, - options = me.options; - if (ie) { - doc.body.disabled = true; - doc.body.contentEditable = true; - doc.body.disabled = false; - } else { - doc.body.contentEditable = true; - } - doc.body.spellcheck = false; - me.document = doc; - me.window = doc.defaultView || doc.parentWindow; - me.iframe = me.window.frameElement; - me.body = doc.body; - me.selection = new dom.Selection(doc); - //gecko初始化就能得到range,无法判断isFocus了 - var geckoSel; - if (browser.gecko && (geckoSel = this.selection.getNative())) { - geckoSel.removeAllRanges(); - } - this._initEvents(); - //为form提交提供一个隐藏的textarea - for ( - var form = this.iframe.parentNode; - !domUtils.isBody(form); - form = form.parentNode - ) { - if (form.tagName === "FORM") { - me.form = form; - if (me.options.autoSyncData) { - domUtils.on(me.window, "blur", function() { - setValue(form, me); - }); - domUtils.on(form, "submit", function() { - me.fireEvent("beforesubmit"); - }); - } else { - domUtils.on(form, "submit", function() { - setValue(this, me); - me.fireEvent("beforesubmit"); - }); - } - break; - } - } - if (options.initialContent) { - if (options.autoClearinitialContent) { - var oldExecCommand = me.execCommand; - me.execCommand = function() { - me.fireEvent("firstBeforeExecCommand"); - return oldExecCommand.apply(me, arguments); - }; - this._setDefaultContent(options.initialContent); - } else this.setContent(options.initialContent, false, true); - } - - //编辑器不能为空内容 - - if (domUtils.isEmptyNode(me.body)) { - me.body.innerHTML = "

" + (browser.ie ? "" : "
") + "

"; - } - //如果要求focus, 就把光标定位到内容开始 - if (options.focus) { - setTimeout(function() { - me.focus(me.options.focusInEnd); - //如果自动清除开着,就不需要做selectionchange; - !me.options.autoClearinitialContent && me._selectionChange(); - }, 0); - } - if (!me.container) { - me.container = this.iframe.parentNode; - } - if (options.fullscreen && me.ui) { - me.ui.setFullScreen(true); - } - - try { - me.document.execCommand("2D-position", false, false); - } catch (e) {} - try { - me.document.execCommand("enableInlineTableEditing", false, false); - } catch (e) {} - try { - me.document.execCommand("enableObjectResizing", false, false); - } catch (e) {} - - //挂接快捷键 - me._bindshortcutKeys(); - me.isReady = 1; - me.fireEvent("ready"); - options.onready && options.onready.call(me); - if (!browser.ie9below) { - domUtils.on(me.window, ["blur", "focus"], function(e) { - //chrome下会出现alt+tab切换时,导致选区位置不对 - if (e.type == "blur") { - me._bakRange = me.selection.getRange(); - try { - me._bakNativeRange = me.selection.getNative().getRangeAt(0); - me.selection.getNative().removeAllRanges(); - } catch (e) { - me._bakNativeRange = null; + function setValue(form, editor) { + if (!editor.options.textarea) { + return; } - } else { - try { - me._bakRange && me._bakRange.select(); - } catch (e) {} - } - }); - } - //trace:1518 ff3.6body不够寛,会导致点击空白处无法获得焦点 - if (browser.gecko && browser.version <= 10902) { - //修复ff3.6初始化进来,不能点击获得焦点 - me.body.contentEditable = false; - setTimeout(function() { - me.body.contentEditable = true; - }, 100); - setInterval(function() { - me.body.style.height = me.iframe.offsetHeight - 20 + "px"; - }, 100); - } - - !options.isShow && me.setHide(); - options.readonly && me.setDisabled(); - }, - - /** - * 同步数据到编辑器所在的form - * 从编辑器的容器节点向上查找form元素,若找到,就同步编辑内容到找到的form里,为提交数据做准备,主要用于是手动提交的情况 - * 后台取得数据的键值,使用你容器上的name属性,如果没有就使用参数里的textarea项 - * @method sync - * @example - * ```javascript - * editor.sync(); - * form.sumbit(); //form变量已经指向了form元素 - * ``` - */ - - /** - * 根据传入的formId,在页面上查找要同步数据的表单,若找到,就同步编辑内容到找到的form里,为提交数据做准备 - * 后台取得数据的键值,该键值默认使用给定的编辑器容器的name属性,如果没有name属性则使用参数项里给定的“textarea”项 - * @method sync - * @param { String } formID 指定一个要同步数据的form的id,编辑器的数据会同步到你指定form下 - */ - sync: function(formId) { - var me = this, - form = formId - ? document.getElementById(formId) - : domUtils.findParent( - me.iframe.parentNode, - function(node) { - return node.tagName === "FORM"; - }, - true - ); - form && setValue(form, me); - }, - - /** - * 手动触发更新按钮栏状态 - */ - syncCommandState: function(){ - this.fireEvent("selectionchange"); - }, - - /** - * 设置编辑器宽度 - * @param width - */ - setWidth: function(width){ - if (width !== parseInt(this.iframe.parentNode.parentNode.style.width)) { - this.iframe.parentNode.parentNode.style.width = width + "px"; - } - }, - - /** - * 设置编辑器高度 - * @method setHeight - * @remind 当配置项autoHeightEnabled为真时,该方法无效 - * @param { Number } number 设置的高度值,纯数值,不带单位 - * @example - * ```javascript - * editor.setHeight(number); - * ``` - */ - setHeight: function(height, notSetHeight) { - if (height !== parseInt(this.iframe.parentNode.style.height)) { - this.iframe.parentNode.style.height = height + "px"; - } - !notSetHeight && - (this.options.minFrameHeight = this.options.initialFrameHeight = height); - this.body.style.height = height + "px"; - !notSetHeight && this.trigger("setHeight"); - }, - - /** - * 为编辑器的编辑命令提供快捷键 - * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口 - * @method addshortcutkey - * @param { Object } keyset 命令名和快捷键键值对对象,多个按钮的快捷键用“+”分隔 - * @example - * ```javascript - * editor.addshortcutkey({ - * "Bold" : "ctrl+66",//^B - * "Italic" : "ctrl+73", //^I - * }); - * ``` - */ - /** - * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口 - * @method addshortcutkey - * @param { String } cmd 触发快捷键时,响应的命令 - * @param { String } keys 快捷键的字符串,多个按钮用“+”分隔 - * @example - * ```javascript - * editor.addshortcutkey("Underline", "ctrl+85"); //^U - * ``` - */ - addshortcutkey: function(cmd, keys) { - var obj = {}; - if (keys) { - obj[cmd] = keys; - } else { - obj = cmd; - } - utils.extend(this.shortcutkeys, obj); - }, - - /** - * 对编辑器设置keydown事件监听,绑定快捷键和命令,当快捷键组合触发成功,会响应对应的命令 - * @method _bindshortcutKeys - * @private - */ - _bindshortcutKeys: function() { - var me = this, - shortcutkeys = this.shortcutkeys; - me.addListener("keydown", function(type, e) { - var keyCode = e.keyCode || e.which; - for (var i in shortcutkeys) { - var tmp = shortcutkeys[i].split(","); - for (var t = 0, ti; (ti = tmp[t++]); ) { - ti = ti.split(":"); - var key = ti[0], - param = ti[1]; - if ( - /^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || - /^(\d+)$/.test(key) - ) { - if ( - ((RegExp.$1 == "ctrl" ? e.ctrlKey || e.metaKey : 0) && - (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1) && - keyCode == RegExp.$3) || - keyCode == RegExp.$1 - ) { - if (me.queryCommandState(i, param) != -1) - me.execCommand(i, param); - domUtils.preventDefault(e); - } + var textarea; + textarea = editor.textarea; + if (!textarea) { + textarea = domUtils.getElementsByTagName(form, "textarea", function (node) { + return node.id === 'ueditor_textarea_' + editor.options.textarea; + })[0]; } - } + if (!textarea) { + textarea = domUtils.getElementsByTagName(form, "textarea", function (node) { + return node.name === editor.options.textarea; + })[0]; + } + if (!textarea) { + form.appendChild( + (textarea = domUtils.createElement(document, "textarea", { + name: editor.options.textarea, + id: "ueditor_textarea_" + editor.options.textarea, + style: "display:none" + })) + ); + } + if (textarea && !editor.textarea) { + editor.textarea = textarea; + } + !textarea.getAttribute("name") && + textarea.setAttribute("name", editor.options.textarea); + textarea.value = editor.hasContents() + ? editor.options.allHtmlEnabled + ? editor.getAllHtml() + : editor.getContent(null, null, true) + : ""; } - }); - }, - /** - * 获取编辑器的内容 - * @method getContent - * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容 - * @return { String } 编辑器的内容字符串, 如果编辑器的内容为空,或者是空的标签内容(如:”<p><br/></p>“), 则返回空字符串 + function loadPlugins(me) { + //初始化插件 + for (var pi in UE.plugins) { + UE.plugins[pi].call(me); + } + } + + function checkCurLang(I18N) { + for (var lang in I18N) { + return lang; + } + } + + function langReadied(me) { + me.langIsReady = true; + + me.fireEvent("langReady"); + } + + /** + * 编辑器准备就绪后会触发该事件 + * @module UE + * @class Editor + * @event ready + * @remind render方法执行完成之后,会触发该事件 + * @remind * @example * ```javascript - * //编辑器html内容:

123456

- * var content = editor.getContent(); //返回值:

123456

- * ``` - */ - - /** - * 获取编辑器的内容。 可以通过参数定义编辑器内置的判空规则 - * @method getContent - * @param { Function } fn 自定的判空规则, 要求该方法返回一个boolean类型的值, - * 代表当前编辑器的内容是否空, - * 如果返回true, 则该方法将直接返回空字符串;如果返回false,则编辑器将返回 - * 经过内置过滤规则处理后的内容。 - * @remind 该方法在处理包含有初始化内容的时候能起到很好的作用。 - * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容 - * @return { String } 编辑器的内容字符串 - * @example - * ```javascript - * // editor 是一个编辑器的实例 - * var content = editor.getContent( function ( editor ) { - * return editor.body.innerHTML === '欢迎使用UEditor'; //返回空字符串 + * editor.addListener( 'ready', function( editor ) { + * editor.execCommand( 'focus' ); //编辑器家在完成后,让编辑器拿到焦点 * } ); * ``` */ - getContent: function(cmd, fn, notSetCursor, ignoreBlank, formatter) { - var me = this; - if (cmd && utils.isFunction(cmd)) { - fn = cmd; - cmd = ""; - } - if (fn ? !fn() : !this.hasContents()) { - return ""; - } - me.fireEvent("beforegetcontent"); - var root = UE.htmlparser(me.body.innerHTML, ignoreBlank); - me.filterOutputRule(root); - me.fireEvent("aftergetcontent", cmd, root); - return root.toHtml(formatter); - }, - - /** - * 取得完整的html代码,可以直接显示成完整的html文档 - * @method getAllHtml - * @return { String } 编辑器的内容html文档字符串 - * @eaxmple - * ```javascript - * editor.getAllHtml(); //返回格式大致是: ...... - * ``` + /** + * 执行destroy方法,会触发该事件 + * @module UE + * @class Editor + * @event destroy + * @see UE.Editor:destroy() */ - getAllHtml: function() { - var me = this, - headHtml = [], - html = ""; - me.fireEvent("getAllHtml", headHtml); - if (browser.ie && browser.version > 8) { - var headHtmlForIE9 = ""; - utils.each(me.document.styleSheets, function(si) { - headHtmlForIE9 += si.href - ? '' - : ""; - }); - utils.each(me.document.getElementsByTagName("script"), function(si) { - headHtmlForIE9 += si.outerHTML; - }); - } - return ( - "" + - (me.options.charset - ? '' - : "") + - (headHtmlForIE9 || - me.document.getElementsByTagName("head")[0].innerHTML) + - headHtml.join("\n") + - "" + - "" + - me.getContent(null, null, true) + - "" - ); - }, - - /** - * 得到编辑器的纯文本内容,但会保留段落格式 - * @method getPlainTxt - * @return { String } 编辑器带段落格式的纯文本内容字符串 + /** + * 执行reset方法,会触发该事件 + * @module UE + * @class Editor + * @event reset + * @see UE.Editor:reset() + */ + /** + * 执行focus方法,会触发该事件 + * @module UE + * @class Editor + * @event focus + * @see UE.Editor:focus(Boolean) + */ + /** + * 语言加载完成会触发该事件 + * @module UE + * @class Editor + * @event langReady + */ + /** + * 运行命令之后会触发该命令 + * @module UE + * @class Editor + * @event beforeExecCommand + */ + /** + * 运行命令之后会触发该命令 + * @module UE + * @class Editor + * @event afterExecCommand + */ + /** + * 运行命令之前会触发该命令 + * @module UE + * @class Editor + * @event firstBeforeExecCommand + */ + /** + * 在getContent方法执行之前会触发该事件 + * @module UE + * @class Editor + * @event beforeGetContent + * @see UE.Editor:getContent() + */ + /** + * 在getContent方法执行之后会触发该事件 + * @module UE + * @class Editor + * @event afterGetContent + * @see UE.Editor:getContent() + */ + /** + * 在getAllHtml方法执行时会触发该事件 + * @module UE + * @class Editor + * @event getAllHtml + * @see UE.Editor:getAllHtml() + */ + /** + * 在setContent方法执行之前会触发该事件 + * @module UE + * @class Editor + * @event beforeSetContent + * @see UE.Editor:setContent(String) + */ + /** + * 在setContent方法执行之后会触发该事件 + * @module UE + * @class Editor + * @event afterSetContent + * @see UE.Editor:setContent(String) + */ + /** + * 每当编辑器内部选区发生改变时,将触发该事件 + * @event selectionchange + * @warning 该事件的触发非常频繁,不建议在该事件的处理过程中做重量级的处理 * @example * ```javascript - * //编辑器html内容:

1

2

- * console.log(editor.getPlainTxt()); //输出:"1\n2\n - * ``` + * editor.addListener( 'selectionchange', function( editor ) { + * console.log('选区发生改变'); + * } + */ + /** + * 在所有selectionchange的监听函数执行之前,会触发该事件 + * @module UE + * @class Editor + * @event beforeSelectionChange + * @see UE.Editor:selectionchange + */ + /** + * 在所有selectionchange的监听函数执行完之后,会触发该事件 + * @module UE + * @class Editor + * @event afterSelectionChange + * @see UE.Editor:selectionchange + */ + /** + * 编辑器内容发生改变时会触发该事件 + * @module UE + * @class Editor + * @event contentChange */ - getPlainTxt: function() { - var reg = new RegExp(domUtils.fillChar, "g"), - html = this.body.innerHTML.replace(/[\n\r]/g, ""); //ie要先去了\n在处理 - html = html - .replace(/<(p|div)[^>]*>(| )<\/\1>/gi, "\n") - .replace(//gi, "\n") - .replace(/<[^>/]+>/g, "") - .replace(/(\n)?<\/([^>]+)>/g, function(a, b, c) { - return dtd.$block[c] ? "\n" : b ? b : ""; - }); - //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 - return html - .replace(reg, "") - .replace(/\u00a0/g, " ") - .replace(/ /g, " "); - }, - /** - * 获取编辑器中的纯文本内容,没有段落格式 - * @method getContentTxt - * @return { String } 编辑器不带段落格式的纯文本内容字符串 + /** + * 以默认参数构建一个编辑器实例 + * @constructor + * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面 * @example * ```javascript - * //编辑器html内容:

1

2

- * console.log(editor.getPlainTxt()); //输出:"12 + * var editor = new UE.Editor(); + * editor.execCommand('blod'); * ``` + * @see UE.Config */ - getContentTxt: function() { - var reg = new RegExp(domUtils.fillChar, "g"); - //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 - return this.body[browser.ie ? "innerText" : "textContent"] - .replace(reg, "") - .replace(/\u00a0/g, " "); - }, - /** - * 设置编辑器的内容,可修改编辑器当前的html内容 - * @method setContent - * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容 - * @warning 该方法会触发selectionchange事件 - * @param { String } html 要插入的html内容 + /** + * 以给定的参数集合创建一个编辑器实例,对于未指定的参数,将应用默认参数。 + * @constructor + * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面 + * @param { Object } setting 创建编辑器的参数 * @example * ```javascript - * editor.getContent('

test

'); + * var editor = new UE.Editor(); + * editor.execCommand('blod'); * ``` + * @see UE.Config */ + var Editor = (UE.Editor = function (options) { + var me = this; + me.uid = uid++; + EventBase.call(me); + me.commands = {}; + me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true); + me.shortcutkeys = {}; + me.inputRules = []; + me.outputRules = []; + //设置默认的常用属性 + me.setOpt(Editor.defaultOptions(me)); - /** - * 设置编辑器的内容,可修改编辑器当前的html内容 - * @method setContent - * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容 - * @warning 该方法会触发selectionchange事件 - * @param { String } html 要插入的html内容 - * @param { Boolean } isAppendTo 若传入true,不清空原来的内容,在最后插入内容,否则,清空内容再插入 - * @example - * ```javascript - * //假设设置前的编辑器内容是

old text

- * editor.setContent('

new text

', true); //插入的结果是

old text

new text

- * ``` - */ - setContent: function(html, isAppendTo, notFireSelectionchange) { - var me = this; + /* 尝试异步加载后台配置 */ + me.loadServerConfig(); - me.fireEvent("beforesetcontent", html); - var root = UE.htmlparser(html); - me.filterInputRule(root); - html = root.toHtml(); - - me.body.innerHTML = (isAppendTo ? me.body.innerHTML : "") + html; - - function isCdataDiv(node) { - return node.tagName == "DIV" && node.getAttribute("cdata_tag"); - } - //给文本或者inline节点套p标签 - if (me.options.enterTag == "p") { - var child = this.body.firstChild, - tmpNode; - if ( - !child || - (child.nodeType == 1 && - (dtd.$cdata[child.tagName] || - isCdataDiv(child) || - domUtils.isCustomeNode(child)) && - child === this.body.lastChild) - ) { - this.body.innerHTML = - "

" + - (browser.ie ? " " : "
") + - "

" + - this.body.innerHTML; - } else { - var p = me.document.createElement("p"); - while (child) { - while ( - child && - (child.nodeType == 3 || - (child.nodeType == 1 && - dtd.p[child.tagName] && - !dtd.$cdata[child.tagName])) - ) { - tmpNode = child.nextSibling; - p.appendChild(child); - child = tmpNode; - } - if (p.firstChild) { - if (!child) { - me.body.appendChild(p); - break; - } else { - child.parentNode.insertBefore(p, child); - p = me.document.createElement("p"); - } - } - child = child.nextSibling; - } - } - } - me.fireEvent("aftersetcontent"); - me.fireEvent("contentchange"); - - !notFireSelectionchange && me._selectionChange(); - //清除保存的选区 - me._bakRange = me._bakIERange = me._bakNativeRange = null; - //trace:1742 setContent后gecko能得到焦点问题 - var geckoSel; - if (browser.gecko && (geckoSel = this.selection.getNative())) { - geckoSel.removeAllRanges(); - } - if (me.options.autoSyncData) { - me.form && setValue(me.form, me); - } - }, - - /** - * 让编辑器获得焦点,默认focus到编辑器头部 - * @method focus - * @example - * ```javascript - * editor.focus() - * ``` - */ - - /** - * 让编辑器获得焦点,toEnd确定focus位置 - * @method focus - * @param { Boolean } toEnd 默认focus到编辑器头部,toEnd为true时focus到内容尾部 - * @example - * ```javascript - * editor.focus(true) - * ``` - */ - focus: function(toEnd) { - try { - var me = this, - rng = me.selection.getRange(); - if (toEnd) { - var node = me.body.lastChild; - if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) { - if (domUtils.isEmptyBlock(node)) { - rng.setStartAtFirst(node); + if (!utils.isEmptyObject(UE.I18N)) { + //修改默认的语言类型 + me.options.lang = checkCurLang(UE.I18N); + UE.plugin.load(me); + langReadied(me); } else { - rng.setStartAtLast(node); + utils.loadFile( + document, + { + src: + me.options.langPath + + me.options.lang + + "/" + + me.options.lang + + ".js?7a537435", + tag: "script", + type: "text/javascript", + defer: "defer" + }, + function () { + UE.plugin.load(me); + langReadied(me); + } + ); } - rng.collapse(true); - } - rng.setCursor(true); - } else { - if ( - !rng.collapsed && - domUtils.isBody(rng.startContainer) && - rng.startOffset == 0 - ) { - var node = me.body.firstChild; - if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) { - rng.setStartAtFirst(node).collapse(true); + + UE.instants["ueditorInstant" + me.uid] = me; + }); + Editor.prototype = { + registerCommand: function (name, obj) { + this.commands[name] = obj; + }, + /** + * 编辑器对外提供的监听ready事件的接口, 通过调用该方法,达到的效果与监听ready事件是一致的 + * @method ready + * @param { Function } fn 编辑器ready之后所执行的回调, 如果在注册事件之前编辑器已经ready,将会 + * 立即触发该回调。 + * @remind 需要等待编辑器加载完成后才能执行的代码,可以使用该方法传入 + * @example + * ```javascript + * editor.ready( function( editor ) { + * editor.setContent('初始化完毕'); + * } ); + * ``` + * @see UE.Editor.event:ready + */ + ready: function (fn) { + var me = this; + if (fn) { + me.isReady ? fn.apply(me) : me.addListener("ready", fn); + } + }, + + /** + * 该方法是提供给插件里面使用,设置配置项默认值 + * @method setOpt + * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置 + * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。 + * @param { String } key 编辑器的可接受的选项名称 + * @param { * } val 该选项可接受的值 + * @example + * ```javascript + * editor.setOpt( 'initContent', '欢迎使用编辑器' ); + * ``` + */ + + /** + * 该方法是提供给插件里面使用,以{key:value}集合的方式设置插件内用到的配置项默认值 + * @method setOpt + * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置 + * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。 + * @param { Object } options 将要设置的选项的键值对对象 + * @example + * ```javascript + * editor.setOpt( { + * 'initContent': '欢迎使用编辑器' + * } ); + * ``` + */ + setOpt: function (key, val) { + var obj = {}; + if (utils.isString(key)) { + obj[key] = val; + } else { + obj = key; + } + utils.extend(this.options, obj, true); + }, + getOpt: function (key) { + return this.options[key]; + }, + /** + * 销毁编辑器实例,使用textarea代替 + * @method destroy + * @example + * ```javascript + * editor.destroy(); + * ``` + */ + destroy: function () { + var me = this; + me.fireEvent("destroy"); + var container = me.container.parentNode; + var textarea = me.textarea; + if (!textarea) { + textarea = document.createElement("textarea"); + container.parentNode.insertBefore(textarea, container); + } else { + textarea.style.display = ""; + } + + textarea.style.width = me.iframe.offsetWidth + "px"; + textarea.style.height = me.iframe.offsetHeight + "px"; + textarea.value = me.getContent(); + textarea.id = me.key; + container.innerHTML = ""; + domUtils.remove(container); + var key = me.key; + //trace:2004 + for (var p in me) { + if (me.hasOwnProperty(p)) { + delete this[p]; + } + } + UE.delEditor(key); + }, + + /** + * 渲染编辑器的DOM到指定容器 + * @method render + * @param { String } containerId 指定一个容器ID + * @remind 执行该方法,会触发ready事件 + * @warning 必须且只能调用一次 + */ + + /** + * 渲染编辑器的DOM到指定容器 + * @method render + * @param { Element } containerDom 直接指定容器对象 + * @remind 执行该方法,会触发ready事件 + * @warning 必须且只能调用一次 + */ + render: function (container) { + var me = this, + options = me.options, + getStyleValue = function (attr) { + return parseInt(domUtils.getComputedStyle(container, attr)); + }; + if (utils.isString(container)) { + container = document.getElementById(container); + } + if (container) { + if (options.initialFrameWidth) { + options.minFrameWidth = options.initialFrameWidth; + } else { + options.minFrameWidth = options.initialFrameWidth = + container.offsetWidth; + } + if (options.initialFrameHeight) { + options.minFrameHeight = options.initialFrameHeight; + } else { + options.initialFrameHeight = options.minFrameHeight = + container.offsetHeight; + } + + container.style.width = /%$/.test(options.initialFrameWidth) + ? "100%" + : options.initialFrameWidth - + getStyleValue("padding-left") - + getStyleValue("padding-right") + + "px"; + container.style.height = /%$/.test(options.initialFrameHeight) + ? "100%" + : options.initialFrameHeight - + getStyleValue("padding-top") - + getStyleValue("padding-bottom") + + "px"; + + container.style.zIndex = options.zIndex; + var additionCssHtml = []; + for (var i in options.iframeCssUrlsAddition) { + additionCssHtml.push("") + } + var html = + (ie && browser.version < 9 ? "" : "") + + "" + + "" + + "" + + (options.iframeCssUrl + ? "" + : "") + + (options.initialStyle + ? "" + : "") + + additionCssHtml.join("") + + "" + + "" + + "" + + (options.iframeJsUrl + ? "" + : "") + + ""; + + container.appendChild( + domUtils.createElement(document, "iframe", { + id: "ueditor_" + me.uid, + width: "100%", + height: "100%", + frameborder: "0", + //先注释掉了,加的原因忘记了,但开启会直接导致全屏模式下内容多时不会出现滚动条 + // scrolling :'no', + src: + "javascript:void(function(){document.open();" + + (options.customDomain && document.domain != location.hostname + ? 'document.domain="' + document.domain + '";' + : "") + + 'document.write("' + + html + + '");document.close();}())' + }) + ); + container.style.overflow = "hidden"; + //解决如果是给定的百分比,会导致高度算不对的问题 + setTimeout(function () { + if (/%$/.test(options.initialFrameWidth)) { + options.minFrameWidth = options.initialFrameWidth = + container.offsetWidth; + //如果这里给定宽度,会导致ie在拖动窗口大小时,编辑区域不随着变化 + // container.style.width = options.initialFrameWidth + 'px'; + } + if (/%$/.test(options.initialFrameHeight)) { + options.minFrameHeight = options.initialFrameHeight = + container.offsetHeight; + container.style.height = options.initialFrameHeight + "px"; + } + }); + } + }, + + /** + * 编辑器初始化 + * @method _setup + * @private + * @param { Element } doc 编辑器Iframe中的文档对象 + */ + _setup: function (doc) { + var me = this, + options = me.options; + if (ie) { + doc.body.disabled = true; + doc.body.contentEditable = true; + doc.body.disabled = false; + } else { + doc.body.contentEditable = true; + } + doc.body.spellcheck = false; + me.document = doc; + me.window = doc.defaultView || doc.parentWindow; + me.iframe = me.window.frameElement; + me.body = doc.body; + me.selection = new dom.Selection(doc); + //gecko初始化就能得到range,无法判断isFocus了 + var geckoSel; + if (browser.gecko && (geckoSel = this.selection.getNative())) { + geckoSel.removeAllRanges(); + } + this._initEvents(); + //为form提交提供一个隐藏的textarea + for ( + var form = this.iframe.parentNode; + !domUtils.isBody(form); + form = form.parentNode + ) { + if (form.tagName === "FORM") { + me.form = form; + if (me.options.autoSyncData) { + domUtils.on(me.window, "blur", function () { + setValue(form, me); + }); + domUtils.on(form, "submit", function () { + me.fireEvent("beforesubmit"); + }); + } else { + domUtils.on(form, "submit", function () { + setValue(this, me); + me.fireEvent("beforesubmit"); + }); + } + break; + } + } + if (options.initialContent) { + if (options.autoClearinitialContent) { + var oldExecCommand = me.execCommand; + me.execCommand = function () { + me.fireEvent("firstBeforeExecCommand"); + return oldExecCommand.apply(me, arguments); + }; + this._setDefaultContent(options.initialContent); + } else this.setContent(options.initialContent, false, true); + } + + //编辑器不能为空内容 + + if (domUtils.isEmptyNode(me.body)) { + me.body.innerHTML = "

" + (browser.ie ? "" : "
") + "

"; + } + //如果要求focus, 就把光标定位到内容开始 + if (options.focus) { + setTimeout(function () { + me.focus(me.options.focusInEnd); + //如果自动清除开着,就不需要做selectionchange; + !me.options.autoClearinitialContent && me._selectionChange(); + }, 0); + } + if (!me.container) { + me.container = this.iframe.parentNode; + } + if (options.fullscreen && me.ui) { + me.ui.setFullScreen(true); + } + + try { + me.document.execCommand("2D-position", false, false); + } catch (e) { + } + try { + me.document.execCommand("enableInlineTableEditing", false, false); + } catch (e) { + } + try { + me.document.execCommand("enableObjectResizing", false, false); + } catch (e) { + } + + //挂接快捷键 + me._bindshortcutKeys(); + me.isReady = 1; + me.fireEvent("ready"); + options.onready && options.onready.call(me); + if (!browser.ie9below) { + domUtils.on(me.window, ["blur", "focus"], function (e) { + //chrome下会出现alt+tab切换时,导致选区位置不对 + if (e.type == "blur") { + me._bakRange = me.selection.getRange(); + try { + me._bakNativeRange = me.selection.getNative().getRangeAt(0); + me.selection.getNative().removeAllRanges(); + } catch (e) { + me._bakNativeRange = null; + } + } else { + try { + me._bakRange && me._bakRange.select(); + } catch (e) { + } + } + }); + } + //trace:1518 ff3.6body不够寛,会导致点击空白处无法获得焦点 + if (browser.gecko && browser.version <= 10902) { + //修复ff3.6初始化进来,不能点击获得焦点 + me.body.contentEditable = false; + setTimeout(function () { + me.body.contentEditable = true; + }, 100); + setInterval(function () { + me.body.style.height = me.iframe.offsetHeight - 20 + "px"; + }, 100); + } + + !options.isShow && me.setHide(); + options.readonly && me.setDisabled(); + }, + + /** + * 同步数据到编辑器所在的form + * 从编辑器的容器节点向上查找form元素,若找到,就同步编辑内容到找到的form里,为提交数据做准备,主要用于是手动提交的情况 + * 后台取得数据的键值,使用你容器上的name属性,如果没有就使用参数里的textarea项 + * @method sync + * @example + * ```javascript + * editor.sync(); + * form.sumbit(); //form变量已经指向了form元素 + * ``` + */ + + /** + * 根据传入的formId,在页面上查找要同步数据的表单,若找到,就同步编辑内容到找到的form里,为提交数据做准备 + * 后台取得数据的键值,该键值默认使用给定的编辑器容器的name属性,如果没有name属性则使用参数项里给定的“textarea”项 + * @method sync + * @param { String } formID 指定一个要同步数据的form的id,编辑器的数据会同步到你指定form下 + */ + sync: function (formId) { + var me = this, + form = formId + ? document.getElementById(formId) + : domUtils.findParent( + me.iframe.parentNode, + function (node) { + return node.tagName === "FORM"; + }, + true + ); + form && setValue(form, me); + }, + + /** + * 手动触发更新按钮栏状态 + */ + syncCommandState: function () { + this.fireEvent("selectionchange"); + }, + + /** + * 设置编辑器宽度 + * @param width + */ + setWidth: function (width) { + if (width !== parseInt(this.iframe.parentNode.parentNode.style.width)) { + this.iframe.parentNode.parentNode.style.width = width + "px"; + } + }, + + /** + * 设置编辑器高度 + * @method setHeight + * @remind 当配置项autoHeightEnabled为真时,该方法无效 + * @param { Number } number 设置的高度值,纯数值,不带单位 + * @example + * ```javascript + * editor.setHeight(number); + * ``` + */ + setHeight: function (height, notSetHeight) { + if (height !== parseInt(this.iframe.parentNode.style.height)) { + this.iframe.parentNode.style.height = height + "px"; + } + !notSetHeight && + (this.options.minFrameHeight = this.options.initialFrameHeight = height); + this.body.style.height = height + "px"; + !notSetHeight && this.trigger("setHeight"); + }, + + /** + * 为编辑器的编辑命令提供快捷键 + * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口 + * @method addshortcutkey + * @param { Object } keyset 命令名和快捷键键值对对象,多个按钮的快捷键用“+”分隔 + * @example + * ```javascript + * editor.addshortcutkey({ + * "Bold" : "ctrl+66",//^B + * "Italic" : "ctrl+73", //^I + * }); + * ``` + */ + /** + * 这个接口是为插件扩展提供的接口,主要是为新添加的插件,如果需要添加快捷键,所提供的接口 + * @method addshortcutkey + * @param { String } cmd 触发快捷键时,响应的命令 + * @param { String } keys 快捷键的字符串,多个按钮用“+”分隔 + * @example + * ```javascript + * editor.addshortcutkey("Underline", "ctrl+85"); //^U + * ``` + */ + addshortcutkey: function (cmd, keys) { + var obj = {}; + if (keys) { + obj[cmd] = keys; + } else { + obj = cmd; + } + utils.extend(this.shortcutkeys, obj); + }, + + /** + * 对编辑器设置keydown事件监听,绑定快捷键和命令,当快捷键组合触发成功,会响应对应的命令 + * @method _bindshortcutKeys + * @private + */ + _bindshortcutKeys: function () { + var me = this, + shortcutkeys = this.shortcutkeys; + me.addListener("keydown", function (type, e) { + var keyCode = e.keyCode || e.which; + for (var i in shortcutkeys) { + var tmp = shortcutkeys[i].split(","); + for (var t = 0, ti; (ti = tmp[t++]);) { + ti = ti.split(":"); + var key = ti[0], + param = ti[1]; + if ( + /^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || + /^(\d+)$/.test(key) + ) { + if ( + ((RegExp.$1 == "ctrl" ? e.ctrlKey || e.metaKey : 0) && + (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1) && + keyCode == RegExp.$3) || + keyCode == RegExp.$1 + ) { + if (me.queryCommandState(i, param) != -1) + me.execCommand(i, param); + domUtils.preventDefault(e); + } + } + } + } + }); + }, + + /** + * 获取编辑器的内容 + * @method getContent + * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容 + * @return { String } 编辑器的内容字符串, 如果编辑器的内容为空,或者是空的标签内容(如:”<p><br/></p>“), 则返回空字符串 + * @example + * ```javascript + * //编辑器html内容:

123456

+ * var content = editor.getContent(); //返回值:

123456

+ * ``` + */ + + /** + * 获取编辑器的内容。 可以通过参数定义编辑器内置的判空规则 + * @method getContent + * @param { Function } fn 自定的判空规则, 要求该方法返回一个boolean类型的值, + * 代表当前编辑器的内容是否空, + * 如果返回true, 则该方法将直接返回空字符串;如果返回false,则编辑器将返回 + * 经过内置过滤规则处理后的内容。 + * @remind 该方法在处理包含有初始化内容的时候能起到很好的作用。 + * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容 + * @return { String } 编辑器的内容字符串 + * @example + * ```javascript + * // editor 是一个编辑器的实例 + * var content = editor.getContent( function ( editor ) { + * return editor.body.innerHTML === '欢迎使用UEditor'; //返回空字符串 + * } ); + * ``` + */ + getContent: function (cmd, fn, notSetCursor, ignoreBlank, formatter) { + var me = this; + if (cmd && utils.isFunction(cmd)) { + fn = cmd; + cmd = ""; + } + if (fn ? !fn() : !this.hasContents()) { + return ""; + } + me.fireEvent("beforegetcontent"); + var root = UE.htmlparser(me.body.innerHTML, ignoreBlank); + me.filterOutputRule(root); + me.fireEvent("aftergetcontent", cmd, root); + return root.toHtml(formatter); + }, + + /** + * 取得完整的html代码,可以直接显示成完整的html文档 + * @method getAllHtml + * @return { String } 编辑器的内容html文档字符串 + * @eaxmple + * ```javascript + * editor.getAllHtml(); //返回格式大致是: ...... + * ``` + */ + getAllHtml: function () { + var me = this, + headHtml = [], + html = ""; + me.fireEvent("getAllHtml", headHtml); + if (browser.ie && browser.version > 8) { + var headHtmlForIE9 = ""; + utils.each(me.document.styleSheets, function (si) { + headHtmlForIE9 += si.href + ? '' + : ""; + }); + utils.each(me.document.getElementsByTagName("script"), function (si) { + headHtmlForIE9 += si.outerHTML; + }); + } + return ( + "" + + (me.options.charset + ? '' + : "") + + (headHtmlForIE9 || + me.document.getElementsByTagName("head")[0].innerHTML) + + headHtml.join("\n") + + "" + + "" + + me.getContent(null, null, true) + + "" + ); + }, + + /** + * 得到编辑器的纯文本内容,但会保留段落格式 + * @method getPlainTxt + * @return { String } 编辑器带段落格式的纯文本内容字符串 + * @example + * ```javascript + * //编辑器html内容:

1

2

+ * console.log(editor.getPlainTxt()); //输出:"1\n2\n + * ``` + */ + getPlainTxt: function () { + var reg = new RegExp(domUtils.fillChar, "g"), + html = this.body.innerHTML.replace(/[\n\r]/g, ""); //ie要先去了\n在处理 + html = html + .replace(/<(p|div)[^>]*>(| )<\/\1>/gi, "\n") + .replace(//gi, "\n") + .replace(/<[^>/]+>/g, "") + .replace(/(\n)?<\/([^>]+)>/g, function (a, b, c) { + return dtd.$block[c] ? "\n" : b ? b : ""; + }); + //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 + return html + .replace(reg, "") + .replace(/\u00a0/g, " ") + .replace(/ /g, " "); + }, + + /** + * 获取编辑器中的纯文本内容,没有段落格式 + * @method getContentTxt + * @return { String } 编辑器不带段落格式的纯文本内容字符串 + * @example + * ```javascript + * //编辑器html内容:

1

2

+ * console.log(editor.getPlainTxt()); //输出:"12 + * ``` + */ + getContentTxt: function () { + var reg = new RegExp(domUtils.fillChar, "g"); + //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 + return this.body[browser.ie ? "innerText" : "textContent"] + .replace(reg, "") + .replace(/\u00a0/g, " "); + }, + + /** + * 设置编辑器的内容,可修改编辑器当前的html内容 + * @method setContent + * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容 + * @warning 该方法会触发selectionchange事件 + * @param { String } html 要插入的html内容 + * @example + * ```javascript + * editor.getContent('

test

'); + * ``` + */ + + /** + * 设置编辑器的内容,可修改编辑器当前的html内容 + * @method setContent + * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容 + * @warning 该方法会触发selectionchange事件 + * @param { String } html 要插入的html内容 + * @param { Boolean } isAppendTo 若传入true,不清空原来的内容,在最后插入内容,否则,清空内容再插入 + * @param { Boolean } notFireSelectionchange 是否阻止触发选区变化,true为阻止,false为不阻止 + * @example + * ```javascript + * //假设设置前的编辑器内容是

old text

+ * editor.setContent('

new text

', true); //插入的结果是

old text

new text

+ * ``` + */ + setContent: function (html, isAppendTo, notFireSelectionchange) { + var me = this; + + me.fireEvent("beforesetcontent", html); + var root = UE.htmlparser(html); + me.filterInputRule(root); + html = root.toHtml(); + + me.body.innerHTML = (isAppendTo ? me.body.innerHTML : "") + html; + + function isCdataDiv(node) { + return node.tagName == "DIV" && node.getAttribute("cdata_tag"); + } + + //给文本或者inline节点套p标签 + if (me.options.enterTag == "p") { + var child = this.body.firstChild, + tmpNode; + if ( + !child || + (child.nodeType == 1 && + (dtd.$cdata[child.tagName] || + isCdataDiv(child) || + domUtils.isCustomeNode(child)) && + child === this.body.lastChild) + ) { + this.body.innerHTML = + "

" + + (browser.ie ? " " : "
") + + "

" + + this.body.innerHTML; + } else { + var p = me.document.createElement("p"); + while (child) { + while ( + child && + (child.nodeType == 3 || + (child.nodeType == 1 && + dtd.p[child.tagName] && + !dtd.$cdata[child.tagName])) + ) { + tmpNode = child.nextSibling; + p.appendChild(child); + child = tmpNode; + } + if (p.firstChild) { + if (!child) { + me.body.appendChild(p); + break; + } else { + child.parentNode.insertBefore(p, child); + p = me.document.createElement("p"); + } + } + child = child.nextSibling; + } + } + } + me.fireEvent("aftersetcontent"); + me.fireEvent("contentchange"); + + !notFireSelectionchange && me._selectionChange(); + //清除保存的选区 + me._bakRange = me._bakIERange = me._bakNativeRange = null; + //trace:1742 setContent后gecko能得到焦点问题 + var geckoSel; + if (browser.gecko && (geckoSel = this.selection.getNative())) { + geckoSel.removeAllRanges(); + } + if (me.options.autoSyncData) { + me.form && setValue(me.form, me); + } + }, + + /** + * 让编辑器获得焦点,默认focus到编辑器头部 + * @method focus + * @example + * ```javascript + * editor.focus() + * ``` + */ + + /** + * 让编辑器获得焦点,toEnd确定focus位置 + * @method focus + * @param { Boolean } toEnd 默认focus到编辑器头部,toEnd为true时focus到内容尾部 + * @example + * ```javascript + * editor.focus(true) + * ``` + */ + focus: function (toEnd) { + try { + var me = this, + rng = me.selection.getRange(); + if (toEnd) { + var node = me.body.lastChild; + if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) { + if (domUtils.isEmptyBlock(node)) { + rng.setStartAtFirst(node); + } else { + rng.setStartAtLast(node); + } + rng.collapse(true); + } + rng.setCursor(true); + } else { + if ( + !rng.collapsed && + domUtils.isBody(rng.startContainer) && + rng.startOffset == 0 + ) { + var node = me.body.firstChild; + if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) { + rng.setStartAtFirst(node).collapse(true); + } + } + + rng.select(true); + } + this.fireEvent("focus selectionchange"); + } catch (e) { + } + }, + isFocus: function () { + return this.selection.isFocus(); + }, + blur: function () { + var sel = this.selection.getNative(); + if (sel.empty && browser.ie) { + var nativeRng = document.body.createTextRange(); + nativeRng.moveToElementText(document.body); + nativeRng.collapse(true); + nativeRng.select(); + sel.empty(); + } else { + sel.removeAllRanges(); + } + + //this.fireEvent('blur selectionchange'); + }, + /** + * 初始化UE事件及部分事件代理 + * @method _initEvents + * @private + */ + _initEvents: function () { + var me = this, + doc = me.document, + win = me.window; + me._proxyDomEvent = utils.bind(me._proxyDomEvent, me); + domUtils.on( + doc, + [ + "click", + "contextmenu", + "mousedown", + "keydown", + "keyup", + "keypress", + "mouseup", + "mouseover", + "mouseout", + "selectstart" + ], + me._proxyDomEvent + ); + domUtils.on(win, ["focus", "blur"], me._proxyDomEvent); + domUtils.on(me.body, "drop", function (e) { + //阻止ff下默认的弹出新页面打开图片 + if (browser.gecko && e.stopPropagation) { + e.stopPropagation(); + } + me.fireEvent("contentchange"); + }); + // 当内容最末尾为非字符时,比较难以在最后插入字符,所以在点击时,自动添加一个空的p标签 + domUtils.on(me.body, "dblclick", function (e) { + try { + var node = me.body.lastChild; + if (!node) { + return; + } + var rect = node.getBoundingClientRect(); + if (e.clientY > rect.top + rect.height) { + var p = document.createElement('p'); + p.innerHTML = '
'; + me.body.appendChild(p); + setTimeout(function () { + me.focus(true); + }, 100); + } + } catch (e) { + console.error('auto insert p at end', e); + } + }); + domUtils.on(doc, ["mouseup", "keydown"], function (evt) { + //特殊键不触发selectionchange + if ( + evt.type === "keydown" && + (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey) + ) { + return; + } + if (evt.button === 2) return; + me._selectionChange(250, evt); + }); + }, + /** + * 触发事件代理 + * @method _proxyDomEvent + * @private + * @return { * } fireEvent的返回值 + * @see UE.EventBase:fireEvent(String) + */ + _proxyDomEvent: function (evt) { + if ( + this.fireEvent("before" + evt.type.replace(/^on/, "").toLowerCase()) === + false + ) { + return false; + } + if (this.fireEvent(evt.type.replace(/^on/, ""), evt) === false) { + return false; + } + return this.fireEvent( + "after" + evt.type.replace(/^on/, "").toLowerCase() + ); + }, + /** + * 变化选区 + * @method _selectionChange + * @private + */ + _selectionChange: function (delay, evt) { + var me = this; + //有光标才做selectionchange 为了解决未focus时点击source不能触发更改工具栏状态的问题(source命令notNeedUndo=1) + // if ( !me.selection.isFocus() ){ + // return; + // } + + var hackForMouseUp = false; + var mouseX, mouseY; + if (browser.ie && browser.version < 9 && evt && evt.type == "mouseup") { + var range = this.selection.getRange(); + if (!range.collapsed) { + hackForMouseUp = true; + mouseX = evt.clientX; + mouseY = evt.clientY; + } + } + clearTimeout(_selectionChangeTimer); + _selectionChangeTimer = setTimeout(function () { + if (!me.selection || !me.selection.getNative()) { + return; + } + //修复一个IE下的bug: 鼠标点击一段已选择的文本中间时,可能在mouseup后的一段时间内取到的range是在selection的type为None下的错误值. + //IE下如果用户是拖拽一段已选择文本,则不会触发mouseup事件,所以这里的特殊处理不会对其有影响 + var ieRange; + if (hackForMouseUp && me.selection.getNative().type == "None") { + ieRange = me.document.body.createTextRange(); + try { + ieRange.moveToPoint(mouseX, mouseY); + } catch (ex) { + ieRange = null; + } + } + var bakGetIERange; + if (ieRange) { + bakGetIERange = me.selection.getIERange; + me.selection.getIERange = function () { + return ieRange; + }; + } + me.selection.cache(); + if (bakGetIERange) { + me.selection.getIERange = bakGetIERange; + } + if (me.selection._cachedRange && me.selection._cachedStartElement) { + me.fireEvent("beforeselectionchange"); + // 第二个参数causeByUi为true代表由用户交互造成的selectionchange. + me.fireEvent("selectionchange", !!evt); + me.fireEvent("afterselectionchange"); + me.selection.clear(); + } + }, delay || 50); + }, + + /** + * 执行编辑命令 + * @method _callCmdFn + * @private + * @param { String } fnName 函数名称 + * @param { * } args 传给命令函数的参数 + * @return { * } 返回命令函数运行的返回值 + */ + _callCmdFn: function (fnName, args) { + var cmdName = args[0].toLowerCase(), + cmd, + cmdFn; + cmd = this.commands[cmdName] || UE.commands[cmdName]; + cmdFn = cmd && cmd[fnName]; + //没有querycommandstate或者没有command的都默认返回0 + if ((!cmd || !cmdFn) && fnName == "queryCommandState") { + return 0; + } else if (cmdFn) { + return cmdFn.apply(this, args); + } + }, + + /** + * 执行编辑命令cmdName,完成富文本编辑效果 + * @method execCommand + * @param { String } cmdName 需要执行的命令 + * @remind 具体命令的使用请参考命令列表 + * @return { * } 返回命令函数运行的返回值 + * @example + * ```javascript + * editor.execCommand(cmdName); + * ``` + */ + execCommand: function (cmdName) { + cmdName = cmdName.toLowerCase(); + var me = this, + result, + cmd = me.commands[cmdName] || UE.commands[cmdName]; + if (!cmd || !cmd.execCommand) { + return null; + } + if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) { + me.__hasEnterExecCommand = true; + if (me.queryCommandState.apply(me, arguments) != -1) { + me.fireEvent("saveScene"); + me.fireEvent.apply( + me, + ["beforeexeccommand", cmdName].concat(arguments) + ); + result = this._callCmdFn("execCommand", arguments); + //保存场景时,做了内容对比,再看是否进行contentchange触发,这里多触发了一次,去掉 + // (!cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange'); + me.fireEvent.apply( + me, + ["afterexeccommand", cmdName].concat(arguments) + ); + me.fireEvent("saveScene"); + } + me.__hasEnterExecCommand = false; + } else { + result = this._callCmdFn("execCommand", arguments); + !me.__hasEnterExecCommand && + !cmd.ignoreContentChange && + !me._ignoreContentChange && + me.fireEvent("contentchange"); + } + !me.__hasEnterExecCommand && + !cmd.ignoreContentChange && + !me._ignoreContentChange && + me._selectionChange(); + return result; + }, + + /** + * 根据传入的command命令,查选编辑器当前的选区,返回命令的状态 + * @method queryCommandState + * @param { String } cmdName 需要查询的命令名称 + * @remind 具体命令的使用请参考命令列表 + * @return { Number } number 返回放前命令的状态,返回值三种情况:(-1|0|1) + * @example + * ```javascript + * editor.queryCommandState(cmdName) => (-1|0|1) + * ``` + * @see COMMAND.LIST + */ + queryCommandState: function (cmdName) { + return this._callCmdFn("queryCommandState", arguments); + }, + + /** + * 根据传入的command命令,查选编辑器当前的选区,根据命令返回相关的值 + * @method queryCommandValue + * @param { String } cmdName 需要查询的命令名称 + * @remind 具体命令的使用请参考命令列表 + * @remind 只有部分插件有此方法 + * @return { * } 返回每个命令特定的当前状态值 + * @grammar editor.queryCommandValue(cmdName) => {*} + * @see COMMAND.LIST + */ + queryCommandValue: function (cmdName) { + return this._callCmdFn("queryCommandValue", arguments); + }, + + /** + * 检查编辑区域中是否有内容 + * @method hasContents + * @remind 默认有文本内容,或者有以下节点都不认为是空 + * table,ul,ol,dl,iframe,area,base,col,hr,img,embed,input,link,meta,param + * @return { Boolean } 检查有内容返回true,否则返回false + * @example + * ```javascript + * editor.hasContents() + * ``` + */ + + /** + * 检查编辑区域中是否有内容,若包含参数tags中的节点类型,直接返回true + * @method hasContents + * @param { Array } tags 传入数组判断时用到的节点类型 + * @return { Boolean } 若文档中包含tags数组里对应的tag,返回true,否则返回false + * @example + * ```javascript + * editor.hasContents(['span']); + * ``` + */ + hasContents: function (tags) { + if (tags) { + for (var i = 0, ci; (ci = tags[i++]);) { + if (this.document.getElementsByTagName(ci).length > 0) { + return true; + } + } + } + if (!domUtils.isEmptyBlock(this.body)) { + return true; + } + // 随时添加,定义的特殊标签如果存在,不能认为是空 + tags = ["div"]; + for (i = 0; (ci = tags[i++]);) { + var nodes = domUtils.getElementsByTagName(this.document, ci); + for (var n = 0, cn; (cn = nodes[n++]);) { + if (domUtils.isCustomeNode(cn)) { + return true; + } + } + } + // 部分如媒体标签,不能认为为空 + tags = ["video", "iframe"] + for (i = 0; (ci = tags[i++]);) { + var nodes = domUtils.getElementsByTagName(this.document, ci); + for (var n = 0, cn; (cn = nodes[n++]);) { + return true; + } + } + return false; + }, + + /** + * 重置编辑器,可用来做多个tab 使用同一个编辑器实例 + * @method reset + * @remind 此方法会清空编辑器内容,清空回退列表,会触发reset事件 + * @example + * ```javascript + * editor.reset() + * ``` + */ + reset: function () { + this.clear(); + this.fireEvent("reset"); + }, + + /** + * 清空编辑器内容 + * @method clear + * @remind 此方法会清空编辑器内容 + * @example + * ```javascript + * editor.clear() + * ``` + */ + clear: function () { + this.setContent(""); + }, + + /** + * 设置当前编辑区域可以编辑 + * @method setEnabled + * @example + * ```javascript + * editor.setEnabled() + * ``` + */ + setEnabled: function () { + var me = this, + range; + if (me.body.contentEditable === "false") { + me.body.contentEditable = true; + range = me.selection.getRange(); + //有可能内容丢失了 + try { + range.moveToBookmark(me.lastBk); + delete me.lastBk; + } catch (e) { + range.setStartAtFirst(me.body).collapse(true); + } + range.select(true); + if (me.bkqueryCommandState) { + me.queryCommandState = me.bkqueryCommandState; + delete me.bkqueryCommandState; + } + if (me.bkqueryCommandValue) { + me.queryCommandValue = me.bkqueryCommandValue; + delete me.bkqueryCommandValue; + } + me.fireEvent("selectionchange"); + } + }, + enable: function () { + return this.setEnabled(); + }, + + /** 设置当前编辑区域不可编辑 + * @method setDisabled + */ + + /** 设置当前编辑区域不可编辑,except中的命令除外 + * @method setDisabled + * @param { String } except 例外命令的字符串 + * @remind 即使设置了disable,此处配置的例外命令仍然可以执行 + * @example + * ```javascript + * editor.setDisabled('bold'); //禁用工具栏中除加粗之外的所有功能 + * ``` + */ + + /** 设置当前编辑区域不可编辑,except中的命令除外 + * @method setDisabled + * @param { Array } except 例外命令的字符串数组,数组中的命令仍然可以执行 + * @remind 即使设置了disable,此处配置的例外命令仍然可以执行 + * @example + * ```javascript + * editor.setDisabled(['bold','insertimage']); //禁用工具栏中除加粗和插入图片之外的所有功能 + * ``` + */ + setDisabled: function (except) { + var me = this; + except = except ? (utils.isArray(except) ? except : [except]) : []; + if (me.body.contentEditable == "true") { + if (!me.lastBk) { + me.lastBk = me.selection.getRange().createBookmark(true); + } + me.body.contentEditable = false; + me.bkqueryCommandState = me.queryCommandState; + me.bkqueryCommandValue = me.queryCommandValue; + me.queryCommandState = function (type) { + if (utils.indexOf(except, type) != -1) { + return me.bkqueryCommandState.apply(me, arguments); + } + return -1; + }; + me.queryCommandValue = function (type) { + if (utils.indexOf(except, type) != -1) { + return me.bkqueryCommandValue.apply(me, arguments); + } + return null; + }; + me.fireEvent("selectionchange"); + } + }, + disable: function (except) { + return this.setDisabled(except); + }, + + /** + * 设置默认内容 + * @method _setDefaultContent + * @private + * @param { String } cont 要存入的内容 + */ + _setDefaultContent: (function () { + function clear() { + var me = this; + if (me.document.getElementById("initContent")) { + me.body.innerHTML = "

" + (ie ? "" : "
") + "

"; + me.removeListener("firstBeforeExecCommand focus", clear); + setTimeout(function () { + me.focus(); + me._selectionChange(); + }, 0); + } + } + + return function (cont) { + var me = this; + me.body.innerHTML = '

' + cont + "

"; + + me.addListener("firstBeforeExecCommand focus", clear); + }; + })(), + + /** + * 显示编辑器 + * @method setShow + * @example + * ```javascript + * editor.setShow() + * ``` + */ + setShow: function () { + var me = this, + range = me.selection.getRange(); + if (me.container.style.display == "none") { + //有可能内容丢失了 + try { + range.moveToBookmark(me.lastBk); + delete me.lastBk; + } catch (e) { + range.setStartAtFirst(me.body).collapse(true); + } + //ie下focus实效,所以做了个延迟 + setTimeout(function () { + range.select(true); + }, 100); + me.container.style.display = ""; + } + }, + show: function () { + return this.setShow(); + }, + /** + * 隐藏编辑器 + * @method setHide + * @example + * ```javascript + * editor.setHide() + * ``` + */ + setHide: function () { + var me = this; + if (!me.lastBk) { + me.lastBk = me.selection.getRange().createBookmark(true); + } + me.container.style.display = "none"; + }, + hide: function () { + return this.setHide(); + }, + + /** + * 根据指定的路径,获取对应的语言资源 + * @method getLang + * @param { String } path 路径根据的是lang目录下的语言文件的路径结构 + * @return { Object | String } 根据路径返回语言资源的Json格式对象或者语言字符串 + * @example + * ```javascript + * editor.getLang('contextMenu.delete'); //如果当前是中文,那返回是的是'删除' + * ``` + */ + getLang: function (path) { + var lang = UE.I18N[this.options.lang]; + if (!lang) { + throw Error("not import language file"); + } + path = (path || "").split("."); + for (var i = 0, ci; (ci = path[i++]);) { + lang = lang[ci]; + if (!lang) break; + } + return lang; + }, + + /** + * 计算编辑器html内容字符串的长度 + * @method getContentLength + * @return { Number } 返回计算的长度 + * @example + * ```javascript + * //编辑器html内容

132

+ * editor.getContentLength() //返回27 + * ``` + */ + /** + * 计算编辑器当前纯文本内容的长度 + * @method getContentLength + * @param { Boolean } ingoneHtml 传入true时,只按照纯文本来计算 + * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签,长度加1 + * @example + * ```javascript + * //编辑器html内容

132

+ * editor.getContentLength() //返回3 + * ``` + */ + getContentLength: function (ingoneHtml, tagNames) { + var count = this.getContent(false, false, true).length; + if (ingoneHtml) { + tagNames = (tagNames || []).concat(["hr", "img", "iframe"]); + count = this.getContentTxt().replace(/[\t\r\n]+/g, "").length; + for (var i = 0, ci; (ci = tagNames[i++]);) { + count += this.document.getElementsByTagName(ci).length; + } + } + return count; + }, + + getScrollTop: function () { + return Math.max(this.document.documentElement.scrollTop, this.document.body.scrollTop); + }, + getScrollLeft: function () { + return Math.max(this.document.documentElement.scrollLeft, this.document.body.scrollLeft); + }, + + /** + * 注册输入过滤规则 + * @method addInputRule + * @param { Function } rule 要添加的过滤规则 + * @example + * ```javascript + * editor.addInputRule(function(root){ + * $.each(root.getNodesByTagName('div'),function(i,node){ + * node.tagName="p"; + * }); + * }); + * ``` + */ + addInputRule: function (rule) { + this.inputRules.push(rule); + }, + + /** + * 执行注册的过滤规则 + * @method filterInputRule + * @param { UE.uNode } root 要过滤的uNode节点 + * @remind 执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数 + * @example + * ```javascript + * editor.filterInputRule(editor.body); + * ``` + * @see UE.Editor:addInputRule + */ + filterInputRule: function (root) { + for (var i = 0, ci; (ci = this.inputRules[i++]);) { + ci.call(this, root); + } + }, + + /** + * 注册输出过滤规则 + * @method addOutputRule + * @param { Function } rule 要添加的过滤规则 + * @example + * ```javascript + * editor.addOutputRule(function(root){ + * $.each(root.getNodesByTagName('p'),function(i,node){ + * node.tagName="div"; + * }); + * }); + * ``` + */ + addOutputRule: function (rule) { + this.outputRules.push(rule); + }, + + /** + * 根据输出过滤规则,过滤编辑器内容 + * @method filterOutputRule + * @remind 执行editor.getContent方法的时候,会先运行该过滤函数 + * @param { UE.uNode } root 要过滤的uNode节点 + * @example + * ```javascript + * editor.filterOutputRule(editor.body); + * ``` + * @see UE.Editor:addOutputRule + */ + filterOutputRule: function (root) { + for (var i = 0, ci; (ci = this.outputRules[i++]);) { + ci.call(this, root); + } + }, + + /** + * 根据action名称获取请求的路径 + * @method getActionUrl + * @remind 假如没有设置serverUrl,会根据imageUrl设置默认的controller路径 + * @param { String } action action名称 + * @example + * ```javascript + * editor.getActionUrl('config'); //返回 "/ueditor/php/controller.php?action=config" + * editor.getActionUrl('image'); //返回 "/ueditor/php/controller.php?action=uplaodimage" + * editor.getActionUrl('scrawl'); //返回 "/ueditor/php/controller.php?action=uplaodscrawl" + * editor.getActionUrl('imageManager'); //返回 "/ueditor/php/controller.php?action=listimage" + * ``` + */ + getActionUrl: function (action) { + var serverUrl = this.getOpt("serverUrl") + if (!action) { + return serverUrl; + } + var actionName = this.getOpt(action) || action, + imageUrl = this.getOpt("imageUrl"); + + if (!serverUrl && imageUrl) { + serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, "$1controller$2"); + } + if (serverUrl) { + serverUrl = + serverUrl + + (serverUrl.indexOf("?") === -1 ? "?" : "&") + + "action=" + + (actionName || ""); + return utils.formatUrl(serverUrl); + } else { + return ""; + } } - } - - rng.select(true); - } - this.fireEvent("focus selectionchange"); - } catch (e) {} - }, - isFocus: function() { - return this.selection.isFocus(); - }, - blur: function() { - var sel = this.selection.getNative(); - if (sel.empty && browser.ie) { - var nativeRng = document.body.createTextRange(); - nativeRng.moveToElementText(document.body); - nativeRng.collapse(true); - nativeRng.select(); - sel.empty(); - } else { - sel.removeAllRanges(); - } - - //this.fireEvent('blur selectionchange'); - }, - /** - * 初始化UE事件及部分事件代理 - * @method _initEvents - * @private - */ - _initEvents: function() { - var me = this, - doc = me.document, - win = me.window; - me._proxyDomEvent = utils.bind(me._proxyDomEvent, me); - domUtils.on( - doc, - [ - "click", - "contextmenu", - "mousedown", - "keydown", - "keyup", - "keypress", - "mouseup", - "mouseover", - "mouseout", - "selectstart" - ], - me._proxyDomEvent - ); - domUtils.on(win, ["focus", "blur"], me._proxyDomEvent); - domUtils.on(me.body, "drop", function(e) { - //阻止ff下默认的弹出新页面打开图片 - if (browser.gecko && e.stopPropagation) { - e.stopPropagation(); - } - me.fireEvent("contentchange"); - }); - // 当内容最末尾为非字符时,比较难以在最后插入字符,所以在点击时,自动添加一个空的p标签 - domUtils.on(me.body, "dblclick", function(e) { - try { - var node = me.body.lastChild; - if (!node) { - return; - } - var rect = node.getBoundingClientRect(); - if (e.clientY > rect.top + rect.height) { - var p = document.createElement('p'); - p.innerHTML = '
'; - me.body.appendChild(p); - setTimeout(function () { - me.focus(true); - }, 100); - } - } catch (e) { - console.error('auto insert p at end', e); - } - }); - domUtils.on(doc, ["mouseup", "keydown"], function(evt) { - //特殊键不触发selectionchange - if ( - evt.type === "keydown" && - (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey) - ) { - return; - } - if (evt.button === 2) return; - me._selectionChange(250, evt); - }); - }, - /** - * 触发事件代理 - * @method _proxyDomEvent - * @private - * @return { * } fireEvent的返回值 - * @see UE.EventBase:fireEvent(String) - */ - _proxyDomEvent: function(evt) { - if ( - this.fireEvent("before" + evt.type.replace(/^on/, "").toLowerCase()) === - false - ) { - return false; - } - if (this.fireEvent(evt.type.replace(/^on/, ""), evt) === false) { - return false; - } - return this.fireEvent( - "after" + evt.type.replace(/^on/, "").toLowerCase() - ); - }, - /** - * 变化选区 - * @method _selectionChange - * @private - */ - _selectionChange: function(delay, evt) { - var me = this; - //有光标才做selectionchange 为了解决未focus时点击source不能触发更改工具栏状态的问题(source命令notNeedUndo=1) - // if ( !me.selection.isFocus() ){ - // return; - // } - - var hackForMouseUp = false; - var mouseX, mouseY; - if (browser.ie && browser.version < 9 && evt && evt.type == "mouseup") { - var range = this.selection.getRange(); - if (!range.collapsed) { - hackForMouseUp = true; - mouseX = evt.clientX; - mouseY = evt.clientY; - } - } - clearTimeout(_selectionChangeTimer); - _selectionChangeTimer = setTimeout(function() { - if (!me.selection || !me.selection.getNative()) { - return; - } - //修复一个IE下的bug: 鼠标点击一段已选择的文本中间时,可能在mouseup后的一段时间内取到的range是在selection的type为None下的错误值. - //IE下如果用户是拖拽一段已选择文本,则不会触发mouseup事件,所以这里的特殊处理不会对其有影响 - var ieRange; - if (hackForMouseUp && me.selection.getNative().type == "None") { - ieRange = me.document.body.createTextRange(); - try { - ieRange.moveToPoint(mouseX, mouseY); - } catch (ex) { - ieRange = null; - } - } - var bakGetIERange; - if (ieRange) { - bakGetIERange = me.selection.getIERange; - me.selection.getIERange = function() { - return ieRange; - }; - } - me.selection.cache(); - if (bakGetIERange) { - me.selection.getIERange = bakGetIERange; - } - if (me.selection._cachedRange && me.selection._cachedStartElement) { - me.fireEvent("beforeselectionchange"); - // 第二个参数causeByUi为true代表由用户交互造成的selectionchange. - me.fireEvent("selectionchange", !!evt); - me.fireEvent("afterselectionchange"); - me.selection.clear(); - } - }, delay || 50); - }, - - /** - * 执行编辑命令 - * @method _callCmdFn - * @private - * @param { String } fnName 函数名称 - * @param { * } args 传给命令函数的参数 - * @return { * } 返回命令函数运行的返回值 - */ - _callCmdFn: function(fnName, args) { - var cmdName = args[0].toLowerCase(), - cmd, - cmdFn; - cmd = this.commands[cmdName] || UE.commands[cmdName]; - cmdFn = cmd && cmd[fnName]; - //没有querycommandstate或者没有command的都默认返回0 - if ((!cmd || !cmdFn) && fnName == "queryCommandState") { - return 0; - } else if (cmdFn) { - return cmdFn.apply(this, args); - } - }, - - /** - * 执行编辑命令cmdName,完成富文本编辑效果 - * @method execCommand - * @param { String } cmdName 需要执行的命令 - * @remind 具体命令的使用请参考命令列表 - * @return { * } 返回命令函数运行的返回值 - * @example - * ```javascript - * editor.execCommand(cmdName); - * ``` - */ - execCommand: function(cmdName) { - cmdName = cmdName.toLowerCase(); - var me = this, - result, - cmd = me.commands[cmdName] || UE.commands[cmdName]; - if (!cmd || !cmd.execCommand) { - return null; - } - if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) { - me.__hasEnterExecCommand = true; - if (me.queryCommandState.apply(me, arguments) != -1) { - me.fireEvent("saveScene"); - me.fireEvent.apply( - me, - ["beforeexeccommand", cmdName].concat(arguments) - ); - result = this._callCmdFn("execCommand", arguments); - //保存场景时,做了内容对比,再看是否进行contentchange触发,这里多触发了一次,去掉 - // (!cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange'); - me.fireEvent.apply( - me, - ["afterexeccommand", cmdName].concat(arguments) - ); - me.fireEvent("saveScene"); - } - me.__hasEnterExecCommand = false; - } else { - result = this._callCmdFn("execCommand", arguments); - !me.__hasEnterExecCommand && - !cmd.ignoreContentChange && - !me._ignoreContentChange && - me.fireEvent("contentchange"); - } - !me.__hasEnterExecCommand && - !cmd.ignoreContentChange && - !me._ignoreContentChange && - me._selectionChange(); - return result; - }, - - /** - * 根据传入的command命令,查选编辑器当前的选区,返回命令的状态 - * @method queryCommandState - * @param { String } cmdName 需要查询的命令名称 - * @remind 具体命令的使用请参考命令列表 - * @return { Number } number 返回放前命令的状态,返回值三种情况:(-1|0|1) - * @example - * ```javascript - * editor.queryCommandState(cmdName) => (-1|0|1) - * ``` - * @see COMMAND.LIST - */ - queryCommandState: function(cmdName) { - return this._callCmdFn("queryCommandState", arguments); - }, - - /** - * 根据传入的command命令,查选编辑器当前的选区,根据命令返回相关的值 - * @method queryCommandValue - * @param { String } cmdName 需要查询的命令名称 - * @remind 具体命令的使用请参考命令列表 - * @remind 只有部分插件有此方法 - * @return { * } 返回每个命令特定的当前状态值 - * @grammar editor.queryCommandValue(cmdName) => {*} - * @see COMMAND.LIST - */ - queryCommandValue: function(cmdName) { - return this._callCmdFn("queryCommandValue", arguments); - }, - - /** - * 检查编辑区域中是否有内容 - * @method hasContents - * @remind 默认有文本内容,或者有以下节点都不认为是空 - * table,ul,ol,dl,iframe,area,base,col,hr,img,embed,input,link,meta,param - * @return { Boolean } 检查有内容返回true,否则返回false - * @example - * ```javascript - * editor.hasContents() - * ``` - */ - - /** - * 检查编辑区域中是否有内容,若包含参数tags中的节点类型,直接返回true - * @method hasContents - * @param { Array } tags 传入数组判断时用到的节点类型 - * @return { Boolean } 若文档中包含tags数组里对应的tag,返回true,否则返回false - * @example - * ```javascript - * editor.hasContents(['span']); - * ``` - */ - hasContents: function(tags) { - if (tags) { - for (var i = 0, ci; (ci = tags[i++]); ) { - if (this.document.getElementsByTagName(ci).length > 0) { - return true; - } - } - } - if (!domUtils.isEmptyBlock(this.body)) { - return true; - } - // 随时添加,定义的特殊标签如果存在,不能认为是空 - tags = ["div"]; - for (i = 0; (ci = tags[i++]); ) { - var nodes = domUtils.getElementsByTagName(this.document, ci); - for (var n = 0, cn; (cn = nodes[n++]); ) { - if (domUtils.isCustomeNode(cn)) { - return true; - } - } - } - // 部分如媒体标签,不能认为为空 - tags = [ "video","iframe" ] - for (i = 0; (ci = tags[i++]); ) { - var nodes = domUtils.getElementsByTagName(this.document, ci); - for (var n = 0, cn; (cn = nodes[n++]); ) { - return true; - } - } - return false; - }, - - /** - * 重置编辑器,可用来做多个tab使用同一个编辑器实例 - * @method reset - * @remind 此方法会清空编辑器内容,清空回退列表,会触发reset事件 - * @example - * ```javascript - * editor.reset() - * ``` - */ - reset: function() { - this.fireEvent("reset"); - }, - - /** - * 设置当前编辑区域可以编辑 - * @method setEnabled - * @example - * ```javascript - * editor.setEnabled() - * ``` - */ - setEnabled: function() { - var me = this, - range; - if (me.body.contentEditable === "false") { - me.body.contentEditable = true; - range = me.selection.getRange(); - //有可能内容丢失了 - try { - range.moveToBookmark(me.lastBk); - delete me.lastBk; - } catch (e) { - range.setStartAtFirst(me.body).collapse(true); - } - range.select(true); - if (me.bkqueryCommandState) { - me.queryCommandState = me.bkqueryCommandState; - delete me.bkqueryCommandState; - } - if (me.bkqueryCommandValue) { - me.queryCommandValue = me.bkqueryCommandValue; - delete me.bkqueryCommandValue; - } - me.fireEvent("selectionchange"); - } - }, - enable: function() { - return this.setEnabled(); - }, - - /** 设置当前编辑区域不可编辑 - * @method setDisabled - */ - - /** 设置当前编辑区域不可编辑,except中的命令除外 - * @method setDisabled - * @param { String } except 例外命令的字符串 - * @remind 即使设置了disable,此处配置的例外命令仍然可以执行 - * @example - * ```javascript - * editor.setDisabled('bold'); //禁用工具栏中除加粗之外的所有功能 - * ``` - */ - - /** 设置当前编辑区域不可编辑,except中的命令除外 - * @method setDisabled - * @param { Array } except 例外命令的字符串数组,数组中的命令仍然可以执行 - * @remind 即使设置了disable,此处配置的例外命令仍然可以执行 - * @example - * ```javascript - * editor.setDisabled(['bold','insertimage']); //禁用工具栏中除加粗和插入图片之外的所有功能 - * ``` - */ - setDisabled: function(except) { - var me = this; - except = except ? (utils.isArray(except) ? except : [except]) : []; - if (me.body.contentEditable == "true") { - if (!me.lastBk) { - me.lastBk = me.selection.getRange().createBookmark(true); - } - me.body.contentEditable = false; - me.bkqueryCommandState = me.queryCommandState; - me.bkqueryCommandValue = me.queryCommandValue; - me.queryCommandState = function(type) { - if (utils.indexOf(except, type) != -1) { - return me.bkqueryCommandState.apply(me, arguments); - } - return -1; }; - me.queryCommandValue = function(type) { - if (utils.indexOf(except, type) != -1) { - return me.bkqueryCommandValue.apply(me, arguments); - } - return null; - }; - me.fireEvent("selectionchange"); - } - }, - disable: function(except) { - return this.setDisabled(except); - }, - - /** - * 设置默认内容 - * @method _setDefaultContent - * @private - * @param { String } cont 要存入的内容 - */ - _setDefaultContent: (function() { - function clear() { - var me = this; - if (me.document.getElementById("initContent")) { - me.body.innerHTML = "

" + (ie ? "" : "
") + "

"; - me.removeListener("firstBeforeExecCommand focus", clear); - setTimeout(function() { - me.focus(); - me._selectionChange(); - }, 0); - } - } - - return function(cont) { - var me = this; - me.body.innerHTML = '

' + cont + "

"; - - me.addListener("firstBeforeExecCommand focus", clear); - }; - })(), - - /** - * 显示编辑器 - * @method setShow - * @example - * ```javascript - * editor.setShow() - * ``` - */ - setShow: function() { - var me = this, - range = me.selection.getRange(); - if (me.container.style.display == "none") { - //有可能内容丢失了 - try { - range.moveToBookmark(me.lastBk); - delete me.lastBk; - } catch (e) { - range.setStartAtFirst(me.body).collapse(true); - } - //ie下focus实效,所以做了个延迟 - setTimeout(function() { - range.select(true); - }, 100); - me.container.style.display = ""; - } - }, - show: function() { - return this.setShow(); - }, - /** - * 隐藏编辑器 - * @method setHide - * @example - * ```javascript - * editor.setHide() - * ``` - */ - setHide: function() { - var me = this; - if (!me.lastBk) { - me.lastBk = me.selection.getRange().createBookmark(true); - } - me.container.style.display = "none"; - }, - hide: function() { - return this.setHide(); - }, - - /** - * 根据指定的路径,获取对应的语言资源 - * @method getLang - * @param { String } path 路径根据的是lang目录下的语言文件的路径结构 - * @return { Object | String } 根据路径返回语言资源的Json格式对象或者语言字符串 - * @example - * ```javascript - * editor.getLang('contextMenu.delete'); //如果当前是中文,那返回是的是'删除' - * ``` - */ - getLang: function(path) { - var lang = UE.I18N[this.options.lang]; - if (!lang) { - throw Error("not import language file"); - } - path = (path || "").split("."); - for (var i = 0, ci; (ci = path[i++]); ) { - lang = lang[ci]; - if (!lang) break; - } - return lang; - }, - - /** - * 计算编辑器html内容字符串的长度 - * @method getContentLength - * @return { Number } 返回计算的长度 - * @example - * ```javascript - * //编辑器html内容

132

- * editor.getContentLength() //返回27 - * ``` - */ - /** - * 计算编辑器当前纯文本内容的长度 - * @method getContentLength - * @param { Boolean } ingoneHtml 传入true时,只按照纯文本来计算 - * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签,长度加1 - * @example - * ```javascript - * //编辑器html内容

132

- * editor.getContentLength() //返回3 - * ``` - */ - getContentLength: function(ingoneHtml, tagNames) { - var count = this.getContent(false, false, true).length; - if (ingoneHtml) { - tagNames = (tagNames || []).concat(["hr", "img", "iframe"]); - count = this.getContentTxt().replace(/[\t\r\n]+/g, "").length; - for (var i = 0, ci; (ci = tagNames[i++]); ) { - count += this.document.getElementsByTagName(ci).length; - } - } - return count; - }, - - /** - * 注册输入过滤规则 - * @method addInputRule - * @param { Function } rule 要添加的过滤规则 - * @example - * ```javascript - * editor.addInputRule(function(root){ - * $.each(root.getNodesByTagName('div'),function(i,node){ - * node.tagName="p"; - * }); - * }); - * ``` - */ - addInputRule: function(rule) { - this.inputRules.push(rule); - }, - - /** - * 执行注册的过滤规则 - * @method filterInputRule - * @param { UE.uNode } root 要过滤的uNode节点 - * @remind 执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数 - * @example - * ```javascript - * editor.filterInputRule(editor.body); - * ``` - * @see UE.Editor:addInputRule - */ - filterInputRule: function(root) { - for (var i = 0, ci; (ci = this.inputRules[i++]); ) { - ci.call(this, root); - } - }, - - /** - * 注册输出过滤规则 - * @method addOutputRule - * @param { Function } rule 要添加的过滤规则 - * @example - * ```javascript - * editor.addOutputRule(function(root){ - * $.each(root.getNodesByTagName('p'),function(i,node){ - * node.tagName="div"; - * }); - * }); - * ``` - */ - addOutputRule: function(rule) { - this.outputRules.push(rule); - }, - - /** - * 根据输出过滤规则,过滤编辑器内容 - * @method filterOutputRule - * @remind 执行editor.getContent方法的时候,会先运行该过滤函数 - * @param { UE.uNode } root 要过滤的uNode节点 - * @example - * ```javascript - * editor.filterOutputRule(editor.body); - * ``` - * @see UE.Editor:addOutputRule - */ - filterOutputRule: function(root) { - for (var i = 0, ci; (ci = this.outputRules[i++]); ) { - ci.call(this, root); - } - }, - - /** - * 根据action名称获取请求的路径 - * @method getActionUrl - * @remind 假如没有设置serverUrl,会根据imageUrl设置默认的controller路径 - * @param { String } action action名称 - * @example - * ```javascript - * editor.getActionUrl('config'); //返回 "/ueditor/php/controller.php?action=config" - * editor.getActionUrl('image'); //返回 "/ueditor/php/controller.php?action=uplaodimage" - * editor.getActionUrl('scrawl'); //返回 "/ueditor/php/controller.php?action=uplaodscrawl" - * editor.getActionUrl('imageManager'); //返回 "/ueditor/php/controller.php?action=listimage" - * ``` - */ - getActionUrl: function(action) { - var actionName = this.getOpt(action) || action, - imageUrl = this.getOpt("imageUrl"), - serverUrl = this.getOpt("serverUrl"); - - if (!serverUrl && imageUrl) { - serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, "$1controller$2"); - } - - if (serverUrl) { - serverUrl = - serverUrl + - (serverUrl.indexOf("?") == -1 ? "?" : "&") + - "action=" + - (actionName || ""); - return utils.formatUrl(serverUrl); - } else { - return ""; - } - } - }; - utils.inherits(Editor, EventBase); -})(); + utils.inherits(Editor, EventBase); + })(); // core/Editor.defaultoptions.js //维护编辑器一下默认的不在插件中的配置项 -UE.Editor.defaultOptions = function(editor) { - var _url = editor.options.UEDITOR_HOME_URL; - return { - isShow: true, - initialContent: "", - initialStyle: "", - autoClearinitialContent: false, - iframeCssUrl: _url + "themes/iframe.css?20221113", - iframeCssUrlsAddition: [], - textarea: "editorValue", - focus: false, - focusInEnd: true, - autoClearEmptyNode: true, - fullscreen: false, - readonly: false, - zIndex: 999, - imagePopup: true, - enterTag: "p", - customDomain: false, - lang: "zh-cn", - langPath: _url + "lang/", - theme: "default", - themePath: _url + "themes/", - allHtmlEnabled: false, - scaleEnabled: false, - tableNativeEditInFF: false, - autoSyncData: true, - fileNameFormat: "{time}{rand:6}" - }; -}; + UE.Editor.defaultOptions = function (editor) { + var _url = editor.options.UEDITOR_HOME_URL; + return { + isShow: true, + initialContent: "", + initialStyle: "", + autoClearinitialContent: false, + iframeCssUrl: _url + "themes/iframe.css?c20ec247", + iframeCssUrlsAddition: [], + textarea: '', + focus: false, + focusInEnd: true, + autoClearEmptyNode: true, + fullscreen: false, + readonly: false, + zIndex: 999, + imagePopup: true, + enterTag: "p", + customDomain: false, + lang: "zh-cn", + langPath: _url + "lang/", + theme: "default", + themePath: _url + "themes/", + allHtmlEnabled: false, + scaleEnabled: false, + tableNativeEditInFF: false, + autoSyncData: true, + fileNameFormat: "{time}{rand:6}" + }; + }; // core/loadconfig.js -(function () { - UE.Editor.prototype.loadServerConfig = function () { - var me = this; - setTimeout(function () { - try { - me.options.imageUrl && - me.setOpt( - "serverUrl", - me.options.imageUrl.replace( - /^(.*[\/]).+([\.].+)$/, - "$1controller$2" - ) - ); + (function () { + UE.Editor.prototype.loadServerConfig = function () { + var me = this; + setTimeout(function () { - var configUrl = me.getActionUrl("config"), - isJsonp = utils.isCrossDomainUrl(configUrl); + if(me.options.loadConfigFromServer===false){ + return; + } - /* 发出ajax请求 */ - me._serverConfigLoaded = false; + try { + me.options.imageUrl && + me.setOpt( + "serverUrl", + me.options.imageUrl.replace( + /^(.*[\/]).+([\.].+)$/, + "$1controller$2" + ) + ); - configUrl && - UE.ajax.request(configUrl, { - method: "GET", - dataType: isJsonp ? "jsonp" : "", - headers: me.options.serverHeaders || {}, - onsuccess: function (r) { - try { - var config = isJsonp ? r : eval("(" + r.responseText + ")"); - // console.log('me.options.before', me.options.audioConfig); - me.options = utils.merge(me.options, config); - // console.log('server.config', config.audioConfig); - // console.log('me.options.after', me.options.audioConfig); - me.fireEvent("serverConfigLoaded"); - me._serverConfigLoaded = true; - } catch (e) { - showErrorMsg(me.getLang("loadconfigFormatError")); + var configUrl = me.getActionUrl("config"), + isJsonp = utils.isCrossDomainUrl(configUrl); + + /* 发出ajax请求 */ + me._serverConfigLoaded = false; + + configUrl && + UE.ajax.request(configUrl, { + method: "GET", + dataType: isJsonp ? "jsonp" : "", + headers: me.options.serverHeaders || {}, + onsuccess: function (r) { + try { + var config = isJsonp ? r : eval("(" + r.responseText + ")"); + config = me.options.serverResponsePrepare( config ) + // console.log('me.options.before', me.options.audioConfig); + me.options = utils.merge(me.options, config); + // console.log('server.config', config.audioConfig); + // console.log('me.options.after', me.options.audioConfig); + me.fireEvent("serverConfigLoaded"); + me._serverConfigLoaded = true; + } catch (e) { + showErrorMsg(me.getLang("loadconfigFormatError")); + } + }, + onerror: function () { + showErrorMsg(me.getLang("loadconfigHttpError")); } - }, - onerror: function () { - showErrorMsg(me.getLang("loadconfigHttpError")); - } - }); - } catch (e) { - showErrorMsg(me.getLang("loadconfigError")); + }); + + + } catch (e) { + showErrorMsg(me.getLang("loadconfigError")); + } + }); + + function showErrorMsg(msg) { + console && console.error(msg); + //me.fireEvent('showMessage', { + // 'title': msg, + // 'type': 'error' + //}); } - }); - - function showErrorMsg(msg) { - console && console.error(msg); - //me.fireEvent('showMessage', { - // 'title': msg, - // 'type': 'error' - //}); - } - }; - - UE.Editor.prototype.isServerConfigLoaded = function () { - var me = this; - return me._serverConfigLoaded || false; - }; - - UE.Editor.prototype.afterConfigReady = function (handler) { - if (!handler || !utils.isFunction(handler)) return; - var me = this; - var readyHandler = function () { - handler.apply(me, arguments); - me.removeListener("serverConfigLoaded", readyHandler); }; - if (me.isServerConfigLoaded()) { - handler.call(me, "serverConfigLoaded"); - } else { - me.addListener("serverConfigLoaded", readyHandler); - } - }; -})(); + UE.Editor.prototype.isServerConfigLoaded = function () { + var me = this; + return me._serverConfigLoaded || false; + }; + + UE.Editor.prototype.afterConfigReady = function (handler) { + if (!handler || !utils.isFunction(handler)) return; + var me = this; + var readyHandler = function () { + handler.apply(me, arguments); + me.removeListener("serverConfigLoaded", readyHandler); + }; + + if (me.isServerConfigLoaded()) { + handler.call(me, "serverConfigLoaded"); + } else { + me.addListener("serverConfigLoaded", readyHandler); + } + }; + })(); // core/ajax.js -/** - * @file - * @module UE.ajax - * @since 1.2.6.1 - */ - -/** - * 提供对ajax请求的支持 - * @module UE.ajax - */ -UE.ajax = (function() { - //创建一个ajaxRequest对象 - var fnStr = "XMLHttpRequest()"; - try { - new ActiveXObject("Msxml2.XMLHTTP"); - fnStr = "ActiveXObject('Msxml2.XMLHTTP')"; - } catch (e) { - try { - new ActiveXObject("Microsoft.XMLHTTP"); - fnStr = "ActiveXObject('Microsoft.XMLHTTP')"; - } catch (e) {} - } - var creatAjaxRequest = new Function("return new " + fnStr); - - /** - * 将json参数转化成适合ajax提交的参数列表 - * @param json + /** + * @file + * @module UE.ajax + * @since 1.2.6.1 */ - function json2str(json) { - var strArr = []; - for (var i in json) { - //忽略默认的几个参数 - if ( - i == "method" || - i == "timeout" || - i == "async" || - i == "dataType" || - i == "callback" - ) - continue; - //忽略控制 - if (json[i] == undefined || json[i] == null) continue; - //传递过来的对象和函数不在提交之列 - if ( - !( - (typeof json[i]).toLowerCase() == "function" || - (typeof json[i]).toLowerCase() == "object" - ) - ) { - strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i])); - } else if (utils.isArray(json[i])) { - //支持传数组内容 - for (var j = 0; j < json[i].length; j++) { - strArr.push( - encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]) - ); - } - } - } - return strArr.join("&"); - } - function doAjax(url, ajaxOptions) { - var xhr = creatAjaxRequest(), - //是否超时 - timeIsOut = false, - //默认参数 - defaultAjaxOptions = { - method: "POST", - timeout: 5000, - async: true, - headers: {}, - data: {}, //需要传递对象的话只能覆盖 - onsuccess: function() {}, - onerror: function() {} - }; - - if (typeof url === "object") { - ajaxOptions = url; - url = ajaxOptions.url; - } - if (!xhr || !url) return; - var ajaxOpts = ajaxOptions - ? utils.extend(defaultAjaxOptions, ajaxOptions) - : defaultAjaxOptions; - - // console.log('ajaxOpts',ajaxOpts); - - var submitStr = json2str(ajaxOpts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" - //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 - if (!utils.isEmptyObject(ajaxOpts.data)) { - submitStr += (submitStr ? "&" : "") + json2str(ajaxOpts.data); - } - //超时检测 - var timerID = setTimeout(function() { - if (xhr.readyState !== 4) { - timeIsOut = true; - xhr.abort(); - clearTimeout(timerID); - } - }, ajaxOpts.timeout); - - var method = ajaxOpts.method.toUpperCase(); - var str = - url + - (url.indexOf("?") === -1 ? "?" : "&") + - (method === "POST" ? "" : submitStr + "&noCache=" + +new Date()); - xhr.open(method, str, ajaxOpts.async); - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (!timeIsOut && xhr.status === 200) { - ajaxOpts.onsuccess(xhr); - } else { - ajaxOpts.onerror(xhr); - } - } - }; - if(ajaxOpts.headers){ - for(var key in ajaxOpts.headers){ - xhr.setRequestHeader(key,ajaxOpts.headers[key]); - } - } - if (method === "POST") { - xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - xhr.send(submitStr); - } else { - xhr.send(null); - } - } - - function doJsonp(url, opts) { - var successhandler = opts.onsuccess || function() {}, - scr = document.createElement("SCRIPT"), - options = opts || {}, - charset = options["charset"], - callbackField = options["jsonp"] || "callback", - callbackFnName, - timeOut = options["timeOut"] || 0, - timer, - reg = new RegExp("(\\?|&)" + callbackField + "=([^&]*)"), - matches; - - if (utils.isFunction(successhandler)) { - callbackFnName = - "bd__editor__" + Math.floor(Math.random() * 2147483648).toString(36); - window[callbackFnName] = getCallBack(0); - } else if (utils.isString(successhandler)) { - callbackFnName = successhandler; - } else { - if ((matches = reg.exec(url))) { - callbackFnName = matches[2]; - } - } - - url = url.replace(reg, "\x241" + callbackField + "=" + callbackFnName); - - if (url.search(reg) < 0) { - url += - (url.indexOf("?") < 0 ? "?" : "&") + - callbackField + - "=" + - callbackFnName; - } - - var queryStr = json2str(opts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" - //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 - if (!utils.isEmptyObject(opts.data)) { - queryStr += (queryStr ? "&" : "") + json2str(opts.data); - } - if (queryStr) { - url = url.replace(/\?/, "?" + queryStr + "&"); - } - - scr.onerror = getCallBack(1); - if (timeOut) { - timer = setTimeout(getCallBack(1), timeOut); - } - createScriptTag(scr, url, charset); - - function createScriptTag(scr, url, charset) { - scr.setAttribute("type", "text/javascript"); - scr.setAttribute("defer", "defer"); - charset && scr.setAttribute("charset", charset); - scr.setAttribute("src", url); - document.getElementsByTagName("head")[0].appendChild(scr); - } - - function getCallBack(onTimeOut) { - return function() { + /** + * 提供对ajax请求的支持 + * @module UE.ajax + */ + UE.ajax = (function () { + //创建一个ajaxRequest对象 + var fnStr = "XMLHttpRequest()"; try { - if (onTimeOut) { - options.onerror && options.onerror(); - } else { + new ActiveXObject("Msxml2.XMLHTTP"); + fnStr = "ActiveXObject('Msxml2.XMLHTTP')"; + } catch (e) { try { - clearTimeout(timer); - successhandler.apply(window, arguments); - } catch (e) {} - } - } catch (exception) { - options.onerror && options.onerror.call(window, exception); - } finally { - options.oncomplete && options.oncomplete.apply(window, arguments); - scr.parentNode && scr.parentNode.removeChild(scr); - window[callbackFnName] = null; - try { - delete window[callbackFnName]; - } catch (e) {} + new ActiveXObject("Microsoft.XMLHTTP"); + fnStr = "ActiveXObject('Microsoft.XMLHTTP')"; + } catch (e) { + } } - }; - } - } + var creatAjaxRequest = new Function("return new " + fnStr); - return { - /** - * 根据给定的参数项,向指定的url发起一个ajax请求。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求 - * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调 - * @method request - * @param { URLString } url ajax请求的url地址 - * @param { Object } ajaxOptions ajax请求选项的键值对,支持的选项如下: - * @example - * ```javascript - * //向sayhello.php发起一个异步的Ajax GET请求, 请求超时时间为10s, 请求完成后执行相应的回调。 - * UE.ajax.requeset( 'sayhello.php', { - * - * //请求方法。可选值: 'GET', 'POST',默认值是'POST' - * method: 'GET', - * - * //超时时间。 默认为5000, 单位是ms - * timeout: 10000, - * - * //是否是异步请求。 true为异步请求, false为同步请求 - * async: true, - * - * //请求携带的数据。如果请求为GET请求, data会经过stringify后附加到请求url之后。 - * data: { - * name: 'ueditor' - * }, - * - * //请求成功后的回调, 该回调接受当前的XMLHttpRequest对象作为参数。 - * onsuccess: function ( xhr ) { - * console.log( xhr.responseText ); - * }, - * - * //请求失败或者超时后的回调。 - * onerror: function ( xhr ) { - * alert( 'Ajax请求失败' ); - * } - * - * } ); - * ``` + /** + * 将json参数转化成适合ajax提交的参数列表 + * @param json */ + function json2str(json) { + var strArr = []; + for (var i in json) { + //忽略默认的几个参数 + if ( + i == "method" || + i == "timeout" || + i == "async" || + i == "dataType" || + i == "callback" + ) + continue; + //忽略控制 + if (json[i] == undefined || json[i] == null) continue; + //传递过来的对象和函数不在提交之列 + if ( + !( + (typeof json[i]).toLowerCase() == "function" || + (typeof json[i]).toLowerCase() == "object" + ) + ) { + strArr.push(encodeURIComponent(i) + "=" + encodeURIComponent(json[i])); + } else if (utils.isArray(json[i])) { + //支持传数组内容 + for (var j = 0; j < json[i].length; j++) { + strArr.push( + encodeURIComponent(i) + "[]=" + encodeURIComponent(json[i][j]) + ); + } + } + } + return strArr.join("&"); + } - /** - * 根据给定的参数项发起一个ajax请求, 参数项里必须包含一个url地址。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求 - * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调。 - * @method request - * @warning 如果在参数项里未提供一个key为“url”的地址值,则该请求将直接退出。 - * @param { Object } ajaxOptions ajax请求选项的键值对,支持的选项如下: - * @example - * ```javascript - * - * //向sayhello.php发起一个异步的Ajax POST请求, 请求超时时间为5s, 请求完成后不执行任何回调。 - * UE.ajax.requeset( 'sayhello.php', { - * - * //请求的地址, 该项是必须的。 - * url: 'sayhello.php' - * - * } ); - * ``` - */ - request: function(url, opts) { - if (opts && opts.dataType === "jsonp") { - doJsonp(url, opts); - } else { - doAjax(url, opts); - } - }, - getJSONP: function(url, data, fn) { - var opts = { - data: data, - oncomplete: fn - }; - doJsonp(url, opts); - } - }; -})(); + function doAjax(url, ajaxOptions) { + var xhr = creatAjaxRequest(), + //是否超时 + timeIsOut = false, + //默认参数 + defaultAjaxOptions = { + method: "POST", + timeout: 5000, + async: true, + headers: {}, + data: {}, //需要传递对象的话只能覆盖 + onsuccess: function () { + }, + onerror: function () { + } + }; + + if (typeof url === "object") { + ajaxOptions = url; + url = ajaxOptions.url; + } + if (!xhr || !url) return; + var ajaxOpts = ajaxOptions + ? utils.extend(defaultAjaxOptions, ajaxOptions) + : defaultAjaxOptions; + + // console.log('ajaxOpts',ajaxOpts); + + var submitStr = json2str(ajaxOpts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" + //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 + if (!utils.isEmptyObject(ajaxOpts.data)) { + submitStr += (submitStr ? "&" : "") + json2str(ajaxOpts.data); + } + //超时检测 + var timerID = setTimeout(function () { + if (xhr.readyState !== 4) { + timeIsOut = true; + xhr.abort(); + clearTimeout(timerID); + } + }, ajaxOpts.timeout); + + var method = ajaxOpts.method.toUpperCase(); + var str = + url + + (url.indexOf("?") === -1 ? "?" : "&") + + (method === "POST" ? "" : submitStr + "&noCache=" + +new Date()); + xhr.open(method, str, ajaxOpts.async); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if (!timeIsOut && xhr.status === 200) { + ajaxOpts.onsuccess(xhr); + } else { + ajaxOpts.onerror(xhr); + } + } + }; + if (ajaxOpts.headers) { + for (var key in ajaxOpts.headers) { + xhr.setRequestHeader(key, ajaxOpts.headers[key]); + } + } + if (method === "POST") { + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xhr.send(submitStr); + } else { + xhr.send(null); + } + } + + function doJsonp(url, opts) { + var successhandler = opts.onsuccess || function () { + }, + scr = document.createElement("SCRIPT"), + options = opts || {}, + charset = options["charset"], + callbackField = options["jsonp"] || "callback", + callbackFnName, + timeOut = options["timeOut"] || 0, + timer, + reg = new RegExp("(\\?|&)" + callbackField + "=([^&]*)"), + matches; + + if (utils.isFunction(successhandler)) { + callbackFnName = + "bd__editor__" + Math.floor(Math.random() * 2147483648).toString(36); + window[callbackFnName] = getCallBack(0); + } else if (utils.isString(successhandler)) { + callbackFnName = successhandler; + } else { + if ((matches = reg.exec(url))) { + callbackFnName = matches[2]; + } + } + + url = url.replace(reg, "\x241" + callbackField + "=" + callbackFnName); + + if (url.search(reg) < 0) { + url += + (url.indexOf("?") < 0 ? "?" : "&") + + callbackField + + "=" + + callbackFnName; + } + + var queryStr = json2str(opts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" + //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 + if (!utils.isEmptyObject(opts.data)) { + queryStr += (queryStr ? "&" : "") + json2str(opts.data); + } + if (queryStr) { + url = url.replace(/\?/, "?" + queryStr + "&"); + } + + scr.onerror = getCallBack(1); + if (timeOut) { + timer = setTimeout(getCallBack(1), timeOut); + } + createScriptTag(scr, url, charset); + + function createScriptTag(scr, url, charset) { + scr.setAttribute("type", "text/javascript"); + scr.setAttribute("defer", "defer"); + charset && scr.setAttribute("charset", charset); + scr.setAttribute("src", url); + document.getElementsByTagName("head")[0].appendChild(scr); + } + + function getCallBack(onTimeOut) { + return function () { + try { + if (onTimeOut) { + options.onerror && options.onerror(); + } else { + try { + clearTimeout(timer); + successhandler.apply(window, arguments); + } catch (e) { + } + } + } catch (exception) { + options.onerror && options.onerror.call(window, exception); + } finally { + options.oncomplete && options.oncomplete.apply(window, arguments); + scr.parentNode && scr.parentNode.removeChild(scr); + window[callbackFnName] = null; + try { + delete window[callbackFnName]; + } catch (e) { + } + } + }; + } + } + + return { + /** + * 根据给定的参数项,向指定的url发起一个ajax请求。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求 + * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调 + * @method request + * @param { URLString } url ajax请求的url地址 + * @param { Object } ajaxOptions ajax请求选项的键值对,支持的选项如下: + * @example + * ```javascript + * //向sayhello.php发起一个异步的Ajax GET请求, 请求超时时间为10s, 请求完成后执行相应的回调。 + * UE.ajax.requeset( 'sayhello.php', { + * + * //请求方法。可选值: 'GET', 'POST',默认值是'POST' + * method: 'GET', + * + * //超时时间。 默认为5000, 单位是ms + * timeout: 10000, + * + * //是否是异步请求。 true为异步请求, false为同步请求 + * async: true, + * + * //请求携带的数据。如果请求为GET请求, data会经过stringify后附加到请求url之后。 + * data: { + * name: 'ueditor' + * }, + * + * //请求成功后的回调, 该回调接受当前的XMLHttpRequest对象作为参数。 + * onsuccess: function ( xhr ) { + * console.log( xhr.responseText ); + * }, + * + * //请求失败或者超时后的回调。 + * onerror: function ( xhr ) { + * alert( 'Ajax请求失败' ); + * } + * + * } ); + * ``` + */ + + /** + * 根据给定的参数项发起一个ajax请求, 参数项里必须包含一个url地址。 ajax请求完成后,会根据请求结果调用相应回调: 如果请求 + * 成功, 则调用onsuccess回调, 失败则调用 onerror 回调。 + * @method request + * @warning 如果在参数项里未提供一个key为“url”的地址值,则该请求将直接退出。 + * @param { Object } ajaxOptions ajax请求选项的键值对,支持的选项如下: + * @example + * ```javascript + * + * //向sayhello.php发起一个异步的Ajax POST请求, 请求超时时间为5s, 请求完成后不执行任何回调。 + * UE.ajax.requeset( 'sayhello.php', { + * + * //请求的地址, 该项是必须的。 + * url: 'sayhello.php' + * + * } ); + * ``` + */ + request: function (url, opts) { + if (opts && opts.dataType === "jsonp") { + doJsonp(url, opts); + } else { + doAjax(url, opts); + } + }, + getJSONP: function (url, data, fn) { + var opts = { + data: data, + oncomplete: fn + }; + doJsonp(url, opts); + } + }; + })(); // core/api.js -UE.api = (function(){ - // axios import - var axios = null; - !function(e,t){axios=t()}(this,(function(){"use strict";function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&void 0!==arguments[2]?arguments[2]:{},a=i.allOwnKeys,s=void 0!==a&&a;if(null!=t)if("object"!==e(t)&&(t=[t]),p(t))for(r=0,o=t.length;r0;)if(t===(n=r[o]).toLowerCase())return n;return null}var N="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,C=function(e){return!h(e)&&e!==N};var x,P=(x="undefined"!=typeof Uint8Array&&c(Uint8Array),function(e){return x&&e instanceof x}),k=l("HTMLFormElement"),U=function(e){var t=Object.prototype.hasOwnProperty;return function(e,n){return t.call(e,n)}}(),_=l("RegExp"),F=function(e,t){var n=Object.getOwnPropertyDescriptors(e),r={};T(n,(function(n,o){!1!==t(n,o,e)&&(r[o]=n)})),Object.defineProperties(e,r)},B="abcdefghijklmnopqrstuvwxyz",L="0123456789",D={DIGIT:L,ALPHA:B,ALPHA_DIGIT:B+B.toUpperCase()+L};var I=l("AsyncFunction"),q={isArray:p,isArrayBuffer:m,isBuffer:function(e){return null!==e&&!h(e)&&null!==e.constructor&&!h(e.constructor)&&v(e.constructor.isBuffer)&&e.constructor.isBuffer(e)},isFormData:function(e){var t;return e&&("function"==typeof FormData&&e instanceof FormData||v(e.append)&&("formdata"===(t=f(e))||"object"===t&&v(e.toString)&&"[object FormData]"===e.toString()))},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&m(e.buffer)},isString:y,isNumber:b,isBoolean:function(e){return!0===e||!1===e},isObject:g,isPlainObject:w,isUndefined:h,isDate:E,isFile:O,isBlob:S,isRegExp:_,isFunction:v,isStream:function(e){return g(e)&&v(e.pipe)},isURLSearchParams:A,isTypedArray:P,isFileList:R,forEach:T,merge:function e(){for(var t=C(this)&&this||{},n=t.caseless,r={},o=function(t,o){var i=n&&j(r,o)||o;w(r[i])&&w(t)?r[i]=e(r[i],t):w(t)?r[i]=e({},t):p(t)?r[i]=t.slice():r[i]=t},i=0,a=arguments.length;i3&&void 0!==arguments[3]?arguments[3]:{},o=r.allOwnKeys;return T(t,(function(t,r){n&&v(t)?e[r]=a(t,n):e[r]=t}),{allOwnKeys:o}),e},trim:function(e){return e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e},inherits:function(e,t,n,r){e.prototype=Object.create(t.prototype,r),e.prototype.constructor=e,Object.defineProperty(e,"super",{value:t.prototype}),n&&Object.assign(e.prototype,n)},toFlatObject:function(e,t,n,r){var o,i,a,s={};if(t=t||{},null==e)return t;do{for(i=(o=Object.getOwnPropertyNames(e)).length;i-- >0;)a=o[i],r&&!r(a,e,t)||s[a]||(t[a]=e[a],s[a]=!0);e=!1!==n&&c(e)}while(e&&(!n||n(e,t))&&e!==Object.prototype);return t},kindOf:f,kindOfTest:l,endsWith:function(e,t,n){e=String(e),(void 0===n||n>e.length)&&(n=e.length),n-=t.length;var r=e.indexOf(t,n);return-1!==r&&r===n},toArray:function(e){if(!e)return null;if(p(e))return e;var t=e.length;if(!b(t))return null;for(var n=new Array(t);t-- >0;)n[t]=e[t];return n},forEachEntry:function(e,t){for(var n,r=(e&&e[Symbol.iterator]).call(e);(n=r.next())&&!n.done;){var o=n.value;t.call(e,o[0],o[1])}},matchAll:function(e,t){for(var n,r=[];null!==(n=e.exec(t));)r.push(n);return r},isHTMLForm:k,hasOwnProperty:U,hasOwnProp:U,reduceDescriptors:F,freezeMethods:function(e){F(e,(function(t,n){if(v(e)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;var r=e[n];v(r)&&(t.enumerable=!1,"writable"in t?t.writable=!1:t.set||(t.set=function(){throw Error("Can not rewrite read-only method '"+n+"'")}))}))},toObjectSet:function(e,t){var n={},r=function(e){e.forEach((function(e){n[e]=!0}))};return p(e)?r(e):r(String(e).split(t)),n},toCamelCase:function(e){return e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(e,t,n){return t.toUpperCase()+n}))},noop:function(){},toFiniteNumber:function(e,t){return e=+e,Number.isFinite(e)?e:t},findKey:j,global:N,isContextDefined:C,ALPHABET:D,generateString:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:16,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:D.ALPHA_DIGIT,n="",r=t.length;e--;)n+=t[Math.random()*r|0];return n},isSpecCompliantForm:function(e){return!!(e&&v(e.append)&&"FormData"===e[Symbol.toStringTag]&&e[Symbol.iterator])},toJSONObject:function(e){var t=new Array(10);return function e(n,r){if(g(n)){if(t.indexOf(n)>=0)return;if(!("toJSON"in n)){t[r]=n;var o=p(n)?[]:{};return T(n,(function(t,n){var i=e(t,r+1);!h(i)&&(o[n]=i)})),t[r]=void 0,o}}return n}(e,0)},isAsyncFn:I,isThenable:function(e){return e&&(g(e)||v(e))&&v(e.then)&&v(e.catch)}};function M(e,t,n,r,o){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack,this.message=e,this.name="AxiosError",t&&(this.code=t),n&&(this.config=n),r&&(this.request=r),o&&(this.response=o)}q.inherits(M,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:q.toJSONObject(this.config),code:this.code,status:this.response&&this.response.status?this.response.status:null}}});var z=M.prototype,H={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((function(e){H[e]={value:e}})),Object.defineProperties(M,H),Object.defineProperty(z,"isAxiosError",{value:!0}),M.from=function(e,t,n,r,o,i){var a=Object.create(z);return q.toFlatObject(e,a,(function(e){return e!==Error.prototype}),(function(e){return"isAxiosError"!==e})),M.call(a,e.message,t,n,r,o),a.cause=e,a.name=e.name,i&&Object.assign(a,i),a};function J(e){return q.isPlainObject(e)||q.isArray(e)}function W(e){return q.endsWith(e,"[]")?e.slice(0,-2):e}function K(e,t,n){return e?e.concat(t).map((function(e,t){return e=W(e),!n&&t?"["+e+"]":e})).join(n?".":""):t}var V=q.toFlatObject(q,{},null,(function(e){return/^is[A-Z]/.test(e)}));function G(t,n,r){if(!q.isObject(t))throw new TypeError("target must be an object");n=n||new FormData;var o=(r=q.toFlatObject(r,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(e,t){return!q.isUndefined(t[e])}))).metaTokens,i=r.visitor||f,a=r.dots,s=r.indexes,u=(r.Blob||"undefined"!=typeof Blob&&Blob)&&q.isSpecCompliantForm(n);if(!q.isFunction(i))throw new TypeError("visitor must be a function");function c(e){if(null===e)return"";if(q.isDate(e))return e.toISOString();if(!u&&q.isBlob(e))throw new M("Blob is not supported. Use a Buffer instead.");return q.isArrayBuffer(e)||q.isTypedArray(e)?u&&"function"==typeof Blob?new Blob([e]):Buffer.from(e):e}function f(t,r,i){var u=t;if(t&&!i&&"object"===e(t))if(q.endsWith(r,"{}"))r=o?r:r.slice(0,-2),t=JSON.stringify(t);else if(q.isArray(t)&&function(e){return q.isArray(e)&&!e.some(J)}(t)||(q.isFileList(t)||q.endsWith(r,"[]"))&&(u=q.toArray(t)))return r=W(r),u.forEach((function(e,t){!q.isUndefined(e)&&null!==e&&n.append(!0===s?K([r],t,a):null===s?r:r+"[]",c(e))})),!1;return!!J(t)||(n.append(K(i,r,a),c(t)),!1)}var l=[],d=Object.assign(V,{defaultVisitor:f,convertValue:c,isVisitable:J});if(!q.isObject(t))throw new TypeError("data must be an object");return function e(t,r){if(!q.isUndefined(t)){if(-1!==l.indexOf(t))throw Error("Circular reference detected in "+r.join("."));l.push(t),q.forEach(t,(function(t,o){!0===(!(q.isUndefined(t)||null===t)&&i.call(n,t,q.isString(o)?o.trim():o,r,d))&&e(t,r?r.concat(o):[o])})),l.pop()}}(t),n}function $(e){var t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,(function(e){return t[e]}))}function X(e,t){this._pairs=[],e&&G(e,this,t)}var Q=X.prototype;function Z(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function Y(e,t,n){if(!t)return e;var r,o=n&&n.encode||Z,i=n&&n.serialize;if(r=i?i(t,n):q.isURLSearchParams(t)?t.toString():new X(t,n).toString(o)){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+r}return e}Q.append=function(e,t){this._pairs.push([e,t])},Q.toString=function(e){var t=e?function(t){return e.call(this,t,$)}:$;return this._pairs.map((function(e){return t(e[0])+"="+t(e[1])}),"").join("&")};var ee,te=function(){function e(){t(this,e),this.handlers=[]}return r(e,[{key:"use",value:function(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}},{key:"eject",value:function(e){this.handlers[e]&&(this.handlers[e]=null)}},{key:"clear",value:function(){this.handlers&&(this.handlers=[])}},{key:"forEach",value:function(e){q.forEach(this.handlers,(function(t){null!==t&&e(t)}))}}]),e}(),ne={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},re={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:X,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},isStandardBrowserEnv:("undefined"==typeof navigator||"ReactNative"!==(ee=navigator.product)&&"NativeScript"!==ee&&"NS"!==ee)&&"undefined"!=typeof window&&"undefined"!=typeof document,isStandardBrowserWebWorkerEnv:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,protocols:["http","https","file","blob","url","data"]};function oe(e){function t(e,n,r,o){var i=e[o++],a=Number.isFinite(+i),s=o>=e.length;return i=!i&&q.isArray(r)?r.length:i,s?(q.hasOwnProp(r,i)?r[i]=[r[i],n]:r[i]=n,!a):(r[i]&&q.isObject(r[i])||(r[i]=[]),t(e,n,r[i],o)&&q.isArray(r[i])&&(r[i]=function(e){var t,n,r={},o=Object.keys(e),i=o.length;for(t=0;t-1,i=q.isObject(e);if(i&&q.isHTMLForm(e)&&(e=new FormData(e)),q.isFormData(e))return o&&o?JSON.stringify(oe(e)):e;if(q.isArrayBuffer(e)||q.isBuffer(e)||q.isStream(e)||q.isFile(e)||q.isBlob(e))return e;if(q.isArrayBufferView(e))return e.buffer;if(q.isURLSearchParams(e))return t.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();if(i){if(r.indexOf("application/x-www-form-urlencoded")>-1)return function(e,t){return G(e,new re.classes.URLSearchParams,Object.assign({visitor:function(e,t,n,r){return re.isNode&&q.isBuffer(e)?(this.append(t,e.toString("base64")),!1):r.defaultVisitor.apply(this,arguments)}},t))}(e,this.formSerializer).toString();if((n=q.isFileList(e))||r.indexOf("multipart/form-data")>-1){var a=this.env&&this.env.FormData;return G(n?{"files[]":e}:e,a&&new a,this.formSerializer)}}return i||o?(t.setContentType("application/json",!1),function(e,t,n){if(q.isString(e))try{return(t||JSON.parse)(e),q.trim(e)}catch(e){if("SyntaxError"!==e.name)throw e}return(n||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){var t=this.transitional||ae.transitional,n=t&&t.forcedJSONParsing,r="json"===this.responseType;if(e&&q.isString(e)&&(n&&!this.responseType||r)){var o=!(t&&t.silentJSONParsing)&&r;try{return JSON.parse(e)}catch(e){if(o){if("SyntaxError"===e.name)throw M.from(e,M.ERR_BAD_RESPONSE,this,null,this.response);throw e}}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:re.classes.FormData,Blob:re.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};q.forEach(["delete","get","head"],(function(e){ae.headers[e]={}})),q.forEach(["post","put","patch"],(function(e){ae.headers[e]=q.merge(ie)}));var se=ae,ue=q.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),ce=Symbol("internals");function fe(e){return e&&String(e).trim().toLowerCase()}function le(e){return!1===e||null==e?e:q.isArray(e)?e.map(le):String(e)}function de(e,t,n,r,o){return q.isFunction(r)?r.call(this,t,n):(o&&(t=n),q.isString(t)?q.isString(r)?-1!==t.indexOf(r):q.isRegExp(r)?r.test(t):void 0:void 0)}var pe=function(e,n){function i(e){t(this,i),e&&this.set(e)}return r(i,[{key:"set",value:function(e,t,n){var r=this;function o(e,t,n){var o=fe(t);if(!o)throw new Error("header name must be a non-empty string");var i=q.findKey(r,o);(!i||void 0===r[i]||!0===n||void 0===n&&!1!==r[i])&&(r[i||t]=le(e))}var i,a,s,u,c,f=function(e,t){return q.forEach(e,(function(e,n){return o(e,n,t)}))};return q.isPlainObject(e)||e instanceof this.constructor?f(e,t):q.isString(e)&&(e=e.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim())?f((c={},(i=e)&&i.split("\n").forEach((function(e){u=e.indexOf(":"),a=e.substring(0,u).trim().toLowerCase(),s=e.substring(u+1).trim(),!a||c[a]&&ue[a]||("set-cookie"===a?c[a]?c[a].push(s):c[a]=[s]:c[a]=c[a]?c[a]+", "+s:s)})),c),t):null!=e&&o(t,e,n),this}},{key:"get",value:function(e,t){if(e=fe(e)){var n=q.findKey(this,e);if(n){var r=this[n];if(!t)return r;if(!0===t)return function(e){for(var t,n=Object.create(null),r=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;t=r.exec(e);)n[t[1]]=t[2];return n}(r);if(q.isFunction(t))return t.call(this,r,n);if(q.isRegExp(t))return t.exec(r);throw new TypeError("parser must be boolean|regexp|function")}}}},{key:"has",value:function(e,t){if(e=fe(e)){var n=q.findKey(this,e);return!(!n||void 0===this[n]||t&&!de(0,this[n],n,t))}return!1}},{key:"delete",value:function(e,t){var n=this,r=!1;function o(e){if(e=fe(e)){var o=q.findKey(n,e);!o||t&&!de(0,n[o],o,t)||(delete n[o],r=!0)}}return q.isArray(e)?e.forEach(o):o(e),r}},{key:"clear",value:function(e){for(var t=Object.keys(this),n=t.length,r=!1;n--;){var o=t[n];e&&!de(0,this[o],o,e,!0)||(delete this[o],r=!0)}return r}},{key:"normalize",value:function(e){var t=this,n={};return q.forEach(this,(function(r,o){var i=q.findKey(n,o);if(i)return t[i]=le(r),void delete t[o];var a=e?function(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(function(e,t,n){return t.toUpperCase()+n}))}(o):String(o).trim();a!==o&&delete t[o],t[a]=le(r),n[a]=!0})),this}},{key:"concat",value:function(){for(var e,t=arguments.length,n=new Array(t),r=0;r1?n-1:0),o=1;o0;){var a=o[i],s=n[a];if(s){var u=t[a],c=void 0===u||s(u,a,t);if(!0!==c)throw new M("option "+a+" must be "+c,M.ERR_BAD_OPTION_VALUE)}else if(!0!==r)throw new M("Unknown option "+a,M.ERR_BAD_OPTION)}},validators:Ce},ke=Pe.validators,Ue=function(){function e(n){t(this,e),this.defaults=n,this.interceptors={request:new te,response:new te}}return r(e,[{key:"request",value:function(e,t){"string"==typeof e?(t=t||{}).url=e:t=e||{};var n,r=t=je(this.defaults,t),o=r.transitional,i=r.paramsSerializer,a=r.headers;void 0!==o&&Pe.assertOptions(o,{silentJSONParsing:ke.transitional(ke.boolean),forcedJSONParsing:ke.transitional(ke.boolean),clarifyTimeoutError:ke.transitional(ke.boolean)},!1),null!=i&&(q.isFunction(i)?t.paramsSerializer={serialize:i}:Pe.assertOptions(i,{encode:ke.function,serialize:ke.function},!0)),t.method=(t.method||this.defaults.method||"get").toLowerCase(),(n=a&&q.merge(a.common,a[t.method]))&&q.forEach(["delete","get","head","post","put","patch","common"],(function(e){delete a[e]})),t.headers=he.concat(n,a);var s=[],u=!0;this.interceptors.request.forEach((function(e){"function"==typeof e.runWhen&&!1===e.runWhen(t)||(u=u&&e.synchronous,s.unshift(e.fulfilled,e.rejected))}));var c,f=[];this.interceptors.response.forEach((function(e){f.push(e.fulfilled,e.rejected)}));var l,d=0;if(!u){var p=[Ae.bind(this),void 0];for(p.unshift.apply(p,s),p.push.apply(p,f),l=p.length,c=Promise.resolve(t);d0;)o._listeners[t](e);o._listeners=null}})),this.promise.then=function(e){var t,n=new Promise((function(e){o.subscribe(e),t=e})).then(e);return n.cancel=function(){o.unsubscribe(t)},n},n((function(e,t,n){o.reason||(o.reason=new ve(e,t,n),r(o.reason))}))}return r(e,[{key:"throwIfRequested",value:function(){if(this.reason)throw this.reason}},{key:"subscribe",value:function(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}},{key:"unsubscribe",value:function(e){if(this._listeners){var t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}}}],[{key:"source",value:function(){var t;return{token:new e((function(e){t=e})),cancel:t}}}]),e}();var Be={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Be).forEach((function(e){var t=o(e,2),n=t[0],r=t[1];Be[r]=n}));var Le=Be;var De=function e(t){var n=new _e(t),r=a(_e.prototype.request,n);return q.extend(r,_e.prototype,n,{allOwnKeys:!0}),q.extend(r,n,null,{allOwnKeys:!0}),r.create=function(n){return e(je(t,n))},r}(se);return De.Axios=_e,De.CanceledError=ve,De.CancelToken=Fe,De.isCancel=ye,De.VERSION=Ne,De.toFormData=G,De.AxiosError=M,De.Cancel=De.CanceledError,De.all=function(e){return Promise.all(e)},De.spread=function(e){return function(t){return e.apply(null,t)}},De.isAxiosError=function(e){return q.isObject(e)&&!0===e.isAxiosError},De.mergeConfig=je,De.AxiosHeaders=he,De.formToJSON=function(e){return oe(q.isHTMLForm(e)?new FormData(e):e)},De.HttpStatusCode=Le,De.default=De,De})); - return { - requestAction: function (me, action, config) { - config.url = me.getOpt('serverUrl'); - config.method = 'post'; - config.params = config.params || {}; - config.params = Object.assign(config.params, me.getOpt('serverparam')); - config.params.action = action; - return this.request(me, config); - }, - request: function (me, config) { - config.headers = config.headers || {}; - var customHeaders = me.getOpt('serverHeaders'); - if (customHeaders) { - for (var key in customHeaders) { - config.headers[key] = customHeaders[key]; + UE.api = (function () { + // axios import + var axios = null; + !function (e, t) { + axios = t() + }(this, (function () { + "use strict"; + + function e(t) { + return e = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { + return typeof e + } : function (e) { + return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e + }, e(t) + } + + function t(e, t) { + if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function") + } + + function n(e, t) { + for (var n = 0; n < t.length; n++) { + var r = t[n]; + r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(e, r.key, r) + } + } + + function r(e, t, r) { + return t && n(e.prototype, t), r && n(e, r), Object.defineProperty(e, "prototype", {writable: !1}), e + } + + function o(e, t) { + return function (e) { + if (Array.isArray(e)) return e + }(e) || function (e, t) { + var n = null == e ? null : "undefined" != typeof Symbol && e[Symbol.iterator] || e["@@iterator"]; + if (null == n) return; + var r, o, i = [], a = !0, s = !1; + try { + for (n = n.call(e); !(a = (r = n.next()).done) && (i.push(r.value), !t || i.length !== t); a = !0) ; + } catch (e) { + s = !0, o = e + } finally { + try { + a || null == n.return || n.return() + } finally { + if (s) throw o + } + } + return i + }(e, t) || function (e, t) { + if (!e) return; + if ("string" == typeof e) return i(e, t); + var n = Object.prototype.toString.call(e).slice(8, -1); + "Object" === n && e.constructor && (n = e.constructor.name); + if ("Map" === n || "Set" === n) return Array.from(e); + if ("Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return i(e, t) + }(e, t) || function () { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") + }() + } + + function i(e, t) { + (null == t || t > e.length) && (t = e.length); + for (var n = 0, r = new Array(t); n < t; n++) r[n] = e[n]; + return r + } + + function a(e, t) { + return function () { + return e.apply(t, arguments) + } + } + + var s, u = Object.prototype.toString, c = Object.getPrototypeOf, f = (s = Object.create(null), function (e) { + var t = u.call(e); + return s[t] || (s[t] = t.slice(8, -1).toLowerCase()) + }), l = function (e) { + return e = e.toLowerCase(), function (t) { + return f(t) === e + } + }, d = function (t) { + return function (n) { + return e(n) === t + } + }, p = Array.isArray, h = d("undefined"); + var m = l("ArrayBuffer"); + var y = d("string"), v = d("function"), b = d("number"), g = function (t) { + return null !== t && "object" === e(t) + }, w = function (e) { + if ("object" !== f(e)) return !1; + var t = c(e); + return !(null !== t && t !== Object.prototype && null !== Object.getPrototypeOf(t) || Symbol.toStringTag in e || Symbol.iterator in e) + }, E = l("Date"), O = l("File"), S = l("Blob"), R = l("FileList"), A = l("URLSearchParams"); + + function T(t, n) { + var r, o, i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}, a = i.allOwnKeys, + s = void 0 !== a && a; + if (null != t) if ("object" !== e(t) && (t = [t]), p(t)) for (r = 0, o = t.length; r < o; r++) n.call(null, t[r], r, t); else { + var u, c = s ? Object.getOwnPropertyNames(t) : Object.keys(t), f = c.length; + for (r = 0; r < f; r++) u = c[r], n.call(null, t[u], u, t) + } + } + + function j(e, t) { + t = t.toLowerCase(); + for (var n, r = Object.keys(e), o = r.length; o-- > 0;) if (t === (n = r[o]).toLowerCase()) return n; + return null + } + + var N = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : "undefined" != typeof window ? window : global, + C = function (e) { + return !h(e) && e !== N + }; + var x, P = (x = "undefined" != typeof Uint8Array && c(Uint8Array), function (e) { + return x && e instanceof x + }), k = l("HTMLFormElement"), U = function (e) { + var t = Object.prototype.hasOwnProperty; + return function (e, n) { + return t.call(e, n) + } + }(), _ = l("RegExp"), F = function (e, t) { + var n = Object.getOwnPropertyDescriptors(e), r = {}; + T(n, (function (n, o) { + !1 !== t(n, o, e) && (r[o] = n) + })), Object.defineProperties(e, r) + }, B = "abcdefghijklmnopqrstuvwxyz", L = "0123456789", + D = {DIGIT: L, ALPHA: B, ALPHA_DIGIT: B + B.toUpperCase() + L}; + var I = l("AsyncFunction"), q = { + isArray: p, + isArrayBuffer: m, + isBuffer: function (e) { + return null !== e && !h(e) && null !== e.constructor && !h(e.constructor) && v(e.constructor.isBuffer) && e.constructor.isBuffer(e) + }, + isFormData: function (e) { + var t; + return e && ("function" == typeof FormData && e instanceof FormData || v(e.append) && ("formdata" === (t = f(e)) || "object" === t && v(e.toString) && "[object FormData]" === e.toString())) + }, + isArrayBufferView: function (e) { + return "undefined" != typeof ArrayBuffer && ArrayBuffer.isView ? ArrayBuffer.isView(e) : e && e.buffer && m(e.buffer) + }, + isString: y, + isNumber: b, + isBoolean: function (e) { + return !0 === e || !1 === e + }, + isObject: g, + isPlainObject: w, + isUndefined: h, + isDate: E, + isFile: O, + isBlob: S, + isRegExp: _, + isFunction: v, + isStream: function (e) { + return g(e) && v(e.pipe) + }, + isURLSearchParams: A, + isTypedArray: P, + isFileList: R, + forEach: T, + merge: function e() { + for (var t = C(this) && this || {}, n = t.caseless, r = {}, o = function (t, o) { + var i = n && j(r, o) || o; + w(r[i]) && w(t) ? r[i] = e(r[i], t) : w(t) ? r[i] = e({}, t) : p(t) ? r[i] = t.slice() : r[i] = t + }, i = 0, a = arguments.length; i < a; i++) arguments[i] && T(arguments[i], o); + return r + }, + extend: function (e, t, n) { + var r = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : {}, o = r.allOwnKeys; + return T(t, (function (t, r) { + n && v(t) ? e[r] = a(t, n) : e[r] = t + }), {allOwnKeys: o}), e + }, + trim: function (e) { + return e.trim ? e.trim() : e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "") + }, + stripBOM: function (e) { + return 65279 === e.charCodeAt(0) && (e = e.slice(1)), e + }, + inherits: function (e, t, n, r) { + e.prototype = Object.create(t.prototype, r), e.prototype.constructor = e, Object.defineProperty(e, "super", {value: t.prototype}), n && Object.assign(e.prototype, n) + }, + toFlatObject: function (e, t, n, r) { + var o, i, a, s = {}; + if (t = t || {}, null == e) return t; + do { + for (i = (o = Object.getOwnPropertyNames(e)).length; i-- > 0;) a = o[i], r && !r(a, e, t) || s[a] || (t[a] = e[a], s[a] = !0); + e = !1 !== n && c(e) + } while (e && (!n || n(e, t)) && e !== Object.prototype); + return t + }, + kindOf: f, + kindOfTest: l, + endsWith: function (e, t, n) { + e = String(e), (void 0 === n || n > e.length) && (n = e.length), n -= t.length; + var r = e.indexOf(t, n); + return -1 !== r && r === n + }, + toArray: function (e) { + if (!e) return null; + if (p(e)) return e; + var t = e.length; + if (!b(t)) return null; + for (var n = new Array(t); t-- > 0;) n[t] = e[t]; + return n + }, + forEachEntry: function (e, t) { + for (var n, r = (e && e[Symbol.iterator]).call(e); (n = r.next()) && !n.done;) { + var o = n.value; + t.call(e, o[0], o[1]) + } + }, + matchAll: function (e, t) { + for (var n, r = []; null !== (n = e.exec(t));) r.push(n); + return r + }, + isHTMLForm: k, + hasOwnProperty: U, + hasOwnProp: U, + reduceDescriptors: F, + freezeMethods: function (e) { + F(e, (function (t, n) { + if (v(e) && -1 !== ["arguments", "caller", "callee"].indexOf(n)) return !1; + var r = e[n]; + v(r) && (t.enumerable = !1, "writable" in t ? t.writable = !1 : t.set || (t.set = function () { + throw Error("Can not rewrite read-only method '" + n + "'") + })) + })) + }, + toObjectSet: function (e, t) { + var n = {}, r = function (e) { + e.forEach((function (e) { + n[e] = !0 + })) + }; + return p(e) ? r(e) : r(String(e).split(t)), n + }, + toCamelCase: function (e) { + return e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, (function (e, t, n) { + return t.toUpperCase() + n + })) + }, + noop: function () { + }, + toFiniteNumber: function (e, t) { + return e = +e, Number.isFinite(e) ? e : t + }, + findKey: j, + global: N, + isContextDefined: C, + ALPHABET: D, + generateString: function () { + for (var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 16, t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : D.ALPHA_DIGIT, n = "", r = t.length; e--;) n += t[Math.random() * r | 0]; + return n + }, + isSpecCompliantForm: function (e) { + return !!(e && v(e.append) && "FormData" === e[Symbol.toStringTag] && e[Symbol.iterator]) + }, + toJSONObject: function (e) { + var t = new Array(10); + return function e(n, r) { + if (g(n)) { + if (t.indexOf(n) >= 0) return; + if (!("toJSON" in n)) { + t[r] = n; + var o = p(n) ? [] : {}; + return T(n, (function (t, n) { + var i = e(t, r + 1); + !h(i) && (o[n] = i) + })), t[r] = void 0, o + } + } + return n + }(e, 0) + }, + isAsyncFn: I, + isThenable: function (e) { + return e && (g(e) || v(e)) && v(e.then) && v(e.catch) + } + }; + + function M(e, t, n, r, o) { + Error.call(this), Error.captureStackTrace ? Error.captureStackTrace(this, this.constructor) : this.stack = (new Error).stack, this.message = e, this.name = "AxiosError", t && (this.code = t), n && (this.config = n), r && (this.request = r), o && (this.response = o) + } + + q.inherits(M, Error, { + toJSON: function () { + return { + message: this.message, + name: this.name, + description: this.description, + number: this.number, + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + config: q.toJSONObject(this.config), + code: this.code, + status: this.response && this.response.status ? this.response.status : null + } + } + }); + var z = M.prototype, H = {}; + ["ERR_BAD_OPTION_VALUE", "ERR_BAD_OPTION", "ECONNABORTED", "ETIMEDOUT", "ERR_NETWORK", "ERR_FR_TOO_MANY_REDIRECTS", "ERR_DEPRECATED", "ERR_BAD_RESPONSE", "ERR_BAD_REQUEST", "ERR_CANCELED", "ERR_NOT_SUPPORT", "ERR_INVALID_URL"].forEach((function (e) { + H[e] = {value: e} + })), Object.defineProperties(M, H), Object.defineProperty(z, "isAxiosError", {value: !0}), M.from = function (e, t, n, r, o, i) { + var a = Object.create(z); + return q.toFlatObject(e, a, (function (e) { + return e !== Error.prototype + }), (function (e) { + return "isAxiosError" !== e + })), M.call(a, e.message, t, n, r, o), a.cause = e, a.name = e.name, i && Object.assign(a, i), a + }; + + function J(e) { + return q.isPlainObject(e) || q.isArray(e) + } + + function W(e) { + return q.endsWith(e, "[]") ? e.slice(0, -2) : e + } + + function K(e, t, n) { + return e ? e.concat(t).map((function (e, t) { + return e = W(e), !n && t ? "[" + e + "]" : e + })).join(n ? "." : "") : t + } + + var V = q.toFlatObject(q, {}, null, (function (e) { + return /^is[A-Z]/.test(e) + })); + + function G(t, n, r) { + if (!q.isObject(t)) throw new TypeError("target must be an object"); + n = n || new FormData; + var o = (r = q.toFlatObject(r, {metaTokens: !0, dots: !1, indexes: !1}, !1, (function (e, t) { + return !q.isUndefined(t[e]) + }))).metaTokens, i = r.visitor || f, a = r.dots, s = r.indexes, + u = (r.Blob || "undefined" != typeof Blob && Blob) && q.isSpecCompliantForm(n); + if (!q.isFunction(i)) throw new TypeError("visitor must be a function"); + + function c(e) { + if (null === e) return ""; + if (q.isDate(e)) return e.toISOString(); + if (!u && q.isBlob(e)) throw new M("Blob is not supported. Use a Buffer instead."); + return q.isArrayBuffer(e) || q.isTypedArray(e) ? u && "function" == typeof Blob ? new Blob([e]) : Buffer.from(e) : e + } + + function f(t, r, i) { + var u = t; + if (t && !i && "object" === e(t)) if (q.endsWith(r, "{}")) r = o ? r : r.slice(0, -2), t = JSON.stringify(t); else if (q.isArray(t) && function (e) { + return q.isArray(e) && !e.some(J) + }(t) || (q.isFileList(t) || q.endsWith(r, "[]")) && (u = q.toArray(t))) return r = W(r), u.forEach((function (e, t) { + !q.isUndefined(e) && null !== e && n.append(!0 === s ? K([r], t, a) : null === s ? r : r + "[]", c(e)) + })), !1; + return !!J(t) || (n.append(K(i, r, a), c(t)), !1) + } + + var l = [], d = Object.assign(V, {defaultVisitor: f, convertValue: c, isVisitable: J}); + if (!q.isObject(t)) throw new TypeError("data must be an object"); + return function e(t, r) { + if (!q.isUndefined(t)) { + if (-1 !== l.indexOf(t)) throw Error("Circular reference detected in " + r.join(".")); + l.push(t), q.forEach(t, (function (t, o) { + !0 === (!(q.isUndefined(t) || null === t) && i.call(n, t, q.isString(o) ? o.trim() : o, r, d)) && e(t, r ? r.concat(o) : [o]) + })), l.pop() + } + }(t), n + } + + function $(e) { + var t = {"!": "%21", "'": "%27", "(": "%28", ")": "%29", "~": "%7E", "%20": "+", "%00": "\0"}; + return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g, (function (e) { + return t[e] + })) + } + + function X(e, t) { + this._pairs = [], e && G(e, this, t) + } + + var Q = X.prototype; + + function Z(e) { + return encodeURIComponent(e).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+").replace(/%5B/gi, "[").replace(/%5D/gi, "]") + } + + function Y(e, t, n) { + if (!t) return e; + var r, o = n && n.encode || Z, i = n && n.serialize; + if (r = i ? i(t, n) : q.isURLSearchParams(t) ? t.toString() : new X(t, n).toString(o)) { + var a = e.indexOf("#"); + -1 !== a && (e = e.slice(0, a)), e += (-1 === e.indexOf("?") ? "?" : "&") + r + } + return e + } + + Q.append = function (e, t) { + this._pairs.push([e, t]) + }, Q.toString = function (e) { + var t = e ? function (t) { + return e.call(this, t, $) + } : $; + return this._pairs.map((function (e) { + return t(e[0]) + "=" + t(e[1]) + }), "").join("&") + }; + var ee, te = function () { + function e() { + t(this, e), this.handlers = [] + } + + return r(e, [{ + key: "use", value: function (e, t, n) { + return this.handlers.push({ + fulfilled: e, + rejected: t, + synchronous: !!n && n.synchronous, + runWhen: n ? n.runWhen : null + }), this.handlers.length - 1 + } + }, { + key: "eject", value: function (e) { + this.handlers[e] && (this.handlers[e] = null) + } + }, { + key: "clear", value: function () { + this.handlers && (this.handlers = []) + } + }, { + key: "forEach", value: function (e) { + q.forEach(this.handlers, (function (t) { + null !== t && e(t) + })) + } + }]), e + }(), ne = {silentJSONParsing: !0, forcedJSONParsing: !0, clarifyTimeoutError: !1}, re = { + isBrowser: !0, + classes: { + URLSearchParams: "undefined" != typeof URLSearchParams ? URLSearchParams : X, + FormData: "undefined" != typeof FormData ? FormData : null, + Blob: "undefined" != typeof Blob ? Blob : null + }, + isStandardBrowserEnv: ("undefined" == typeof navigator || "ReactNative" !== (ee = navigator.product) && "NativeScript" !== ee && "NS" !== ee) && "undefined" != typeof window && "undefined" != typeof document, + isStandardBrowserWebWorkerEnv: "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope && "function" == typeof self.importScripts, + protocols: ["http", "https", "file", "blob", "url", "data"] + }; + + function oe(e) { + function t(e, n, r, o) { + var i = e[o++], a = Number.isFinite(+i), s = o >= e.length; + return i = !i && q.isArray(r) ? r.length : i, s ? (q.hasOwnProp(r, i) ? r[i] = [r[i], n] : r[i] = n, !a) : (r[i] && q.isObject(r[i]) || (r[i] = []), t(e, n, r[i], o) && q.isArray(r[i]) && (r[i] = function (e) { + var t, n, r = {}, o = Object.keys(e), i = o.length; + for (t = 0; t < i; t++) r[n = o[t]] = e[n]; + return r + }(r[i])), !a) + } + + if (q.isFormData(e) && q.isFunction(e.entries)) { + var n = {}; + return q.forEachEntry(e, (function (e, r) { + t(function (e) { + return q.matchAll(/\w+|\[(\w*)]/g, e).map((function (e) { + return "[]" === e[0] ? "" : e[1] || e[0] + })) + }(e), r, n, 0) + })), n + } + return null + } + + var ie = {"Content-Type": void 0}; + var ae = { + transitional: ne, + adapter: ["xhr", "http"], + transformRequest: [function (e, t) { + var n, r = t.getContentType() || "", o = r.indexOf("application/json") > -1, i = q.isObject(e); + if (i && q.isHTMLForm(e) && (e = new FormData(e)), q.isFormData(e)) return o && o ? JSON.stringify(oe(e)) : e; + if (q.isArrayBuffer(e) || q.isBuffer(e) || q.isStream(e) || q.isFile(e) || q.isBlob(e)) return e; + if (q.isArrayBufferView(e)) return e.buffer; + if (q.isURLSearchParams(e)) return t.setContentType("application/x-www-form-urlencoded;charset=utf-8", !1), e.toString(); + if (i) { + if (r.indexOf("application/x-www-form-urlencoded") > -1) return function (e, t) { + return G(e, new re.classes.URLSearchParams, Object.assign({ + visitor: function (e, t, n, r) { + return re.isNode && q.isBuffer(e) ? (this.append(t, e.toString("base64")), !1) : r.defaultVisitor.apply(this, arguments) + } + }, t)) + }(e, this.formSerializer).toString(); + if ((n = q.isFileList(e)) || r.indexOf("multipart/form-data") > -1) { + var a = this.env && this.env.FormData; + return G(n ? {"files[]": e} : e, a && new a, this.formSerializer) + } + } + return i || o ? (t.setContentType("application/json", !1), function (e, t, n) { + if (q.isString(e)) try { + return (t || JSON.parse)(e), q.trim(e) + } catch (e) { + if ("SyntaxError" !== e.name) throw e + } + return (n || JSON.stringify)(e) + }(e)) : e + }], + transformResponse: [function (e) { + var t = this.transitional || ae.transitional, n = t && t.forcedJSONParsing, + r = "json" === this.responseType; + if (e && q.isString(e) && (n && !this.responseType || r)) { + var o = !(t && t.silentJSONParsing) && r; + try { + return JSON.parse(e) + } catch (e) { + if (o) { + if ("SyntaxError" === e.name) throw M.from(e, M.ERR_BAD_RESPONSE, this, null, this.response); + throw e + } + } + } + return e + }], + timeout: 0, + xsrfCookieName: "XSRF-TOKEN", + xsrfHeaderName: "X-XSRF-TOKEN", + maxContentLength: -1, + maxBodyLength: -1, + env: {FormData: re.classes.FormData, Blob: re.classes.Blob}, + validateStatus: function (e) { + return e >= 200 && e < 300 + }, + headers: {common: {Accept: "application/json, text/plain, */*"}} + }; + q.forEach(["delete", "get", "head"], (function (e) { + ae.headers[e] = {} + })), q.forEach(["post", "put", "patch"], (function (e) { + ae.headers[e] = q.merge(ie) + })); + var se = ae, + ue = q.toObjectSet(["age", "authorization", "content-length", "content-type", "etag", "expires", "from", "host", "if-modified-since", "if-unmodified-since", "last-modified", "location", "max-forwards", "proxy-authorization", "referer", "retry-after", "user-agent"]), + ce = Symbol("internals"); + + function fe(e) { + return e && String(e).trim().toLowerCase() + } + + function le(e) { + return !1 === e || null == e ? e : q.isArray(e) ? e.map(le) : String(e) + } + + function de(e, t, n, r, o) { + return q.isFunction(r) ? r.call(this, t, n) : (o && (t = n), q.isString(t) ? q.isString(r) ? -1 !== t.indexOf(r) : q.isRegExp(r) ? r.test(t) : void 0 : void 0) + } + + var pe = function (e, n) { + function i(e) { + t(this, i), e && this.set(e) + } + + return r(i, [{ + key: "set", value: function (e, t, n) { + var r = this; + + function o(e, t, n) { + var o = fe(t); + if (!o) throw new Error("header name must be a non-empty string"); + var i = q.findKey(r, o); + (!i || void 0 === r[i] || !0 === n || void 0 === n && !1 !== r[i]) && (r[i || t] = le(e)) + } + + var i, a, s, u, c, f = function (e, t) { + return q.forEach(e, (function (e, n) { + return o(e, n, t) + })) + }; + return q.isPlainObject(e) || e instanceof this.constructor ? f(e, t) : q.isString(e) && (e = e.trim()) && !/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim()) ? f((c = {}, (i = e) && i.split("\n").forEach((function (e) { + u = e.indexOf(":"), a = e.substring(0, u).trim().toLowerCase(), s = e.substring(u + 1).trim(), !a || c[a] && ue[a] || ("set-cookie" === a ? c[a] ? c[a].push(s) : c[a] = [s] : c[a] = c[a] ? c[a] + ", " + s : s) + })), c), t) : null != e && o(t, e, n), this + } + }, { + key: "get", value: function (e, t) { + if (e = fe(e)) { + var n = q.findKey(this, e); + if (n) { + var r = this[n]; + if (!t) return r; + if (!0 === t) return function (e) { + for (var t, n = Object.create(null), r = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g; t = r.exec(e);) n[t[1]] = t[2]; + return n + }(r); + if (q.isFunction(t)) return t.call(this, r, n); + if (q.isRegExp(t)) return t.exec(r); + throw new TypeError("parser must be boolean|regexp|function") + } + } + } + }, { + key: "has", value: function (e, t) { + if (e = fe(e)) { + var n = q.findKey(this, e); + return !(!n || void 0 === this[n] || t && !de(0, this[n], n, t)) + } + return !1 + } + }, { + key: "delete", value: function (e, t) { + var n = this, r = !1; + + function o(e) { + if (e = fe(e)) { + var o = q.findKey(n, e); + !o || t && !de(0, n[o], o, t) || (delete n[o], r = !0) + } + } + + return q.isArray(e) ? e.forEach(o) : o(e), r + } + }, { + key: "clear", value: function (e) { + for (var t = Object.keys(this), n = t.length, r = !1; n--;) { + var o = t[n]; + e && !de(0, this[o], o, e, !0) || (delete this[o], r = !0) + } + return r + } + }, { + key: "normalize", value: function (e) { + var t = this, n = {}; + return q.forEach(this, (function (r, o) { + var i = q.findKey(n, o); + if (i) return t[i] = le(r), void delete t[o]; + var a = e ? function (e) { + return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g, (function (e, t, n) { + return t.toUpperCase() + n + })) + }(o) : String(o).trim(); + a !== o && delete t[o], t[a] = le(r), n[a] = !0 + })), this + } + }, { + key: "concat", value: function () { + for (var e, t = arguments.length, n = new Array(t), r = 0; r < t; r++) n[r] = arguments[r]; + return (e = this.constructor).concat.apply(e, [this].concat(n)) + } + }, { + key: "toJSON", value: function (e) { + var t = Object.create(null); + return q.forEach(this, (function (n, r) { + null != n && !1 !== n && (t[r] = e && q.isArray(n) ? n.join(", ") : n) + })), t + } + }, { + key: Symbol.iterator, value: function () { + return Object.entries(this.toJSON())[Symbol.iterator]() + } + }, { + key: "toString", value: function () { + return Object.entries(this.toJSON()).map((function (e) { + var t = o(e, 2); + return t[0] + ": " + t[1] + })).join("\n") + } + }, { + key: Symbol.toStringTag, get: function () { + return "AxiosHeaders" + } + }], [{ + key: "from", value: function (e) { + return e instanceof this ? e : new this(e) + } + }, { + key: "concat", value: function (e) { + for (var t = new this(e), n = arguments.length, r = new Array(n > 1 ? n - 1 : 0), o = 1; o < n; o++) r[o - 1] = arguments[o]; + return r.forEach((function (e) { + return t.set(e) + })), t + } + }, { + key: "accessor", value: function (e) { + var t = (this[ce] = this[ce] = {accessors: {}}).accessors, n = this.prototype; + + function r(e) { + var r = fe(e); + t[r] || (!function (e, t) { + var n = q.toCamelCase(" " + t); + ["get", "set", "has"].forEach((function (r) { + Object.defineProperty(e, r + n, { + value: function (e, n, o) { + return this[r].call(this, t, e, n, o) + }, configurable: !0 + }) + })) + }(n, e), t[r] = !0) + } + + return q.isArray(e) ? e.forEach(r) : r(e), this + } + }]), i + }(); + pe.accessor(["Content-Type", "Content-Length", "Accept", "Accept-Encoding", "User-Agent", "Authorization"]), q.freezeMethods(pe.prototype), q.freezeMethods(pe); + var he = pe; + + function me(e, t) { + var n = this || se, r = t || n, o = he.from(r.headers), i = r.data; + return q.forEach(e, (function (e) { + i = e.call(n, i, o.normalize(), t ? t.status : void 0) + })), o.normalize(), i + } + + function ye(e) { + return !(!e || !e.__CANCEL__) + } + + function ve(e, t, n) { + M.call(this, null == e ? "canceled" : e, M.ERR_CANCELED, t, n), this.name = "CanceledError" + } + + q.inherits(ve, M, {__CANCEL__: !0}); + var be = re.isStandardBrowserEnv ? { + write: function (e, t, n, r, o, i) { + var a = []; + a.push(e + "=" + encodeURIComponent(t)), q.isNumber(n) && a.push("expires=" + new Date(n).toGMTString()), q.isString(r) && a.push("path=" + r), q.isString(o) && a.push("domain=" + o), !0 === i && a.push("secure"), document.cookie = a.join("; ") + }, read: function (e) { + var t = document.cookie.match(new RegExp("(^|;\\s*)(" + e + ")=([^;]*)")); + return t ? decodeURIComponent(t[3]) : null + }, remove: function (e) { + this.write(e, "", Date.now() - 864e5) + } + } : { + write: function () { + }, read: function () { + return null + }, remove: function () { + } + }; + + function ge(e, t) { + return e && !/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t) ? function (e, t) { + return t ? e.replace(/\/+$/, "") + "/" + t.replace(/^\/+/, "") : e + }(e, t) : t + } + + var we = re.isStandardBrowserEnv ? function () { + var e, t = /(msie|trident)/i.test(navigator.userAgent), n = document.createElement("a"); + + function r(e) { + var r = e; + return t && (n.setAttribute("href", r), r = n.href), n.setAttribute("href", r), { + href: n.href, + protocol: n.protocol ? n.protocol.replace(/:$/, "") : "", + host: n.host, + search: n.search ? n.search.replace(/^\?/, "") : "", + hash: n.hash ? n.hash.replace(/^#/, "") : "", + hostname: n.hostname, + port: n.port, + pathname: "/" === n.pathname.charAt(0) ? n.pathname : "/" + n.pathname + } + } + + return e = r(window.location.href), function (t) { + var n = q.isString(t) ? r(t) : t; + return n.protocol === e.protocol && n.host === e.host + } + }() : function () { + return !0 + }; + + function Ee(e, t) { + var n = 0, r = function (e, t) { + e = e || 10; + var n, r = new Array(e), o = new Array(e), i = 0, a = 0; + return t = void 0 !== t ? t : 1e3, function (s) { + var u = Date.now(), c = o[a]; + n || (n = u), r[i] = s, o[i] = u; + for (var f = a, l = 0; f !== i;) l += r[f++], f %= e; + if ((i = (i + 1) % e) === a && (a = (a + 1) % e), !(u - n < t)) { + var d = c && u - c; + return d ? Math.round(1e3 * l / d) : void 0 + } + } + }(50, 250); + return function (o) { + var i = o.loaded, a = o.lengthComputable ? o.total : void 0, s = i - n, u = r(s); + n = i; + var c = { + loaded: i, + total: a, + progress: a ? i / a : void 0, + bytes: s, + rate: u || void 0, + estimated: u && a && i <= a ? (a - i) / u : void 0, + event: o + }; + c[t ? "download" : "upload"] = !0, e(c) + } + } + + var Oe = { + http: null, xhr: "undefined" != typeof XMLHttpRequest && function (e) { + return new Promise((function (t, n) { + var r, o = e.data, i = he.from(e.headers).normalize(), a = e.responseType; + + function s() { + e.cancelToken && e.cancelToken.unsubscribe(r), e.signal && e.signal.removeEventListener("abort", r) + } + + q.isFormData(o) && (re.isStandardBrowserEnv || re.isStandardBrowserWebWorkerEnv ? i.setContentType(!1) : i.setContentType("multipart/form-data;", !1)); + var u = new XMLHttpRequest; + if (e.auth) { + var c = e.auth.username || "", + f = e.auth.password ? unescape(encodeURIComponent(e.auth.password)) : ""; + i.set("Authorization", "Basic " + btoa(c + ":" + f)) + } + var l = ge(e.baseURL, e.url); + + function d() { + if (u) { + var r = he.from("getAllResponseHeaders" in u && u.getAllResponseHeaders()); + !function (e, t, n) { + var r = n.config.validateStatus; + n.status && r && !r(n.status) ? t(new M("Request failed with status code " + n.status, [M.ERR_BAD_REQUEST, M.ERR_BAD_RESPONSE][Math.floor(n.status / 100) - 4], n.config, n.request, n)) : e(n) + }((function (e) { + t(e), s() + }), (function (e) { + n(e), s() + }), { + data: a && "text" !== a && "json" !== a ? u.response : u.responseText, + status: u.status, + statusText: u.statusText, + headers: r, + config: e, + request: u + }), u = null + } + } + + if (u.open(e.method.toUpperCase(), Y(l, e.params, e.paramsSerializer), !0), u.timeout = e.timeout, "onloadend" in u ? u.onloadend = d : u.onreadystatechange = function () { + u && 4 === u.readyState && (0 !== u.status || u.responseURL && 0 === u.responseURL.indexOf("file:")) && setTimeout(d) + }, u.onabort = function () { + u && (n(new M("Request aborted", M.ECONNABORTED, e, u)), u = null) + }, u.onerror = function () { + n(new M("Network Error", M.ERR_NETWORK, e, u)), u = null + }, u.ontimeout = function () { + var t = e.timeout ? "timeout of " + e.timeout + "ms exceeded" : "timeout exceeded", + r = e.transitional || ne; + e.timeoutErrorMessage && (t = e.timeoutErrorMessage), n(new M(t, r.clarifyTimeoutError ? M.ETIMEDOUT : M.ECONNABORTED, e, u)), u = null + }, re.isStandardBrowserEnv) { + var p = (e.withCredentials || we(l)) && e.xsrfCookieName && be.read(e.xsrfCookieName); + p && i.set(e.xsrfHeaderName, p) + } + void 0 === o && i.setContentType(null), "setRequestHeader" in u && q.forEach(i.toJSON(), (function (e, t) { + u.setRequestHeader(t, e) + })), q.isUndefined(e.withCredentials) || (u.withCredentials = !!e.withCredentials), a && "json" !== a && (u.responseType = e.responseType), "function" == typeof e.onDownloadProgress && u.addEventListener("progress", Ee(e.onDownloadProgress, !0)), "function" == typeof e.onUploadProgress && u.upload && u.upload.addEventListener("progress", Ee(e.onUploadProgress)), (e.cancelToken || e.signal) && (r = function (t) { + u && (n(!t || t.type ? new ve(null, e, u) : t), u.abort(), u = null) + }, e.cancelToken && e.cancelToken.subscribe(r), e.signal && (e.signal.aborted ? r() : e.signal.addEventListener("abort", r))); + var h, m = (h = /^([-+\w]{1,25})(:?\/\/|:)/.exec(l)) && h[1] || ""; + m && -1 === re.protocols.indexOf(m) ? n(new M("Unsupported protocol " + m + ":", M.ERR_BAD_REQUEST, e)) : u.send(o || null) + })) + } + }; + q.forEach(Oe, (function (e, t) { + if (e) { + try { + Object.defineProperty(e, "name", {value: t}) + } catch (e) { + } + Object.defineProperty(e, "adapterName", {value: t}) + } + })); + var Se = function (e) { + for (var t, n, r = (e = q.isArray(e) ? e : [e]).length, o = 0; o < r && (t = e[o], !(n = q.isString(t) ? Oe[t.toLowerCase()] : t)); o++) ; + if (!n) { + if (!1 === n) throw new M("Adapter ".concat(t, " is not supported by the environment"), "ERR_NOT_SUPPORT"); + throw new Error(q.hasOwnProp(Oe, t) ? "Adapter '".concat(t, "' is not available in the build") : "Unknown adapter '".concat(t, "'")) + } + if (!q.isFunction(n)) throw new TypeError("adapter is not a function"); + return n + }; + + function Re(e) { + if (e.cancelToken && e.cancelToken.throwIfRequested(), e.signal && e.signal.aborted) throw new ve(null, e) + } + + function Ae(e) { + return Re(e), e.headers = he.from(e.headers), e.data = me.call(e, e.transformRequest), -1 !== ["post", "put", "patch"].indexOf(e.method) && e.headers.setContentType("application/x-www-form-urlencoded", !1), Se(e.adapter || se.adapter)(e).then((function (t) { + return Re(e), t.data = me.call(e, e.transformResponse, t), t.headers = he.from(t.headers), t + }), (function (t) { + return ye(t) || (Re(e), t && t.response && (t.response.data = me.call(e, e.transformResponse, t.response), t.response.headers = he.from(t.response.headers))), Promise.reject(t) + })) + } + + var Te = function (e) { + return e instanceof he ? e.toJSON() : e + }; + + function je(e, t) { + t = t || {}; + var n = {}; + + function r(e, t, n) { + return q.isPlainObject(e) && q.isPlainObject(t) ? q.merge.call({caseless: n}, e, t) : q.isPlainObject(t) ? q.merge({}, t) : q.isArray(t) ? t.slice() : t + } + + function o(e, t, n) { + return q.isUndefined(t) ? q.isUndefined(e) ? void 0 : r(void 0, e, n) : r(e, t, n) + } + + function i(e, t) { + if (!q.isUndefined(t)) return r(void 0, t) + } + + function a(e, t) { + return q.isUndefined(t) ? q.isUndefined(e) ? void 0 : r(void 0, e) : r(void 0, t) + } + + function s(n, o, i) { + return i in t ? r(n, o) : i in e ? r(void 0, n) : void 0 + } + + var u = { + url: i, + method: i, + data: i, + baseURL: a, + transformRequest: a, + transformResponse: a, + paramsSerializer: a, + timeout: a, + timeoutMessage: a, + withCredentials: a, + adapter: a, + responseType: a, + xsrfCookieName: a, + xsrfHeaderName: a, + onUploadProgress: a, + onDownloadProgress: a, + decompress: a, + maxContentLength: a, + maxBodyLength: a, + beforeRedirect: a, + transport: a, + httpAgent: a, + httpsAgent: a, + cancelToken: a, + socketPath: a, + responseEncoding: a, + validateStatus: s, + headers: function (e, t) { + return o(Te(e), Te(t), !0) + } + }; + return q.forEach(Object.keys(Object.assign({}, e, t)), (function (r) { + var i = u[r] || o, a = i(e[r], t[r], r); + q.isUndefined(a) && i !== s || (n[r] = a) + })), n + } + + var Ne = "1.4.0", Ce = {}; + ["object", "boolean", "number", "function", "string", "symbol"].forEach((function (t, n) { + Ce[t] = function (r) { + return e(r) === t || "a" + (n < 1 ? "n " : " ") + t + } + })); + var xe = {}; + Ce.transitional = function (e, t, n) { + function r(e, t) { + return "[Axios v1.4.0] Transitional option '" + e + "'" + t + (n ? ". " + n : "") + } + + return function (n, o, i) { + if (!1 === e) throw new M(r(o, " has been removed" + (t ? " in " + t : "")), M.ERR_DEPRECATED); + return t && !xe[o] && (xe[o] = !0, console.warn(r(o, " has been deprecated since v" + t + " and will be removed in the near future"))), !e || e(n, o, i) + } + }; + var Pe = { + assertOptions: function (t, n, r) { + if ("object" !== e(t)) throw new M("options must be an object", M.ERR_BAD_OPTION_VALUE); + for (var o = Object.keys(t), i = o.length; i-- > 0;) { + var a = o[i], s = n[a]; + if (s) { + var u = t[a], c = void 0 === u || s(u, a, t); + if (!0 !== c) throw new M("option " + a + " must be " + c, M.ERR_BAD_OPTION_VALUE) + } else if (!0 !== r) throw new M("Unknown option " + a, M.ERR_BAD_OPTION) + } + }, validators: Ce + }, ke = Pe.validators, Ue = function () { + function e(n) { + t(this, e), this.defaults = n, this.interceptors = {request: new te, response: new te} + } + + return r(e, [{ + key: "request", value: function (e, t) { + "string" == typeof e ? (t = t || {}).url = e : t = e || {}; + var n, r = t = je(this.defaults, t), o = r.transitional, i = r.paramsSerializer, a = r.headers; + void 0 !== o && Pe.assertOptions(o, { + silentJSONParsing: ke.transitional(ke.boolean), + forcedJSONParsing: ke.transitional(ke.boolean), + clarifyTimeoutError: ke.transitional(ke.boolean) + }, !1), null != i && (q.isFunction(i) ? t.paramsSerializer = {serialize: i} : Pe.assertOptions(i, { + encode: ke.function, + serialize: ke.function + }, !0)), t.method = (t.method || this.defaults.method || "get").toLowerCase(), (n = a && q.merge(a.common, a[t.method])) && q.forEach(["delete", "get", "head", "post", "put", "patch", "common"], (function (e) { + delete a[e] + })), t.headers = he.concat(n, a); + var s = [], u = !0; + this.interceptors.request.forEach((function (e) { + "function" == typeof e.runWhen && !1 === e.runWhen(t) || (u = u && e.synchronous, s.unshift(e.fulfilled, e.rejected)) + })); + var c, f = []; + this.interceptors.response.forEach((function (e) { + f.push(e.fulfilled, e.rejected) + })); + var l, d = 0; + if (!u) { + var p = [Ae.bind(this), void 0]; + for (p.unshift.apply(p, s), p.push.apply(p, f), l = p.length, c = Promise.resolve(t); d < l;) c = c.then(p[d++], p[d++]); + return c + } + l = s.length; + var h = t; + for (d = 0; d < l;) { + var m = s[d++], y = s[d++]; + try { + h = m(h) + } catch (e) { + y.call(this, e); + break + } + } + try { + c = Ae.call(this, h) + } catch (e) { + return Promise.reject(e) + } + for (d = 0, l = f.length; d < l;) c = c.then(f[d++], f[d++]); + return c + } + }, { + key: "getUri", value: function (e) { + return Y(ge((e = je(this.defaults, e)).baseURL, e.url), e.params, e.paramsSerializer) + } + }]), e + }(); + q.forEach(["delete", "get", "head", "options"], (function (e) { + Ue.prototype[e] = function (t, n) { + return this.request(je(n || {}, {method: e, url: t, data: (n || {}).data})) + } + })), q.forEach(["post", "put", "patch"], (function (e) { + function t(t) { + return function (n, r, o) { + return this.request(je(o || {}, { + method: e, + headers: t ? {"Content-Type": "multipart/form-data"} : {}, + url: n, + data: r + })) + } + } + + Ue.prototype[e] = t(), Ue.prototype[e + "Form"] = t(!0) + })); + var _e = Ue, Fe = function () { + function e(n) { + if (t(this, e), "function" != typeof n) throw new TypeError("executor must be a function."); + var r; + this.promise = new Promise((function (e) { + r = e + })); + var o = this; + this.promise.then((function (e) { + if (o._listeners) { + for (var t = o._listeners.length; t-- > 0;) o._listeners[t](e); + o._listeners = null + } + })), this.promise.then = function (e) { + var t, n = new Promise((function (e) { + o.subscribe(e), t = e + })).then(e); + return n.cancel = function () { + o.unsubscribe(t) + }, n + }, n((function (e, t, n) { + o.reason || (o.reason = new ve(e, t, n), r(o.reason)) + })) + } + + return r(e, [{ + key: "throwIfRequested", value: function () { + if (this.reason) throw this.reason + } + }, { + key: "subscribe", value: function (e) { + this.reason ? e(this.reason) : this._listeners ? this._listeners.push(e) : this._listeners = [e] + } + }, { + key: "unsubscribe", value: function (e) { + if (this._listeners) { + var t = this._listeners.indexOf(e); + -1 !== t && this._listeners.splice(t, 1) + } + } + }], [{ + key: "source", value: function () { + var t; + return { + token: new e((function (e) { + t = e + })), cancel: t + } + } + }]), e + }(); + var Be = { + Continue: 100, + SwitchingProtocols: 101, + Processing: 102, + EarlyHints: 103, + Ok: 200, + Created: 201, + Accepted: 202, + NonAuthoritativeInformation: 203, + NoContent: 204, + ResetContent: 205, + PartialContent: 206, + MultiStatus: 207, + AlreadyReported: 208, + ImUsed: 226, + MultipleChoices: 300, + MovedPermanently: 301, + Found: 302, + SeeOther: 303, + NotModified: 304, + UseProxy: 305, + Unused: 306, + TemporaryRedirect: 307, + PermanentRedirect: 308, + BadRequest: 400, + Unauthorized: 401, + PaymentRequired: 402, + Forbidden: 403, + NotFound: 404, + MethodNotAllowed: 405, + NotAcceptable: 406, + ProxyAuthenticationRequired: 407, + RequestTimeout: 408, + Conflict: 409, + Gone: 410, + LengthRequired: 411, + PreconditionFailed: 412, + PayloadTooLarge: 413, + UriTooLong: 414, + UnsupportedMediaType: 415, + RangeNotSatisfiable: 416, + ExpectationFailed: 417, + ImATeapot: 418, + MisdirectedRequest: 421, + UnprocessableEntity: 422, + Locked: 423, + FailedDependency: 424, + TooEarly: 425, + UpgradeRequired: 426, + PreconditionRequired: 428, + TooManyRequests: 429, + RequestHeaderFieldsTooLarge: 431, + UnavailableForLegalReasons: 451, + InternalServerError: 500, + NotImplemented: 501, + BadGateway: 502, + ServiceUnavailable: 503, + GatewayTimeout: 504, + HttpVersionNotSupported: 505, + VariantAlsoNegotiates: 506, + InsufficientStorage: 507, + LoopDetected: 508, + NotExtended: 510, + NetworkAuthenticationRequired: 511 + }; + Object.entries(Be).forEach((function (e) { + var t = o(e, 2), n = t[0], r = t[1]; + Be[r] = n + })); + var Le = Be; + var De = function e(t) { + var n = new _e(t), r = a(_e.prototype.request, n); + return q.extend(r, _e.prototype, n, {allOwnKeys: !0}), q.extend(r, n, null, {allOwnKeys: !0}), r.create = function (n) { + return e(je(t, n)) + }, r + }(se); + return De.Axios = _e, De.CanceledError = ve, De.CancelToken = Fe, De.isCancel = ye, De.VERSION = Ne, De.toFormData = G, De.AxiosError = M, De.Cancel = De.CanceledError, De.all = function (e) { + return Promise.all(e) + }, De.spread = function (e) { + return function (t) { + return e.apply(null, t) + } + }, De.isAxiosError = function (e) { + return q.isObject(e) && !0 === e.isAxiosError + }, De.mergeConfig = je, De.AxiosHeaders = he, De.formToJSON = function (e) { + return oe(q.isHTMLForm(e) ? new FormData(e) : e) + }, De.HttpStatusCode = Le, De.default = De, De + })); + return { + requestAction: function (me, action, config) { + // config.url = me.getOpt('serverUrl'); + config.url = me.getActionUrl(); + config.method = 'post'; + config.params = config.params || {}; + config.params = Object.assign(config.params, me.getOpt('serverparam')); + config.params.action = action; + return this.request(me, config); + }, + request: function (me, config) { + config.headers = config.headers || {}; + var customHeaders = me.getOpt('serverHeaders'); + if (customHeaders) { + for (var key in customHeaders) { + config.headers[key] = customHeaders[key]; + } + } + return axios(config); + } } - } - return axios(config); - } - } -})(); + })(); // core/image.js -UE.image = (function(){ - // import browser-image-compression - // https://www.npmjs.com/package/browser-image-compression - var imageCompression = null; - !function(e,t){imageCompression=t();}(this,(function(){"use strict";function _mergeNamespaces(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(r){if("default"!==r&&!(r in e)){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}}))})),Object.freeze(e)}function copyExifWithoutOrientation(e,t){return new Promise((function(r,i){let o;return getApp1Segment(e).then((function(e){try{return o=e,r(new Blob([t.slice(0,2),o,t.slice(2)],{type:"image/jpeg"}))}catch(e){return i(e)}}),i)}))}const getApp1Segment=e=>new Promise(((t,r)=>{const i=new FileReader;i.addEventListener("load",(({target:{result:e}})=>{const i=new DataView(e);let o=0;if(65496!==i.getUint16(o))return r("not a valid JPEG");for(o+=2;;){const a=i.getUint16(o);if(65498===a)break;const s=i.getUint16(o+2);if(65505===a&&1165519206===i.getUint32(o+4)){const a=o+10;let f;switch(i.getUint16(a)){case 18761:f=!0;break;case 19789:f=!1;break;default:return r("TIFF header contains invalid endian")}if(42!==i.getUint16(a+2,f))return r("TIFF header contains invalid version");const l=i.getUint32(a+4,f),c=a+l+2+12*i.getUint16(a+l,f);for(let e=a+l+2;e>>24&255,i[r+1]=o>>>16&255,i[r+2]=o>>>8&255,i[r+3]=o>>>0&255,new Uint8Array(i.buffer,0,r+4)},UZIP.deflateRaw=function(e,t){null==t&&(t={level:6});var r=new Uint8Array(50+Math.floor(1.1*e.length)),i=UZIP.F.deflateRaw(e,r,i,t.level);return new Uint8Array(r.buffer,0,i)},UZIP.encode=function(e,t){null==t&&(t=!1);var r=0,i=UZIP.bin.writeUint,o=UZIP.bin.writeUshort,a={};for(var s in e){var f=!UZIP._noNeed(s)&&!t,l=e[s],c=UZIP.crc.crc(l,0,l.length);a[s]={cpr:f,usize:l.length,crc:c,file:f?UZIP.deflateRaw(l):l}}for(var s in a)r+=a[s].file.length+30+46+2*UZIP.bin.sizeUTF8(s);r+=22;var u=new Uint8Array(r),h=0,d=[];for(var s in a){var A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,0)}var g=0,p=h;for(var s in a){A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,1,d[g++])}var m=h-p;return i(u,h,101010256),h+=4,o(u,h+=4,g),o(u,h+=2,g),i(u,h+=2,m),i(u,h+=4,p),h+=4,h+=2,u.buffer},UZIP._noNeed=function(e){var t=e.split(".").pop().toLowerCase();return-1!="png,jpg,jpeg,zip".indexOf(t)},UZIP._writeHeader=function(e,t,r,i,o,a){var s=UZIP.bin.writeUint,f=UZIP.bin.writeUshort,l=i.file;return s(e,t,0==o?67324752:33639248),t+=4,1==o&&(t+=2),f(e,t,20),f(e,t+=2,0),f(e,t+=2,i.cpr?8:0),s(e,t+=2,0),s(e,t+=4,i.crc),s(e,t+=4,l.length),s(e,t+=4,i.usize),f(e,t+=4,UZIP.bin.sizeUTF8(r)),f(e,t+=2,0),t+=2,1==o&&(t+=2,t+=2,s(e,t+=6,a),t+=4),t+=UZIP.bin.writeUTF8(e,t,r),0==o&&(e.set(l,t),t+=l.length),t},UZIP.crc={table:function(){for(var e=new Uint32Array(256),t=0;t<256;t++){for(var r=t,i=0;i<8;i++)1&r?r=3988292384^r>>>1:r>>>=1;e[t]=r}return e}(),update:function(e,t,r,i){for(var o=0;o>>8;return e},crc:function(e,t,r){return 4294967295^UZIP.crc.update(4294967295,e,t,r)}},UZIP.adler=function(e,t,r){for(var i=1,o=0,a=t,s=t+r;a>8&255},readUint:function(e,t){return 16777216*e[t+3]+(e[t+2]<<16|e[t+1]<<8|e[t])},writeUint:function(e,t,r){e[t]=255&r,e[t+1]=r>>8&255,e[t+2]=r>>16&255,e[t+3]=r>>24&255},readASCII:function(e,t,r){for(var i="",o=0;o>6,e[t+o+1]=128|s>>0&63,o+=2;else if(0==(4294901760&s))e[t+o]=224|s>>12,e[t+o+1]=128|s>>6&63,e[t+o+2]=128|s>>0&63,o+=3;else{if(0!=(4292870144&s))throw"e";e[t+o]=240|s>>18,e[t+o+1]=128|s>>12&63,e[t+o+2]=128|s>>6&63,e[t+o+3]=128|s>>0&63,o+=4}}return o},sizeUTF8:function(e){for(var t=e.length,r=0,i=0;i>>3}var d=a.lits,A=a.strt,g=a.prev,p=0,m=0,w=0,v=0,b=0,y=0;for(h>2&&(A[y=UZIP.F._hash(e,0)]=0),l=0;l14e3||m>26697)&&h-l>100&&(u>>16,B=65535&F;if(0!=F){B=65535&F;var U=s(_=F>>>16,a.of0);a.lhst[257+U]++;var C=s(B,a.df0);a.dhst[C]++,v+=a.exb[U]+a.dxb[C],d[p]=_<<23|l-u,d[p+1]=B<<16|U<<8|C,p+=2,u=l+_}else a.lhst[e[l]]++;m++}}for(w==l&&0!=e.length||(u>>3},UZIP.F._bestMatch=function(e,t,r,i,o,a){var s=32767&t,f=r[s],l=s-f+32768&32767;if(f==s||i!=UZIP.F._hash(e,t-l))return 0;for(var c=0,u=0,h=Math.min(32767,t);l<=h&&0!=--a&&f!=s;){if(0==c||e[t+c]==e[t+c-l]){var d=UZIP.F._howLong(e,t,l);if(d>c){if(u=l,(c=d)>=o)break;l+2A&&(A=m,f=p)}}}l+=(s=f)-(f=r[s])+32768&32767}return c<<16|u},UZIP.F._howLong=function(e,t,r){if(e[t]!=e[t-r]||e[t+1]!=e[t+1-r]||e[t+2]!=e[t+2-r])return 0;var i=t,o=Math.min(e.length,t+258);for(t+=3;t>>23,R=M+(8388607&T);M>16,H=O>>8&255,L=255&O;y(f,l=UZIP.F._writeLit(257+H,C,f,l),S-v.of0[H]),l+=v.exb[H],b(f,l=UZIP.F._writeLit(L,I,f,l),P-v.df0[L]),l+=v.dxb[L],M+=S}}l=UZIP.F._writeLit(256,C,f,l)}return l},UZIP.F._copyExact=function(e,t,r,i,o){var a=o>>>3;return i[a]=r,i[a+1]=r>>>8,i[a+2]=255-i[a],i[a+3]=255-i[a+1],a+=4,i.set(new Uint8Array(e.buffer,t,r),a),o+(r+4<<3)},UZIP.F.getTrees=function(){for(var e=UZIP.F.U,t=UZIP.F._hufTree(e.lhst,e.ltree,15),r=UZIP.F._hufTree(e.dhst,e.dtree,15),i=[],o=UZIP.F._lenCodes(e.ltree,i),a=[],s=UZIP.F._lenCodes(e.dtree,a),f=0;f4&&0==e.itree[1+(e.ordr[c-1]<<1)];)c--;return[t,r,l,o,s,c,i,a]},UZIP.F.getSecond=function(e){for(var t=[],r=0;r>1)+",");return t},UZIP.F.contSize=function(e,t){for(var r=0,i=0;i15&&(UZIP.F._putsE(r,i,s,f),i+=f)}return i},UZIP.F._lenCodes=function(e,t){for(var r=e.length;2!=r&&0==e[r-1];)r-=2;for(var i=0;i>>1,138))<11?t.push(17,c-3):t.push(18,c-11),i+=2*c-2}else if(o==f&&a==o&&s==o){for(l=i+5;l+2>>1,6);t.push(16,c-3),i+=2*c-2}else t.push(o,0)}return r>>>1},UZIP.F._hufTree=function(e,t,r){var i=[],o=e.length,a=t.length,s=0;for(s=0;sr&&(UZIP.F.restrictDepth(l,r,p),p=r),s=0;st;i++){var s=e[i].d;e[i].d=t,a+=o-(1<>>=r-t;a>0;){(s=e[i].d)=0;i--)e[i].d==t&&a<0&&(e[i].d--,a++);0!=a&&console.log("debt left")},UZIP.F._goodIndex=function(e,t){var r=0;return t[16|r]<=e&&(r|=16),t[8|r]<=e&&(r|=8),t[4|r]<=e&&(r|=4),t[2|r]<=e&&(r|=2),t[1|r]<=e&&(r|=1),r},UZIP.F._writeLit=function(e,t,r,i){return UZIP.F._putsF(r,i,t[e<<1]),i+t[1+(e<<1)]},UZIP.F.inflate=function(e,t){var r=Uint8Array;if(3==e[0]&&0==e[1])return t||new r(0);var i=UZIP.F,o=i._bitsF,a=i._bitsE,s=i._decodeTiny,f=i.makeCodes,l=i.codes2map,c=i._get17,u=i.U,h=null==t;h&&(t=new r(e.length>>>2<<3));for(var d,A,g=0,p=0,m=0,w=0,v=0,b=0,y=0,E=0,F=0;0==g;)if(g=o(e,F,1),p=o(e,F+1,2),F+=3,0!=p){if(h&&(t=UZIP.F._check(t,E+(1<<17))),1==p&&(d=u.flmap,A=u.fdmap,b=511,y=31),2==p){m=a(e,F,5)+257,w=a(e,F+5,5)+1,v=a(e,F+10,4)+4,F+=14;for(var _=0;_<38;_+=2)u.itree[_]=0,u.itree[_+1]=0;var B=1;for(_=0;_B&&(B=U)}F+=3*v,f(u.itree,B),l(u.itree,B,u.imap),d=u.lmap,A=u.dmap,F=s(u.imap,(1<>>4;if(M>>>8==0)t[E++]=M;else{if(256==M)break;var x=E+M-254;if(M>264){var T=u.ldef[M-257];x=E+(T>>>3)+a(e,F,7&T),F+=7&T}var S=A[c(e,F)&y];F+=15&S;var R=S>>>4,O=u.ddef[R],P=(O>>>4)+o(e,F,15&O);for(F+=15&O,h&&(t=UZIP.F._check(t,E+(1<<17)));E>>3),L=e[H-4]|e[H-3]<<8;h&&(t=UZIP.F._check(t,E+L)),t.set(new r(e.buffer,e.byteOffset+H,L),E),F=H+L<<3,E+=L}return t.length==E?t:t.slice(0,E)},UZIP.F._check=function(e,t){var r=e.length;if(t<=r)return e;var i=new Uint8Array(Math.max(r<<1,t));return i.set(e,0),i},UZIP.F._decodeTiny=function(e,t,r,i,o,a){for(var s=UZIP.F._bitsE,f=UZIP.F._get17,l=0;l>>4;if(u<=15)a[l]=u,l++;else{var h=0,d=0;16==u?(d=3+s(i,o,2),o+=2,h=a[l-1]):17==u?(d=3+s(i,o,3),o+=3):18==u&&(d=11+s(i,o,7),o+=7);for(var A=l+d;l>>1;ao&&(o=f),a++}for(;a>1,f=e[a+1],l=s<<4|f,c=t-f,u=e[a]<>>15-t]=l,u++}},UZIP.F.revCodes=function(e,t){for(var r=UZIP.F.U.rev15,i=15-t,o=0;o>>i}},UZIP.F._putsE=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},UZIP.F._putsF=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},UZIP.F._bitsE=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},UZIP.F._get25=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},UZIP.F.U=(t=Uint16Array,r=Uint32Array,{next_code:new t(16),bl_count:new t(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new t(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new r(32),flmap:new t(512),fltree:[],fdmap:new t(32),fdtree:[],lmap:new t(32768),ltree:[],ttree:[],dmap:new t(32768),dtree:[],imap:new t(512),itree:[],rev15:new t(32768),lhst:new r(286),dhst:new r(30),ihst:new r(19),lits:new r(15e3),strt:new t(65536),prev:new t(32768)}),function(){for(var e=UZIP.F.U,t=0;t<32768;t++){var r=t;r=(4278255360&(r=(4042322160&(r=(3435973836&(r=(2863311530&r)>>>1|(1431655765&r)<<1))>>>2|(858993459&r)<<2))>>>4|(252645135&r)<<4))>>>8|(16711935&r)<<8,e.rev15[t]=(r>>>16|r<<16)>>>17}function pushV(e,t,r){for(;0!=t--;)e.push(0,r)}for(t=0;t<32;t++)e.ldef[t]=e.of0[t]<<3|e.exb[t],e.ddef[t]=e.df0[t]<<4|e.dxb[t];pushV(e.fltree,144,8),pushV(e.fltree,112,9),pushV(e.fltree,24,7),pushV(e.fltree,8,8),UZIP.F.makeCodes(e.fltree,9),UZIP.F.codes2map(e.fltree,9,e.flmap),UZIP.F.revCodes(e.fltree,9),pushV(e.fdtree,32,5),UZIP.F.makeCodes(e.fdtree,5),UZIP.F.codes2map(e.fdtree,5,e.fdmap),UZIP.F.revCodes(e.fdtree,5),pushV(e.itree,19,0),pushV(e.ltree,286,0),pushV(e.dtree,30,0),pushV(e.ttree,320,0)}()}({get exports(){return e},set exports(t){e=t}});var UZIP=_mergeNamespaces({__proto__:null,default:e},[e]);const UPNG=function(){var e={nextZero(e,t){for(;0!=e[t];)t++;return t},readUshort:(e,t)=>e[t]<<8|e[t+1],writeUshort(e,t,r){e[t]=r>>8&255,e[t+1]=255&r},readUint:(e,t)=>16777216*e[t]+(e[t+1]<<16|e[t+2]<<8|e[t+3]),writeUint(e,t,r){e[t]=r>>24&255,e[t+1]=r>>16&255,e[t+2]=r>>8&255,e[t+3]=255&r},readASCII(e,t,r){let i="";for(let o=0;oe.length<2?`0${e}`:e,readUTF8(t,r,i){let o,a="";for(let o=0;o>3)]>>7-((7&A)<<0)&1);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E>2)]>>6-((3&A)<<1)&3);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E>1)]>>4-((1&A)<<2)&15);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E>>3)]>>>7-(7&B)&1))==255*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(2==h)for(B=0;B>>2)]>>>6-((3&B)<<1)&3))==85*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(4==h)for(B=0;B>>1)]>>>4-((1&B)<<2)&15))==17*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(8==h)for(B=0;B>3,s=Math.ceil(r*o/8),f=new Uint8Array(i*s);let l=0;const c=[0,0,4,0,2,0,1],u=[0,4,0,2,0,1,0],h=[8,8,8,4,4,2,2],d=[8,8,4,4,2,2,1];let A=0;for(;A<7;){const p=h[A],m=d[A];let w=0,v=0,b=c[A];for(;b>3])>>7-(7&i)&1,f[_*s+(t>>3)]|=g<<7-((7&t)<<0);if(2==o)g=(g=e[i>>3])>>6-(7&i)&3,f[_*s+(t>>2)]|=g<<6-((3&t)<<1);if(4==o)g=(g=e[i>>3])>>4-(7&i)&15,f[_*s+(t>>1)]|=g<<4-((1&t)<<2);if(o>=8){const r=_*s+t*a;for(let t=0;t>3)+t]}i+=o,t+=m}F++,_+=p}w*v!=0&&(l+=v*(1+E)),A+=1}return f}(r,e)),r}function _inflate(e,r){return t(new Uint8Array(e.buffer,2,e.length-6),r)}var t=function(){const e={H:{}};return e.H.N=function(t,r){const i=Uint8Array;let o,a,s=0,f=0,l=0,c=0,u=0,h=0,d=0,A=0,g=0;if(3==t[0]&&0==t[1])return r||new i(0);const p=e.H,m=p.b,w=p.e,v=p.R,b=p.n,y=p.A,E=p.Z,F=p.m,_=null==r;for(_&&(r=new i(t.length>>>2<<5));0==s;)if(s=m(t,g,1),f=m(t,g+1,2),g+=3,0!=f){if(_&&(r=e.H.W(r,A+(1<<17))),1==f&&(o=F.J,a=F.h,h=511,d=31),2==f){l=w(t,g,5)+257,c=w(t,g+5,5)+1,u=w(t,g+10,4)+4,g+=14;let e=1;for(var B=0;B<38;B+=2)F.Q[B]=0,F.Q[B+1]=0;for(B=0;Be&&(e=r)}g+=3*u,b(F.Q,e),y(F.Q,e,F.u),o=F.w,a=F.d,g=v(F.u,(1<>>4;if(i>>>8==0)r[A++]=i;else{if(256==i)break;{let e=A+i-254;if(i>264){const r=F.q[i-257];e=A+(r>>>3)+w(t,g,7&r),g+=7&r}const o=a[E(t,g)&d];g+=15&o;const s=o>>>4,f=F.c[s],l=(f>>>4)+m(t,g,15&f);for(g+=15&f;A>>3),a=t[o-4]|t[o-3]<<8;_&&(r=e.H.W(r,A+a)),r.set(new i(t.buffer,t.byteOffset+o,a),A),g=o+a<<3,A+=a}return r.length==A?r:r.slice(0,A)},e.H.W=function(e,t){const r=e.length;if(t<=r)return e;const i=new Uint8Array(r<<1);return i.set(e,0),i},e.H.R=function(t,r,i,o,a,s){const f=e.H.e,l=e.H.Z;let c=0;for(;c>>4;if(i<=15)s[c]=i,c++;else{let e=0,t=0;16==i?(t=3+f(o,a,2),a+=2,e=s[c-1]):17==i?(t=3+f(o,a,3),a+=3):18==i&&(t=11+f(o,a,7),a+=7);const r=c+t;for(;c>>1;for(;ao&&(o=r),a++}for(;a>1,s=t[e+1],f=o<<4|s,l=r-s;let c=t[e]<>>15-r]=f,c++}}},e.H.l=function(t,r){const i=e.H.m.r,o=15-r;for(let e=0;e>>o}},e.H.M=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},e.H.I=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},e.H.e=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},e.H.i=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},e.H.m=function(){const e=Uint16Array,t=Uint32Array;return{K:new e(16),j:new e(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new e(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new t(32),J:new e(512),_:[],h:new e(32),$:[],w:new e(32768),C:[],v:[],d:new e(32768),D:[],u:new e(512),Q:[],r:new e(32768),s:new t(286),Y:new t(30),a:new t(19),t:new t(15e3),k:new e(65536),g:new e(32768)}}(),function(){const t=e.H.m;for(var r=0;r<32768;r++){let e=r;e=(2863311530&e)>>>1|(1431655765&e)<<1,e=(3435973836&e)>>>2|(858993459&e)<<2,e=(4042322160&e)>>>4|(252645135&e)<<4,e=(4278255360&e)>>>8|(16711935&e)<<8,t.r[r]=(e>>>16|e<<16)>>>17}function n(e,t,r){for(;0!=t--;)e.push(0,r)}for(r=0;r<32;r++)t.q[r]=t.S[r]<<3|t.T[r],t.c[r]=t.p[r]<<4|t.z[r];n(t._,144,8),n(t._,112,9),n(t._,24,7),n(t._,8,8),e.H.n(t._,9),e.H.A(t._,9,t.J),e.H.l(t._,9),n(t.$,32,5),e.H.n(t.$,5),e.H.A(t.$,5,t.h),e.H.l(t.$,5),n(t.Q,19,0),n(t.C,286,0),n(t.D,30,0),n(t.v,320,0)}(),e.H.N}();function _getBPP(e){return[1,null,3,1,2,null,4][e.ctype]*e.depth}function _filterZero(e,t,r,i,o){let a=_getBPP(t);const s=Math.ceil(i*a/8);let f,l;a=Math.ceil(a/8);let c=e[r],u=0;if(c>1&&(e[r]=[0,0,1][c-2]),3==c)for(u=a;u>>1)&255;for(let t=0;t>>1);for(;u>>1)}else{for(;u=0&&f>=0?(h=r*t+a<<2,d=(f+r)*o+s+a<<2):(h=(-f+r)*t-s+a<<2,d=r*o+a<<2),0==l)i[d]=e[h],i[d+1]=e[h+1],i[d+2]=e[h+2],i[d+3]=e[h+3];else if(1==l){var A=e[h+3]*(1/255),g=e[h]*A,p=e[h+1]*A,m=e[h+2]*A,w=i[d+3]*(1/255),v=i[d]*w,b=i[d+1]*w,y=i[d+2]*w;const t=1-A,r=A+w*t,o=0==r?0:1/r;i[d+3]=255*r,i[d+0]=(g+v*t)*o,i[d+1]=(p+b*t)*o,i[d+2]=(m+y*t)*o}else if(2==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];A==w&&g==v&&p==b&&m==y?(i[d]=0,i[d+1]=0,i[d+2]=0,i[d+3]=0):(i[d]=g,i[d+1]=p,i[d+2]=m,i[d+3]=A)}else if(3==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];if(A==w&&g==v&&p==b&&m==y)continue;if(A<220&&w>20)return!1}return!0}return{decode:function decode(r){const i=new Uint8Array(r);let o=8;const a=e,s=a.readUshort,f=a.readUint,l={tabs:{},frames:[]},c=new Uint8Array(i.length);let u,h=0,d=0;const A=[137,80,78,71,13,10,26,10];for(var g=0;g<8;g++)if(i[g]!=A[g])throw"The input is not a PNG file!";for(;o>>1:r>>>=1;e[t]=r}return e}(),update(e,t,r,o){for(let a=0;a>>8;return e},crc:(e,t,r)=>4294967295^i.update(4294967295,e,t,r)};function addErr(e,t,r,i){t[r]+=e[0]*i>>4,t[r+1]+=e[1]*i>>4,t[r+2]+=e[2]*i>>4,t[r+3]+=e[3]*i>>4}function N(e){return Math.max(0,Math.min(255,e))}function D(e,t){const r=e[0]-t[0],i=e[1]-t[1],o=e[2]-t[2],a=e[3]-t[3];return r*r+i*i+o*o+a*a}function dither(e,t,r,i,o,a,s){null==s&&(s=1);const f=i.length,l=[];for(var c=0;c>>0&255,e>>>8&255,e>>>16&255,e>>>24&255])}for(c=0;c>2]=u,A[c>>2]=i[u]}}function _main(e,r,o,a,s){null==s&&(s={});const{crc:f}=i,l=t.writeUint,c=t.writeUshort,u=t.writeASCII;let h=8;const d=e.frames.length>1;let A,g=!1,p=33+(d?20:0);if(null!=s.sRGB&&(p+=13),null!=s.pHYs&&(p+=21),null!=s.iCCP&&(A=pako.deflate(s.iCCP),p+=21+A.length+4),3==e.ctype){for(var m=e.plte.length,w=0;w>>24!=255&&(g=!0);p+=8+3*m+4+(g?8+1*m+4:0)}for(var v=0;v>>8&255,a=r>>>16&255;b[h+t+0]=i,b[h+t+1]=o,b[h+t+2]=a}if(h+=3*m,l(b,h,f(b,h-3*m-4,3*m+4)),h+=4,g){l(b,h,m),h+=4,u(b,h,"tRNS"),h+=4;for(w=0;w>>24&255;h+=m,l(b,h,f(b,h-m-4,m+4)),h+=4}}let E=0;for(v=0;vc&&(c=t),eh&&(h=e))}-1==c&&(s=f=c=h=0),a&&(1==(1&s)&&s--,1==(1&f)&&f--);const v=(c-s+1)*(h-f+1);v>2,e>>2);F.push(_);const t=new Uint8Array(r.abuf,i,e);h&&dither(B.img,B.rect.width,B.rect.height,E,t,_),B.img.set(t),i+=e}}else for(p=0;pU&&t==e[w-U])_[w]=_[w-U];else{let e=y[t];if(null==e&&(y[t]=e=E.length,E.push(t),E.length>=300))break;_[w]=e}}}const C=E.length;C<=256&&0==u&&(A=C<=2?1:C<=4?2:C<=16?4:8,A=Math.max(A,c));for(p=0;p>1)]|=o[e+Q]<<4-4*(1&Q);else if(2==A)for(Q=0;Q>2)]|=o[e+Q]<<6-2*(3&Q);else if(1==A)for(Q=0;Q>3)]|=o[e+Q]<<7-1*(7&Q)}t=I,d=3,i=1}else if(0==v&&1==b.length){I=new Uint8Array(U*e*3);const o=U*e;for(w=0;ww&&(w=i),fv&&(v=f))}-1==w&&(p=m=w=v=0),f&&(1==(1&p)&&p--,1==(1&m)&&m--),s={x:p,y:m,width:w-p+1,height:v-m+1};const b=o[a];b.rect=s,b.blend=1,b.img=new Uint8Array(s.width*s.height*4),0==o[a-1].dispose?(e(u,r,i,b.img,s.width,s.height,-s.x,-s.y,0),_prepareDiff(A,r,i,b.img,s)):e(A,r,i,b.img,s.width,s.height,-s.x,-s.y,0)}function _prepareDiff(t,r,i,o,a){e(t,r,i,o,a.width,a.height,-a.x,-a.y,2)}function _filterZero(e,t,r,i,o,a,s){const f=[];let l,c=[0,1,2,3,4];-1!=a?c=[a]:(t*i>5e5||1==r)&&(c=[0]),s&&(l={level:0});const u=UZIP;for(var h=0;h>1)+256&255;if(4==s)for(c=a;c>1)&255;for(c=a;c>1)&255}if(4==s){for(c=0;c>2);let u;if(r.length<2e7)for(var h=0;h>2]=u.ind,o[h>>2]=u.est.rgba}else for(h=0;h>2]=u.ind,o[h>>2]=u.est.rgba}return{abuf:i.buffer,inds:c,plte:f}}function getKDtree(e,t,r){null==r&&(r=1e-4);const i=new Uint32Array(e.buffer),o={i0:0,i1:e.length,bst:null,est:null,tdst:0,left:null,right:null};o.bst=stats(e,o.i0,o.i1),o.est=estats(o.bst);const a=[o];for(;a.lengtht&&(t=a[s].est.L,o=s);if(t=l||f.i1<=l){f.est.L=0;continue}const c={i0:f.i0,i1:l,bst:null,est:null,tdst:0,left:null,right:null};c.bst=stats(e,c.i0,c.i1),c.est=estats(c.bst);const u={i0:l,i1:f.i1,bst:null,est:null,tdst:0,left:null,right:null};u.bst={R:[],m:[],N:f.bst.N-c.bst.N};for(s=0;s<16;s++)u.bst.R[s]=f.bst.R[s]-c.bst.R[s];for(s=0;s<4;s++)u.bst.m[s]=f.bst.m[s]-c.bst.m[s];u.est=estats(u.bst),f.left=c,f.right=u,a[o]=c,a.push(u)}a.sort(((e,t)=>t.bst.N-e.bst.N));for(s=0;s0&&(s=e.right,f=e.left);const l=getNearest(s,t,r,i,o);if(l.tdst<=a*a)return l;const c=getNearest(f,t,r,i,o);return c.tdsta;)i-=4;if(r>=i)break;const s=t[r>>2];t[r>>2]=t[i>>2],t[i>>2]=s,r+=4,i-=4}for(;vecDot(e,r,o)>a;)r-=4;return r+4}function vecDot(e,t,r){return e[t]*r[0]+e[t+1]*r[1]+e[t+2]*r[2]+e[t+3]*r[3]}function stats(e,t,r){const i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],o=[0,0,0,0],a=r-t>>2;for(let a=t;a>>0}}var o={multVec:(e,t)=>[e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],e[4]*t[0]+e[5]*t[1]+e[6]*t[2]+e[7]*t[3],e[8]*t[0]+e[9]*t[1]+e[10]*t[2]+e[11]*t[3],e[12]*t[0]+e[13]*t[1]+e[14]*t[2]+e[15]*t[3]],dot:(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],sml:(e,t)=>[e*t[0],e*t[1],e*t[2],e*t[3]]};UPNG.encode=function encode(e,t,r,i,o,a,s){null==i&&(i=0),null==s&&(s=!1);const f=compress(e,t,r,i,[!1,!1,!1,0,s,!1]);return compressPNG(f,-1),_main(f,t,r,o,a)},UPNG.encodeLL=function encodeLL(e,t,r,i,o,a,s,f){const l={ctype:0+(1==i?0:2)+(0==o?0:4),depth:a,frames:[]},c=(i+o)*a,u=c*t;for(let i=0;i>>0),set16(1),set16(32),set32(3),set32(c),set32(2835),set32(2835),seek(8),set32(16711680),set32(65280),set32(255),set32(4278190080),set32(1466527264),function convert(){for(;b0;){for(w=122+b*l,g=0;g>>24,d.setUint32(w+g,p<<8|m),g+=4;b++}E{t(new Blob([e],{type:"image/bmp"}))}))},_dly:9};var r={CHROME:"CHROME",FIREFOX:"FIREFOX",DESKTOP_SAFARI:"DESKTOP_SAFARI",IE:"IE",IOS:"IOS",ETC:"ETC"},i={[r.CHROME]:16384,[r.FIREFOX]:11180,[r.DESKTOP_SAFARI]:16384,[r.IE]:8192,[r.IOS]:4096,[r.ETC]:8192};const o="undefined"!=typeof window,a="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,s=o&&window.cordova&&window.cordova.require&&window.cordova.require("cordova/modulemapper"),CustomFile=(o||a)&&(s&&s.getOriginalSymbol(window,"File")||"undefined"!=typeof File&&File),CustomFileReader=(o||a)&&(s&&s.getOriginalSymbol(window,"FileReader")||"undefined"!=typeof FileReader&&FileReader);function getFilefromDataUrl(e,t,r=Date.now()){return new Promise((i=>{const o=e.split(","),a=o[0].match(/:(.*?);/)[1],s=globalThis.atob(o[1]);let f=s.length;const l=new Uint8Array(f);for(;f--;)l[f]=s.charCodeAt(f);const c=new Blob([l],{type:a});c.name=t,c.lastModified=r,i(c)}))}function getDataUrlFromFile(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=()=>t(i.result),i.onerror=e=>r(e),i.readAsDataURL(e)}))}function loadImage(e){return new Promise(((t,r)=>{const i=new Image;i.onload=()=>t(i),i.onerror=e=>r(e),i.src=e}))}function getBrowserName(){if(void 0!==getBrowserName.cachedResult)return getBrowserName.cachedResult;let e=r.ETC;const{userAgent:t}=navigator;return/Chrom(e|ium)/i.test(t)?e=r.CHROME:/iP(ad|od|hone)/i.test(t)&&/WebKit/i.test(t)?e=r.IOS:/Safari/i.test(t)?e=r.DESKTOP_SAFARI:/Firefox/i.test(t)?e=r.FIREFOX:(/MSIE/i.test(t)||!0==!!document.documentMode)&&(e=r.IE),getBrowserName.cachedResult=e,getBrowserName.cachedResult}function approximateBelowMaximumCanvasSizeOfBrowser(e,t){const r=getBrowserName(),o=i[r];let a=e,s=t,f=a*s;const l=a>s?s/a:a/s;for(;f>o*o;){const e=(o+a)/2,t=(o+s)/2;et.toBlob(e,r))).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_5.call(this)}catch(e){return f(e)}}.bind(this),f);{if("function"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return e.convertToBlob({type:r,quality:a}).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f);{let d;return d=e.toDataURL(r,a),getFilefromDataUrl(d,i,o).then(function(e){try{return l=e,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f)}function $If_6(){return $If_5.call(this)}}function $If_5(){return $If_4.call(this)}}function $If_4(){return s(l)}}))}function cleanupCanvasMemory(e){e.width=0,e.height=0}function isAutoOrientationInBrowser(){return new Promise((function(e,t){let r,i,o,a,s;return void 0!==isAutoOrientationInBrowser.cachedResult?e(isAutoOrientationInBrowser.cachedResult):(r="data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==",getFilefromDataUrl("data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==","test.jpg",Date.now()).then((function(r){try{return i=r,drawFileInCanvas(i).then((function(r){try{return o=r[1],canvasToFile(o,i.type,i.name,i.lastModified).then((function(r){try{return a=r,cleanupCanvasMemory(o),drawFileInCanvas(a).then((function(r){try{return s=r[0],isAutoOrientationInBrowser.cachedResult=1===s.width&&2===s.height,e(isAutoOrientationInBrowser.cachedResult)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t))}))}function getExifOrientation(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=e=>{const r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return t(-2);const i=r.byteLength;let o=2;for(;or(e),i.readAsArrayBuffer(e)}))}function handleMaxWidthOrHeight(e,t){const{width:r}=e,{height:i}=e,{maxWidthOrHeight:o}=t;let a,s=e;return isFinite(o)&&(r>o||i>o)&&([s,a]=getNewCanvasAndCtx(r,i),r>i?(s.width=o,s.height=i/r*o):(s.width=r/i*o,s.height=o),a.drawImage(e,0,0,s.width,s.height),cleanupCanvasMemory(e)),s}function followExifOrientation(e,t){const{width:r}=e,{height:i}=e,[o,a]=getNewCanvasAndCtx(r,i);switch(t>4&&t<9?(o.width=i,o.height=r):(o.width=r,o.height=i),t){case 2:a.transform(-1,0,0,1,r,0);break;case 3:a.transform(-1,0,0,-1,r,i);break;case 4:a.transform(1,0,0,-1,0,i);break;case 5:a.transform(0,1,1,0,0,0);break;case 6:a.transform(0,1,-1,0,i,0);break;case 7:a.transform(0,-1,-1,0,i,r);break;case 8:a.transform(0,-1,1,0,0,r)}return a.drawImage(e,0,0,r,i),cleanupCanvasMemory(e),o}function compress(e,t,r=0){return new Promise((function(i,o){let a,s,f,l,c,u,h,d,A,g,p,m,w,v,b,y,E,F,_,B;function incProgress(e=5){if(t.signal&&t.signal.aborted)throw t.signal.reason;a+=e,t.onProgress(Math.min(a,100))}function setProgress(e){if(t.signal&&t.signal.aborted)throw t.signal.reason;a=Math.min(Math.max(e,a),100),t.onProgress(a)}return a=r,s=t.maxIteration||10,f=1024*t.maxSizeMB*1024,incProgress(),drawFileInCanvas(e,t).then(function(r){try{return[,l]=r,incProgress(),c=handleMaxWidthOrHeight(l,t),incProgress(),new Promise((function(r,i){var o;if(!(o=t.exifOrientation))return getExifOrientation(e).then(function(e){try{return o=e,$If_2.call(this)}catch(e){return i(e)}}.bind(this),i);function $If_2(){return r(o)}return $If_2.call(this)})).then(function(r){try{return u=r,incProgress(),isAutoOrientationInBrowser().then(function(r){try{return h=r?c:followExifOrientation(c,u),incProgress(),d=t.initialQuality||1,A=t.fileType||e.type,canvasToFile(h,A,e.name,e.lastModified,d).then(function(r){try{{if(g=r,incProgress(),p=g.size>f,m=g.size>e.size,!p&&!m)return setProgress(100),i(g);var a;function $Loop_3(){if(s--&&(b>f||b>w)){let t,r;return t=B?.95*_.width:_.width,r=B?.95*_.height:_.height,[E,F]=getNewCanvasAndCtx(t,r),F.drawImage(_,0,0,t,r),d*="image/png"===A?.85:.95,canvasToFile(E,A,e.name,e.lastModified,d).then((function(e){try{return y=e,cleanupCanvasMemory(_),_=E,b=y.size,setProgress(Math.min(99,Math.floor((v-b)/(v-f)*100))),$Loop_3}catch(e){return o(e)}}),o)}return[1]}return w=e.size,v=g.size,b=v,_=h,B=!t.alwaysKeepResolution&&p,(a=function(e){for(;e;){if(e.then)return void e.then(a,o);try{if(e.pop){if(e.length)return e.pop()?$Loop_3_exit.call(this):e;e=$Loop_3}else e=e.call(this)}catch(e){return o(e)}}}.bind(this))($Loop_3);function $Loop_3_exit(){return cleanupCanvasMemory(_),cleanupCanvasMemory(E),cleanupCanvasMemory(c),cleanupCanvasMemory(h),cleanupCanvasMemory(l),setProgress(100),i(y)}}}catch(u){return o(u)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}))}const f="\nlet scriptImported = false\nself.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n options.onProgress = (progress) => self.postMessage({ progress, id })\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n self.importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message + '\\n' + e.stack, id })\n }\n})\n";let l;function compressOnWebWorker(e,t){return new Promise(((r,i)=>{l||(l=function createWorkerScriptURL(e){const t=[];return"function"==typeof e?t.push(`(${e})()`):t.push(e),URL.createObjectURL(new Blob(t))}(f));const o=new Worker(l);o.addEventListener("message",(function handler(e){if(t.signal&&t.signal.aborted)o.terminate();else if(void 0===e.data.progress){if(e.data.error)return i(new Error(e.data.error)),void o.terminate();r(e.data.file),o.terminate()}else t.onProgress(e.data.progress)})),o.addEventListener("error",i),t.signal&&t.signal.addEventListener("abort",(()=>{i(t.signal.reason),o.terminate()})),o.postMessage({file:e,imageCompressionLibUrl:t.libURL,options:{...t,onProgress:void 0,signal:void 0}})}))}function imageCompression(e,t){return new Promise((function(r,i){let o,a,s,f,l,c;if(o={...t},s=0,({onProgress:f}=o),o.maxSizeMB=o.maxSizeMB||Number.POSITIVE_INFINITY,l="boolean"!=typeof o.useWebWorker||o.useWebWorker,delete o.useWebWorker,o.onProgress=e=>{s=e,"function"==typeof f&&f(s)},!(1||e instanceof Blob||e instanceof CustomFile))return i(new Error("The file given is not an instance of Blob or File"));if(!/^image/.test(e.type))return i(new Error("The file given is not an image"));if(c="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!l||"function"!=typeof Worker||c)return compress(e,o).then(function(e){try{return a=e,$If_4.call(this)}catch(e){return i(e)}}.bind(this),i);var u=function(){try{return $If_4.call(this)}catch(e){return i(e)}}.bind(this),$Try_1_Catch=function(t){try{return compress(e,o).then((function(e){try{return a=e,u()}catch(e){return i(e)}}),i)}catch(e){return i(e)}};try{return o.libURL=o.libURL||"https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js",compressOnWebWorker(e,o).then((function(e){try{return a=e,u()}catch(e){return $Try_1_Catch()}}),$Try_1_Catch)}catch(e){$Try_1_Catch()}function $If_4(){try{a.name=e.name,a.lastModified=e.lastModified}catch(e){}try{o.preserveExif&&"image/jpeg"===e.type&&(!o.fileType||o.fileType&&o.fileType===e.type)&&(a=copyExifWithoutOrientation(e,a))}catch(e){}return r(a)}}))}return imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation,imageCompression.cleanupCanvasMemory=cleanupCanvasMemory,imageCompression.isAutoOrientationInBrowser=isAutoOrientationInBrowser,imageCompression.approximateBelowMaximumCanvasSizeOfBrowser=approximateBelowMaximumCanvasSizeOfBrowser,imageCompression.copyExifWithoutOrientation=copyExifWithoutOrientation,imageCompression.getBrowserName=getBrowserName,imageCompression.version="2.0.2",imageCompression})); - return { - // { - // maxSizeMB: number, // (default: Number.POSITIVE_INFINITY) - // maxWidthOrHeight: number, // compressedFile will scale down by ratio to a point that width or height is smaller than maxWidthOrHeight (default: undefined) - // // but, automatically reduce the size to smaller than the maximum Canvas size supported by each browser. - // // Please check the Caveat part for details. - // onProgress: Function, // optional, a function takes one progress argument (percentage from 0 to 100) - // useWebWorker: boolean, // optional, use multi-thread web worker, fallback to run in main-thread (default: true) - // libURL: string, // optional, the libURL of this library for importing script in Web Worker (default: https://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.js) - // preserveExif: boolean, // optional, use preserve Exif metadata for JPEG image e.g., Camera model, Focal length, etc (default: false) - // - // signal: AbortSignal, // optional, to abort / cancel the compression - // - // // following options are for advanced users - // maxIteration: number, // optional, max number of iteration to compress the image (default: 10) - // exifOrientation: number, // optional, see https://stackoverflow.com/a/32490603/10395024 - // fileType: string, // optional, fileType override e.g., 'image/jpeg', 'image/png' (default: file.type) - // initialQuality: number, // optional, initial quality value between 0 and 1 (default: 1) - // alwaysKeepResolution: boolean // optional, only reduce quality, always keep width and height (default: false) - // } - compress:function(file,option){ - return imageCompression(file,option); - } - }; -})(); + UE.image = (function () { + // import browser-image-compression + // https://www.npmjs.com/package/browser-image-compression + var imageCompression = null; + !function (e, t) { + imageCompression = t(); + }(this, (function () { + "use strict"; + + function _mergeNamespaces(e, t) { + return t.forEach((function (t) { + t && "string" != typeof t && !Array.isArray(t) && Object.keys(t).forEach((function (r) { + if ("default" !== r && !(r in e)) { + var i = Object.getOwnPropertyDescriptor(t, r); + Object.defineProperty(e, r, i.get ? i : { + enumerable: !0, get: function () { + return t[r] + } + }) + } + })) + })), Object.freeze(e) + } + + function copyExifWithoutOrientation(e, t) { + return new Promise((function (r, i) { + let o; + return getApp1Segment(e).then((function (e) { + try { + return o = e, r(new Blob([t.slice(0, 2), o, t.slice(2)], {type: "image/jpeg"})) + } catch (e) { + return i(e) + } + }), i) + })) + } + + const getApp1Segment = e => new Promise(((t, r) => { + const i = new FileReader; + i.addEventListener("load", (({target: {result: e}}) => { + const i = new DataView(e); + let o = 0; + if (65496 !== i.getUint16(o)) return r("not a valid JPEG"); + for (o += 2; ;) { + const a = i.getUint16(o); + if (65498 === a) break; + const s = i.getUint16(o + 2); + if (65505 === a && 1165519206 === i.getUint32(o + 4)) { + const a = o + 10; + let f; + switch (i.getUint16(a)) { + case 18761: + f = !0; + break; + case 19789: + f = !1; + break; + default: + return r("TIFF header contains invalid endian") + } + if (42 !== i.getUint16(a + 2, f)) return r("TIFF header contains invalid version"); + const l = i.getUint32(a + 4, f), c = a + l + 2 + 12 * i.getUint16(a + l, f); + for (let e = a + l + 2; e < c; e += 12) { + if (274 == i.getUint16(e, f)) { + if (3 !== i.getUint16(e + 2, f)) return r("Orientation data type is invalid"); + if (1 !== i.getUint32(e + 4, f)) return r("Orientation data count is invalid"); + i.setUint16(e + 8, 1, f); + break + } + } + return t(e.slice(o, o + 2 + s)) + } + o += 2 + s + } + return t(new Blob) + })), i.readAsArrayBuffer(e) + })); + var e = {}; + !function (e) { + var t, r, UZIP = {}; + e.exports = UZIP, UZIP.parse = function (e, t) { + for (var r = UZIP.bin.readUshort, i = UZIP.bin.readUint, o = 0, a = {}, s = new Uint8Array(e), f = s.length - 4; 101010256 != i(s, f);) f--; + o = f; + o += 4; + var l = r(s, o += 4); + r(s, o += 2); + var c = i(s, o += 2), u = i(s, o += 4); + o += 4, o = u; + for (var h = 0; h < l; h++) { + i(s, o), o += 4, o += 4, o += 4, i(s, o += 4); + c = i(s, o += 4); + var d = i(s, o += 4), A = r(s, o += 4), g = r(s, o + 2), p = r(s, o + 4); + o += 6; + var m = i(s, o += 8); + o += 4, o += A + g + p, UZIP._readLocal(s, m, a, c, d, t) + } + return a + }, UZIP._readLocal = function (e, t, r, i, o, a) { + var s = UZIP.bin.readUshort, f = UZIP.bin.readUint; + f(e, t), s(e, t += 4), s(e, t += 2); + var l = s(e, t += 2); + f(e, t += 2), f(e, t += 4), t += 4; + var c = s(e, t += 8), u = s(e, t += 2); + t += 2; + var h = UZIP.bin.readUTF8(e, t, c); + if (t += c, t += u, a) r[h] = {size: o, csize: i}; else { + var d = new Uint8Array(e.buffer, t); + if (0 == l) r[h] = new Uint8Array(d.buffer.slice(t, t + i)); else { + if (8 != l) throw"unknown compression method: " + l; + var A = new Uint8Array(o); + UZIP.inflateRaw(d, A), r[h] = A + } + } + }, UZIP.inflateRaw = function (e, t) { + return UZIP.F.inflate(e, t) + }, UZIP.inflate = function (e, t) { + return e[0], e[1], UZIP.inflateRaw(new Uint8Array(e.buffer, e.byteOffset + 2, e.length - 6), t) + }, UZIP.deflate = function (e, t) { + null == t && (t = {level: 6}); + var r = 0, i = new Uint8Array(50 + Math.floor(1.1 * e.length)); + i[r] = 120, i[r + 1] = 156, r += 2, r = UZIP.F.deflateRaw(e, i, r, t.level); + var o = UZIP.adler(e, 0, e.length); + return i[r + 0] = o >>> 24 & 255, i[r + 1] = o >>> 16 & 255, i[r + 2] = o >>> 8 & 255, i[r + 3] = o >>> 0 & 255, new Uint8Array(i.buffer, 0, r + 4) + }, UZIP.deflateRaw = function (e, t) { + null == t && (t = {level: 6}); + var r = new Uint8Array(50 + Math.floor(1.1 * e.length)), i = UZIP.F.deflateRaw(e, r, i, t.level); + return new Uint8Array(r.buffer, 0, i) + }, UZIP.encode = function (e, t) { + null == t && (t = !1); + var r = 0, i = UZIP.bin.writeUint, o = UZIP.bin.writeUshort, a = {}; + for (var s in e) { + var f = !UZIP._noNeed(s) && !t, l = e[s], c = UZIP.crc.crc(l, 0, l.length); + a[s] = {cpr: f, usize: l.length, crc: c, file: f ? UZIP.deflateRaw(l) : l} + } + for (var s in a) r += a[s].file.length + 30 + 46 + 2 * UZIP.bin.sizeUTF8(s); + r += 22; + var u = new Uint8Array(r), h = 0, d = []; + for (var s in a) { + var A = a[s]; + d.push(h), h = UZIP._writeHeader(u, h, s, A, 0) + } + var g = 0, p = h; + for (var s in a) { + A = a[s]; + d.push(h), h = UZIP._writeHeader(u, h, s, A, 1, d[g++]) + } + var m = h - p; + return i(u, h, 101010256), h += 4, o(u, h += 4, g), o(u, h += 2, g), i(u, h += 2, m), i(u, h += 4, p), h += 4, h += 2, u.buffer + }, UZIP._noNeed = function (e) { + var t = e.split(".").pop().toLowerCase(); + return -1 != "png,jpg,jpeg,zip".indexOf(t) + }, UZIP._writeHeader = function (e, t, r, i, o, a) { + var s = UZIP.bin.writeUint, f = UZIP.bin.writeUshort, l = i.file; + return s(e, t, 0 == o ? 67324752 : 33639248), t += 4, 1 == o && (t += 2), f(e, t, 20), f(e, t += 2, 0), f(e, t += 2, i.cpr ? 8 : 0), s(e, t += 2, 0), s(e, t += 4, i.crc), s(e, t += 4, l.length), s(e, t += 4, i.usize), f(e, t += 4, UZIP.bin.sizeUTF8(r)), f(e, t += 2, 0), t += 2, 1 == o && (t += 2, t += 2, s(e, t += 6, a), t += 4), t += UZIP.bin.writeUTF8(e, t, r), 0 == o && (e.set(l, t), t += l.length), t + }, UZIP.crc = { + table: function () { + for (var e = new Uint32Array(256), t = 0; t < 256; t++) { + for (var r = t, i = 0; i < 8; i++) 1 & r ? r = 3988292384 ^ r >>> 1 : r >>>= 1; + e[t] = r + } + return e + }(), update: function (e, t, r, i) { + for (var o = 0; o < i; o++) e = UZIP.crc.table[255 & (e ^ t[r + o])] ^ e >>> 8; + return e + }, crc: function (e, t, r) { + return 4294967295 ^ UZIP.crc.update(4294967295, e, t, r) + } + }, UZIP.adler = function (e, t, r) { + for (var i = 1, o = 0, a = t, s = t + r; a < s;) { + for (var f = Math.min(a + 5552, s); a < f;) o += i += e[a++]; + i %= 65521, o %= 65521 + } + return o << 16 | i + }, UZIP.bin = { + readUshort: function (e, t) { + return e[t] | e[t + 1] << 8 + }, writeUshort: function (e, t, r) { + e[t] = 255 & r, e[t + 1] = r >> 8 & 255 + }, readUint: function (e, t) { + return 16777216 * e[t + 3] + (e[t + 2] << 16 | e[t + 1] << 8 | e[t]) + }, writeUint: function (e, t, r) { + e[t] = 255 & r, e[t + 1] = r >> 8 & 255, e[t + 2] = r >> 16 & 255, e[t + 3] = r >> 24 & 255 + }, readASCII: function (e, t, r) { + for (var i = "", o = 0; o < r; o++) i += String.fromCharCode(e[t + o]); + return i + }, writeASCII: function (e, t, r) { + for (var i = 0; i < r.length; i++) e[t + i] = r.charCodeAt(i) + }, pad: function (e) { + return e.length < 2 ? "0" + e : e + }, readUTF8: function (e, t, r) { + for (var i, o = "", a = 0; a < r; a++) o += "%" + UZIP.bin.pad(e[t + a].toString(16)); + try { + i = decodeURIComponent(o) + } catch (i) { + return UZIP.bin.readASCII(e, t, r) + } + return i + }, writeUTF8: function (e, t, r) { + for (var i = r.length, o = 0, a = 0; a < i; a++) { + var s = r.charCodeAt(a); + if (0 == (4294967168 & s)) e[t + o] = s, o++; else if (0 == (4294965248 & s)) e[t + o] = 192 | s >> 6, e[t + o + 1] = 128 | s >> 0 & 63, o += 2; else if (0 == (4294901760 & s)) e[t + o] = 224 | s >> 12, e[t + o + 1] = 128 | s >> 6 & 63, e[t + o + 2] = 128 | s >> 0 & 63, o += 3; else { + if (0 != (4292870144 & s)) throw"e"; + e[t + o] = 240 | s >> 18, e[t + o + 1] = 128 | s >> 12 & 63, e[t + o + 2] = 128 | s >> 6 & 63, e[t + o + 3] = 128 | s >> 0 & 63, o += 4 + } + } + return o + }, sizeUTF8: function (e) { + for (var t = e.length, r = 0, i = 0; i < t; i++) { + var o = e.charCodeAt(i); + if (0 == (4294967168 & o)) r++; else if (0 == (4294965248 & o)) r += 2; else if (0 == (4294901760 & o)) r += 3; else { + if (0 != (4292870144 & o)) throw"e"; + r += 4 + } + } + return r + } + }, UZIP.F = {}, UZIP.F.deflateRaw = function (e, t, r, i) { + var o = [[0, 0, 0, 0, 0], [4, 4, 8, 4, 0], [4, 5, 16, 8, 0], [4, 6, 16, 16, 0], [4, 10, 16, 32, 0], [8, 16, 32, 32, 0], [8, 16, 128, 128, 0], [8, 32, 128, 256, 0], [32, 128, 258, 1024, 1], [32, 258, 258, 4096, 1]][i], + a = UZIP.F.U, s = UZIP.F._goodIndex; + UZIP.F._hash; + var f = UZIP.F._putsE, l = 0, c = r << 3, u = 0, h = e.length; + if (0 == i) { + for (; l < h;) { + f(t, c, l + (_ = Math.min(65535, h - l)) == h ? 1 : 0), c = UZIP.F._copyExact(e, l, _, t, c + 8), l += _ + } + return c >>> 3 + } + var d = a.lits, A = a.strt, g = a.prev, p = 0, m = 0, w = 0, v = 0, b = 0, y = 0; + for (h > 2 && (A[y = UZIP.F._hash(e, 0)] = 0), l = 0; l < h; l++) { + if (b = y, l + 1 < h - 2) { + y = UZIP.F._hash(e, l + 1); + var E = l + 1 & 32767; + g[E] = A[y], A[y] = E + } + if (u <= l) { + (p > 14e3 || m > 26697) && h - l > 100 && (u < l && (d[p] = l - u, p += 2, u = l), c = UZIP.F._writeBlock(l == h - 1 || u == h ? 1 : 0, d, p, v, e, w, l - w, t, c), p = m = v = 0, w = l); + var F = 0; + l < h - 2 && (F = UZIP.F._bestMatch(e, l, g, b, Math.min(o[2], h - l), o[3])); + var _ = F >>> 16, B = 65535 & F; + if (0 != F) { + B = 65535 & F; + var U = s(_ = F >>> 16, a.of0); + a.lhst[257 + U]++; + var C = s(B, a.df0); + a.dhst[C]++, v += a.exb[U] + a.dxb[C], d[p] = _ << 23 | l - u, d[p + 1] = B << 16 | U << 8 | C, p += 2, u = l + _ + } else a.lhst[e[l]]++; + m++ + } + } + for (w == l && 0 != e.length || (u < l && (d[p] = l - u, p += 2, u = l), c = UZIP.F._writeBlock(1, d, p, v, e, w, l - w, t, c), p = 0, m = 0, p = m = v = 0, w = l); 0 != (7 & c);) c++; + return c >>> 3 + }, UZIP.F._bestMatch = function (e, t, r, i, o, a) { + var s = 32767 & t, f = r[s], l = s - f + 32768 & 32767; + if (f == s || i != UZIP.F._hash(e, t - l)) return 0; + for (var c = 0, u = 0, h = Math.min(32767, t); l <= h && 0 != --a && f != s;) { + if (0 == c || e[t + c] == e[t + c - l]) { + var d = UZIP.F._howLong(e, t, l); + if (d > c) { + if (u = l, (c = d) >= o) break; + l + 2 < d && (d = l + 2); + for (var A = 0, g = 0; g < d - 2; g++) { + var p = t - l + g + 32768 & 32767, m = p - r[p] + 32768 & 32767; + m > A && (A = m, f = p) + } + } + } + l += (s = f) - (f = r[s]) + 32768 & 32767 + } + return c << 16 | u + }, UZIP.F._howLong = function (e, t, r) { + if (e[t] != e[t - r] || e[t + 1] != e[t + 1 - r] || e[t + 2] != e[t + 2 - r]) return 0; + var i = t, o = Math.min(e.length, t + 258); + for (t += 3; t < o && e[t] == e[t - r];) t++; + return t - i + }, UZIP.F._hash = function (e, t) { + return (e[t] << 8 | e[t + 1]) + (e[t + 2] << 4) & 65535 + }, UZIP.saved = 0, UZIP.F._writeBlock = function (e, t, r, i, o, a, s, f, l) { + var c, u, h, d, A, g, p, m, w, v = UZIP.F.U, b = UZIP.F._putsF, y = UZIP.F._putsE; + v.lhst[256]++, u = (c = UZIP.F.getTrees())[0], h = c[1], d = c[2], A = c[3], g = c[4], p = c[5], m = c[6], w = c[7]; + var E = 32 + (0 == (l + 3 & 7) ? 0 : 8 - (l + 3 & 7)) + (s << 3), + F = i + UZIP.F.contSize(v.fltree, v.lhst) + UZIP.F.contSize(v.fdtree, v.dhst), + _ = i + UZIP.F.contSize(v.ltree, v.lhst) + UZIP.F.contSize(v.dtree, v.dhst); + _ += 14 + 3 * p + UZIP.F.contSize(v.itree, v.ihst) + (2 * v.ihst[16] + 3 * v.ihst[17] + 7 * v.ihst[18]); + for (var B = 0; B < 286; B++) v.lhst[B] = 0; + for (B = 0; B < 30; B++) v.dhst[B] = 0; + for (B = 0; B < 19; B++) v.ihst[B] = 0; + var U = E < F && E < _ ? 0 : F < _ ? 1 : 2; + if (b(f, l, e), b(f, l + 1, U), l += 3, 0 == U) { + for (; 0 != (7 & l);) l++; + l = UZIP.F._copyExact(o, a, s, f, l) + } else { + var C, I; + if (1 == U && (C = v.fltree, I = v.fdtree), 2 == U) { + UZIP.F.makeCodes(v.ltree, u), UZIP.F.revCodes(v.ltree, u), UZIP.F.makeCodes(v.dtree, h), UZIP.F.revCodes(v.dtree, h), UZIP.F.makeCodes(v.itree, d), UZIP.F.revCodes(v.itree, d), C = v.ltree, I = v.dtree, y(f, l, A - 257), y(f, l += 5, g - 1), y(f, l += 5, p - 4), l += 4; + for (var Q = 0; Q < p; Q++) y(f, l + 3 * Q, v.itree[1 + (v.ordr[Q] << 1)]); + l += 3 * p, l = UZIP.F._codeTiny(m, v.itree, f, l), l = UZIP.F._codeTiny(w, v.itree, f, l) + } + for (var M = a, x = 0; x < r; x += 2) { + for (var T = t[x], S = T >>> 23, R = M + (8388607 & T); M < R;) l = UZIP.F._writeLit(o[M++], C, f, l); + if (0 != S) { + var O = t[x + 1], P = O >> 16, H = O >> 8 & 255, L = 255 & O; + y(f, l = UZIP.F._writeLit(257 + H, C, f, l), S - v.of0[H]), l += v.exb[H], b(f, l = UZIP.F._writeLit(L, I, f, l), P - v.df0[L]), l += v.dxb[L], M += S + } + } + l = UZIP.F._writeLit(256, C, f, l) + } + return l + }, UZIP.F._copyExact = function (e, t, r, i, o) { + var a = o >>> 3; + return i[a] = r, i[a + 1] = r >>> 8, i[a + 2] = 255 - i[a], i[a + 3] = 255 - i[a + 1], a += 4, i.set(new Uint8Array(e.buffer, t, r), a), o + (r + 4 << 3) + }, UZIP.F.getTrees = function () { + for (var e = UZIP.F.U, t = UZIP.F._hufTree(e.lhst, e.ltree, 15), r = UZIP.F._hufTree(e.dhst, e.dtree, 15), i = [], o = UZIP.F._lenCodes(e.ltree, i), a = [], s = UZIP.F._lenCodes(e.dtree, a), f = 0; f < i.length; f += 2) e.ihst[i[f]]++; + for (f = 0; f < a.length; f += 2) e.ihst[a[f]]++; + for (var l = UZIP.F._hufTree(e.ihst, e.itree, 7), c = 19; c > 4 && 0 == e.itree[1 + (e.ordr[c - 1] << 1)];) c--; + return [t, r, l, o, s, c, i, a] + }, UZIP.F.getSecond = function (e) { + for (var t = [], r = 0; r < e.length; r += 2) t.push(e[r + 1]); + return t + }, UZIP.F.nonZero = function (e) { + for (var t = "", r = 0; r < e.length; r += 2) 0 != e[r + 1] && (t += (r >> 1) + ","); + return t + }, UZIP.F.contSize = function (e, t) { + for (var r = 0, i = 0; i < t.length; i++) r += t[i] * e[1 + (i << 1)]; + return r + }, UZIP.F._codeTiny = function (e, t, r, i) { + for (var o = 0; o < e.length; o += 2) { + var a = e[o], s = e[o + 1]; + i = UZIP.F._writeLit(a, t, r, i); + var f = 16 == a ? 2 : 17 == a ? 3 : 7; + a > 15 && (UZIP.F._putsE(r, i, s, f), i += f) + } + return i + }, UZIP.F._lenCodes = function (e, t) { + for (var r = e.length; 2 != r && 0 == e[r - 1];) r -= 2; + for (var i = 0; i < r; i += 2) { + var o = e[i + 1], a = i + 3 < r ? e[i + 3] : -1, s = i + 5 < r ? e[i + 5] : -1, + f = 0 == i ? -1 : e[i - 1]; + if (0 == o && a == o && s == o) { + for (var l = i + 5; l + 2 < r && e[l + 2] == o;) l += 2; + (c = Math.min(l + 1 - i >>> 1, 138)) < 11 ? t.push(17, c - 3) : t.push(18, c - 11), i += 2 * c - 2 + } else if (o == f && a == o && s == o) { + for (l = i + 5; l + 2 < r && e[l + 2] == o;) l += 2; + var c = Math.min(l + 1 - i >>> 1, 6); + t.push(16, c - 3), i += 2 * c - 2 + } else t.push(o, 0) + } + return r >>> 1 + }, UZIP.F._hufTree = function (e, t, r) { + var i = [], o = e.length, a = t.length, s = 0; + for (s = 0; s < a; s += 2) t[s] = 0, t[s + 1] = 0; + for (s = 0; s < o; s++) 0 != e[s] && i.push({lit: s, f: e[s]}); + var f = i.length, l = i.slice(0); + if (0 == f) return 0; + if (1 == f) { + var c = i[0].lit; + l = 0 == c ? 1 : 0; + return t[1 + (c << 1)] = 1, t[1 + (l << 1)] = 1, 1 + } + i.sort((function (e, t) { + return e.f - t.f + })); + var u = i[0], h = i[1], d = 0, A = 1, g = 2; + for (i[0] = { + lit: -1, + f: u.f + h.f, + l: u, + r: h, + d: 0 + }; A != f - 1;) u = d != A && (g == f || i[d].f < i[g].f) ? i[d++] : i[g++], h = d != A && (g == f || i[d].f < i[g].f) ? i[d++] : i[g++], i[A++] = { + lit: -1, + f: u.f + h.f, + l: u, + r: h + }; + var p = UZIP.F.setDepth(i[A - 1], 0); + for (p > r && (UZIP.F.restrictDepth(l, r, p), p = r), s = 0; s < f; s++) t[1 + (l[s].lit << 1)] = l[s].d; + return p + }, UZIP.F.setDepth = function (e, t) { + return -1 != e.lit ? (e.d = t, t) : Math.max(UZIP.F.setDepth(e.l, t + 1), UZIP.F.setDepth(e.r, t + 1)) + }, UZIP.F.restrictDepth = function (e, t, r) { + var i = 0, o = 1 << r - t, a = 0; + for (e.sort((function (e, t) { + return t.d == e.d ? e.f - t.f : t.d - e.d + })), i = 0; i < e.length && e[i].d > t; i++) { + var s = e[i].d; + e[i].d = t, a += o - (1 << r - s) + } + for (a >>>= r - t; a > 0;) { + (s = e[i].d) < t ? (e[i].d++, a -= 1 << t - s - 1) : i++ + } + for (; i >= 0; i--) e[i].d == t && a < 0 && (e[i].d--, a++); + 0 != a && console.log("debt left") + }, UZIP.F._goodIndex = function (e, t) { + var r = 0; + return t[16 | r] <= e && (r |= 16), t[8 | r] <= e && (r |= 8), t[4 | r] <= e && (r |= 4), t[2 | r] <= e && (r |= 2), t[1 | r] <= e && (r |= 1), r + }, UZIP.F._writeLit = function (e, t, r, i) { + return UZIP.F._putsF(r, i, t[e << 1]), i + t[1 + (e << 1)] + }, UZIP.F.inflate = function (e, t) { + var r = Uint8Array; + if (3 == e[0] && 0 == e[1]) return t || new r(0); + var i = UZIP.F, o = i._bitsF, a = i._bitsE, s = i._decodeTiny, f = i.makeCodes, l = i.codes2map, + c = i._get17, u = i.U, h = null == t; + h && (t = new r(e.length >>> 2 << 3)); + for (var d, A, g = 0, p = 0, m = 0, w = 0, v = 0, b = 0, y = 0, E = 0, F = 0; 0 == g;) if (g = o(e, F, 1), p = o(e, F + 1, 2), F += 3, 0 != p) { + if (h && (t = UZIP.F._check(t, E + (1 << 17))), 1 == p && (d = u.flmap, A = u.fdmap, b = 511, y = 31), 2 == p) { + m = a(e, F, 5) + 257, w = a(e, F + 5, 5) + 1, v = a(e, F + 10, 4) + 4, F += 14; + for (var _ = 0; _ < 38; _ += 2) u.itree[_] = 0, u.itree[_ + 1] = 0; + var B = 1; + for (_ = 0; _ < v; _++) { + var U = a(e, F + 3 * _, 3); + u.itree[1 + (u.ordr[_] << 1)] = U, U > B && (B = U) + } + F += 3 * v, f(u.itree, B), l(u.itree, B, u.imap), d = u.lmap, A = u.dmap, F = s(u.imap, (1 << B) - 1, m + w, e, F, u.ttree); + var C = i._copyOut(u.ttree, 0, m, u.ltree); + b = (1 << C) - 1; + var I = i._copyOut(u.ttree, m, w, u.dtree); + y = (1 << I) - 1, f(u.ltree, C), l(u.ltree, C, d), f(u.dtree, I), l(u.dtree, I, A) + } + for (; ;) { + var Q = d[c(e, F) & b]; + F += 15 & Q; + var M = Q >>> 4; + if (M >>> 8 == 0) t[E++] = M; else { + if (256 == M) break; + var x = E + M - 254; + if (M > 264) { + var T = u.ldef[M - 257]; + x = E + (T >>> 3) + a(e, F, 7 & T), F += 7 & T + } + var S = A[c(e, F) & y]; + F += 15 & S; + var R = S >>> 4, O = u.ddef[R], P = (O >>> 4) + o(e, F, 15 & O); + for (F += 15 & O, h && (t = UZIP.F._check(t, E + (1 << 17))); E < x;) t[E] = t[E++ - P], t[E] = t[E++ - P], t[E] = t[E++ - P], t[E] = t[E++ - P]; + E = x + } + } + } else { + 0 != (7 & F) && (F += 8 - (7 & F)); + var H = 4 + (F >>> 3), L = e[H - 4] | e[H - 3] << 8; + h && (t = UZIP.F._check(t, E + L)), t.set(new r(e.buffer, e.byteOffset + H, L), E), F = H + L << 3, E += L + } + return t.length == E ? t : t.slice(0, E) + }, UZIP.F._check = function (e, t) { + var r = e.length; + if (t <= r) return e; + var i = new Uint8Array(Math.max(r << 1, t)); + return i.set(e, 0), i + }, UZIP.F._decodeTiny = function (e, t, r, i, o, a) { + for (var s = UZIP.F._bitsE, f = UZIP.F._get17, l = 0; l < r;) { + var c = e[f(i, o) & t]; + o += 15 & c; + var u = c >>> 4; + if (u <= 15) a[l] = u, l++; else { + var h = 0, d = 0; + 16 == u ? (d = 3 + s(i, o, 2), o += 2, h = a[l - 1]) : 17 == u ? (d = 3 + s(i, o, 3), o += 3) : 18 == u && (d = 11 + s(i, o, 7), o += 7); + for (var A = l + d; l < A;) a[l] = h, l++ + } + } + return o + }, UZIP.F._copyOut = function (e, t, r, i) { + for (var o = 0, a = 0, s = i.length >>> 1; a < r;) { + var f = e[a + t]; + i[a << 1] = 0, i[1 + (a << 1)] = f, f > o && (o = f), a++ + } + for (; a < s;) i[a << 1] = 0, i[1 + (a << 1)] = 0, a++; + return o + }, UZIP.F.makeCodes = function (e, t) { + for (var r, i, o, a, s = UZIP.F.U, f = e.length, l = s.bl_count, c = 0; c <= t; c++) l[c] = 0; + for (c = 1; c < f; c += 2) l[e[c]]++; + var u = s.next_code; + for (r = 0, l[0] = 0, i = 1; i <= t; i++) r = r + l[i - 1] << 1, u[i] = r; + for (o = 0; o < f; o += 2) 0 != (a = e[o + 1]) && (e[o] = u[a], u[a]++) + }, UZIP.F.codes2map = function (e, t, r) { + for (var i = e.length, o = UZIP.F.U.rev15, a = 0; a < i; a += 2) if (0 != e[a + 1]) for (var s = a >> 1, f = e[a + 1], l = s << 4 | f, c = t - f, u = e[a] << c, h = u + (1 << c); u != h;) { + r[o[u] >>> 15 - t] = l, u++ + } + }, UZIP.F.revCodes = function (e, t) { + for (var r = UZIP.F.U.rev15, i = 15 - t, o = 0; o < e.length; o += 2) { + var a = e[o] << t - e[o + 1]; + e[o] = r[a] >>> i + } + }, UZIP.F._putsE = function (e, t, r) { + r <<= 7 & t; + var i = t >>> 3; + e[i] |= r, e[i + 1] |= r >>> 8 + }, UZIP.F._putsF = function (e, t, r) { + r <<= 7 & t; + var i = t >>> 3; + e[i] |= r, e[i + 1] |= r >>> 8, e[i + 2] |= r >>> 16 + }, UZIP.F._bitsE = function (e, t, r) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8) >>> (7 & t) & (1 << r) - 1 + }, UZIP.F._bitsF = function (e, t, r) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t) & (1 << r) - 1 + }, UZIP.F._get17 = function (e, t) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t) + }, UZIP.F._get25 = function (e, t) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16 | e[3 + (t >>> 3)] << 24) >>> (7 & t) + }, UZIP.F.U = (t = Uint16Array, r = Uint32Array, { + next_code: new t(16), + bl_count: new t(16), + ordr: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], + of0: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999], + exb: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0], + ldef: new t(32), + df0: [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535], + dxb: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0], + ddef: new r(32), + flmap: new t(512), + fltree: [], + fdmap: new t(32), + fdtree: [], + lmap: new t(32768), + ltree: [], + ttree: [], + dmap: new t(32768), + dtree: [], + imap: new t(512), + itree: [], + rev15: new t(32768), + lhst: new r(286), + dhst: new r(30), + ihst: new r(19), + lits: new r(15e3), + strt: new t(65536), + prev: new t(32768) + }), function () { + for (var e = UZIP.F.U, t = 0; t < 32768; t++) { + var r = t; + r = (4278255360 & (r = (4042322160 & (r = (3435973836 & (r = (2863311530 & r) >>> 1 | (1431655765 & r) << 1)) >>> 2 | (858993459 & r) << 2)) >>> 4 | (252645135 & r) << 4)) >>> 8 | (16711935 & r) << 8, e.rev15[t] = (r >>> 16 | r << 16) >>> 17 + } + + function pushV(e, t, r) { + for (; 0 != t--;) e.push(0, r) + } + + for (t = 0; t < 32; t++) e.ldef[t] = e.of0[t] << 3 | e.exb[t], e.ddef[t] = e.df0[t] << 4 | e.dxb[t]; + pushV(e.fltree, 144, 8), pushV(e.fltree, 112, 9), pushV(e.fltree, 24, 7), pushV(e.fltree, 8, 8), UZIP.F.makeCodes(e.fltree, 9), UZIP.F.codes2map(e.fltree, 9, e.flmap), UZIP.F.revCodes(e.fltree, 9), pushV(e.fdtree, 32, 5), UZIP.F.makeCodes(e.fdtree, 5), UZIP.F.codes2map(e.fdtree, 5, e.fdmap), UZIP.F.revCodes(e.fdtree, 5), pushV(e.itree, 19, 0), pushV(e.ltree, 286, 0), pushV(e.dtree, 30, 0), pushV(e.ttree, 320, 0) + }() + }({ + get exports() { + return e + }, set exports(t) { + e = t + } + }); + var UZIP = _mergeNamespaces({__proto__: null, default: e}, [e]); + const UPNG = function () { + var e = { + nextZero(e, t) { + for (; 0 != e[t];) t++; + return t + }, + readUshort: (e, t) => e[t] << 8 | e[t + 1], + writeUshort(e, t, r) { + e[t] = r >> 8 & 255, e[t + 1] = 255 & r + }, + readUint: (e, t) => 16777216 * e[t] + (e[t + 1] << 16 | e[t + 2] << 8 | e[t + 3]), + writeUint(e, t, r) { + e[t] = r >> 24 & 255, e[t + 1] = r >> 16 & 255, e[t + 2] = r >> 8 & 255, e[t + 3] = 255 & r + }, + readASCII(e, t, r) { + let i = ""; + for (let o = 0; o < r; o++) i += String.fromCharCode(e[t + o]); + return i + }, + writeASCII(e, t, r) { + for (let i = 0; i < r.length; i++) e[t + i] = r.charCodeAt(i) + }, + readBytes(e, t, r) { + const i = []; + for (let o = 0; o < r; o++) i.push(e[t + o]); + return i + }, + pad: e => e.length < 2 ? `0${e}` : e, + readUTF8(t, r, i) { + let o, a = ""; + for (let o = 0; o < i; o++) a += `%${e.pad(t[r + o].toString(16))}`; + try { + o = decodeURIComponent(a) + } catch (o) { + return e.readASCII(t, r, i) + } + return o + } + }; + + function decodeImage(t, r, i, o) { + const a = r * i, s = _getBPP(o), f = Math.ceil(r * s / 8), l = new Uint8Array(4 * a), + c = new Uint32Array(l.buffer), {ctype: u} = o, {depth: h} = o, d = e.readUshort; + if (6 == u) { + const e = a << 2; + if (8 == h) for (var A = 0; A < e; A += 4) l[A] = t[A], l[A + 1] = t[A + 1], l[A + 2] = t[A + 2], l[A + 3] = t[A + 3]; + if (16 == h) for (A = 0; A < e; A++) l[A] = t[A << 1] + } else if (2 == u) { + const e = o.tabs.tRNS; + if (null == e) { + if (8 == h) for (A = 0; A < a; A++) { + var g = 3 * A; + c[A] = 255 << 24 | t[g + 2] << 16 | t[g + 1] << 8 | t[g] + } + if (16 == h) for (A = 0; A < a; A++) { + g = 6 * A; + c[A] = 255 << 24 | t[g + 4] << 16 | t[g + 2] << 8 | t[g] + } + } else { + var p = e[0]; + const r = e[1], i = e[2]; + if (8 == h) for (A = 0; A < a; A++) { + var m = A << 2; + g = 3 * A; + c[A] = 255 << 24 | t[g + 2] << 16 | t[g + 1] << 8 | t[g], t[g] == p && t[g + 1] == r && t[g + 2] == i && (l[m + 3] = 0) + } + if (16 == h) for (A = 0; A < a; A++) { + m = A << 2, g = 6 * A; + c[A] = 255 << 24 | t[g + 4] << 16 | t[g + 2] << 8 | t[g], d(t, g) == p && d(t, g + 2) == r && d(t, g + 4) == i && (l[m + 3] = 0) + } + } + } else if (3 == u) { + const e = o.tabs.PLTE, s = o.tabs.tRNS, c = s ? s.length : 0; + if (1 == h) for (var w = 0; w < i; w++) { + var v = w * f, b = w * r; + for (A = 0; A < r; A++) { + m = b + A << 2; + var y = 3 * (E = t[v + (A >> 3)] >> 7 - ((7 & A) << 0) & 1); + l[m] = e[y], l[m + 1] = e[y + 1], l[m + 2] = e[y + 2], l[m + 3] = E < c ? s[E] : 255 + } + } + if (2 == h) for (w = 0; w < i; w++) for (v = w * f, b = w * r, A = 0; A < r; A++) { + m = b + A << 2, y = 3 * (E = t[v + (A >> 2)] >> 6 - ((3 & A) << 1) & 3); + l[m] = e[y], l[m + 1] = e[y + 1], l[m + 2] = e[y + 2], l[m + 3] = E < c ? s[E] : 255 + } + if (4 == h) for (w = 0; w < i; w++) for (v = w * f, b = w * r, A = 0; A < r; A++) { + m = b + A << 2, y = 3 * (E = t[v + (A >> 1)] >> 4 - ((1 & A) << 2) & 15); + l[m] = e[y], l[m + 1] = e[y + 1], l[m + 2] = e[y + 2], l[m + 3] = E < c ? s[E] : 255 + } + if (8 == h) for (A = 0; A < a; A++) { + var E; + m = A << 2, y = 3 * (E = t[A]); + l[m] = e[y], l[m + 1] = e[y + 1], l[m + 2] = e[y + 2], l[m + 3] = E < c ? s[E] : 255 + } + } else if (4 == u) { + if (8 == h) for (A = 0; A < a; A++) { + m = A << 2; + var F = t[_ = A << 1]; + l[m] = F, l[m + 1] = F, l[m + 2] = F, l[m + 3] = t[_ + 1] + } + if (16 == h) for (A = 0; A < a; A++) { + var _; + m = A << 2, F = t[_ = A << 2]; + l[m] = F, l[m + 1] = F, l[m + 2] = F, l[m + 3] = t[_ + 2] + } + } else if (0 == u) for (p = o.tabs.tRNS ? o.tabs.tRNS : -1, w = 0; w < i; w++) { + const e = w * f, i = w * r; + if (1 == h) for (var B = 0; B < r; B++) { + var U = (F = 255 * (t[e + (B >>> 3)] >>> 7 - (7 & B) & 1)) == 255 * p ? 0 : 255; + c[i + B] = U << 24 | F << 16 | F << 8 | F + } else if (2 == h) for (B = 0; B < r; B++) { + U = (F = 85 * (t[e + (B >>> 2)] >>> 6 - ((3 & B) << 1) & 3)) == 85 * p ? 0 : 255; + c[i + B] = U << 24 | F << 16 | F << 8 | F + } else if (4 == h) for (B = 0; B < r; B++) { + U = (F = 17 * (t[e + (B >>> 1)] >>> 4 - ((1 & B) << 2) & 15)) == 17 * p ? 0 : 255; + c[i + B] = U << 24 | F << 16 | F << 8 | F + } else if (8 == h) for (B = 0; B < r; B++) { + U = (F = t[e + B]) == p ? 0 : 255; + c[i + B] = U << 24 | F << 16 | F << 8 | F + } else if (16 == h) for (B = 0; B < r; B++) { + F = t[e + (B << 1)], U = d(t, e + (B << 1)) == p ? 0 : 255; + c[i + B] = U << 24 | F << 16 | F << 8 | F + } + } + return l + } + + function _decompress(e, r, i, o) { + const a = _getBPP(e), s = Math.ceil(i * a / 8), f = new Uint8Array((s + 1 + e.interlace) * o); + return r = e.tabs.CgBI ? t(r, f) : _inflate(r, f), 0 == e.interlace ? r = _filterZero(r, e, 0, i, o) : 1 == e.interlace && (r = function _readInterlace(e, t) { + const r = t.width, i = t.height, o = _getBPP(t), a = o >> 3, s = Math.ceil(r * o / 8), + f = new Uint8Array(i * s); + let l = 0; + const c = [0, 0, 4, 0, 2, 0, 1], u = [0, 4, 0, 2, 0, 1, 0], h = [8, 8, 8, 4, 4, 2, 2], + d = [8, 8, 4, 4, 2, 2, 1]; + let A = 0; + for (; A < 7;) { + const p = h[A], m = d[A]; + let w = 0, v = 0, b = c[A]; + for (; b < i;) b += p, v++; + let y = u[A]; + for (; y < r;) y += m, w++; + const E = Math.ceil(w * o / 8); + _filterZero(e, t, l, w, v); + let F = 0, _ = c[A]; + for (; _ < i;) { + let t = u[A], i = l + F * E << 3; + for (; t < r;) { + var g; + if (1 == o) g = (g = e[i >> 3]) >> 7 - (7 & i) & 1, f[_ * s + (t >> 3)] |= g << 7 - ((7 & t) << 0); + if (2 == o) g = (g = e[i >> 3]) >> 6 - (7 & i) & 3, f[_ * s + (t >> 2)] |= g << 6 - ((3 & t) << 1); + if (4 == o) g = (g = e[i >> 3]) >> 4 - (7 & i) & 15, f[_ * s + (t >> 1)] |= g << 4 - ((1 & t) << 2); + if (o >= 8) { + const r = _ * s + t * a; + for (let t = 0; t < a; t++) f[r + t] = e[(i >> 3) + t] + } + i += o, t += m + } + F++, _ += p + } + w * v != 0 && (l += v * (1 + E)), A += 1 + } + return f + }(r, e)), r + } + + function _inflate(e, r) { + return t(new Uint8Array(e.buffer, 2, e.length - 6), r) + } + + var t = function () { + const e = {H: {}}; + return e.H.N = function (t, r) { + const i = Uint8Array; + let o, a, s = 0, f = 0, l = 0, c = 0, u = 0, h = 0, d = 0, A = 0, g = 0; + if (3 == t[0] && 0 == t[1]) return r || new i(0); + const p = e.H, m = p.b, w = p.e, v = p.R, b = p.n, y = p.A, E = p.Z, F = p.m, _ = null == r; + for (_ && (r = new i(t.length >>> 2 << 5)); 0 == s;) if (s = m(t, g, 1), f = m(t, g + 1, 2), g += 3, 0 != f) { + if (_ && (r = e.H.W(r, A + (1 << 17))), 1 == f && (o = F.J, a = F.h, h = 511, d = 31), 2 == f) { + l = w(t, g, 5) + 257, c = w(t, g + 5, 5) + 1, u = w(t, g + 10, 4) + 4, g += 14; + let e = 1; + for (var B = 0; B < 38; B += 2) F.Q[B] = 0, F.Q[B + 1] = 0; + for (B = 0; B < u; B++) { + const r = w(t, g + 3 * B, 3); + F.Q[1 + (F.X[B] << 1)] = r, r > e && (e = r) + } + g += 3 * u, b(F.Q, e), y(F.Q, e, F.u), o = F.w, a = F.d, g = v(F.u, (1 << e) - 1, l + c, t, g, F.v); + const r = p.V(F.v, 0, l, F.C); + h = (1 << r) - 1; + const i = p.V(F.v, l, c, F.D); + d = (1 << i) - 1, b(F.C, r), y(F.C, r, o), b(F.D, i), y(F.D, i, a) + } + for (; ;) { + const e = o[E(t, g) & h]; + g += 15 & e; + const i = e >>> 4; + if (i >>> 8 == 0) r[A++] = i; else { + if (256 == i) break; + { + let e = A + i - 254; + if (i > 264) { + const r = F.q[i - 257]; + e = A + (r >>> 3) + w(t, g, 7 & r), g += 7 & r + } + const o = a[E(t, g) & d]; + g += 15 & o; + const s = o >>> 4, f = F.c[s], l = (f >>> 4) + m(t, g, 15 & f); + for (g += 15 & f; A < e;) r[A] = r[A++ - l], r[A] = r[A++ - l], r[A] = r[A++ - l], r[A] = r[A++ - l]; + A = e + } + } + } + } else { + 0 != (7 & g) && (g += 8 - (7 & g)); + const o = 4 + (g >>> 3), a = t[o - 4] | t[o - 3] << 8; + _ && (r = e.H.W(r, A + a)), r.set(new i(t.buffer, t.byteOffset + o, a), A), g = o + a << 3, A += a + } + return r.length == A ? r : r.slice(0, A) + }, e.H.W = function (e, t) { + const r = e.length; + if (t <= r) return e; + const i = new Uint8Array(r << 1); + return i.set(e, 0), i + }, e.H.R = function (t, r, i, o, a, s) { + const f = e.H.e, l = e.H.Z; + let c = 0; + for (; c < i;) { + const e = t[l(o, a) & r]; + a += 15 & e; + const i = e >>> 4; + if (i <= 15) s[c] = i, c++; else { + let e = 0, t = 0; + 16 == i ? (t = 3 + f(o, a, 2), a += 2, e = s[c - 1]) : 17 == i ? (t = 3 + f(o, a, 3), a += 3) : 18 == i && (t = 11 + f(o, a, 7), a += 7); + const r = c + t; + for (; c < r;) s[c] = e, c++ + } + } + return a + }, e.H.V = function (e, t, r, i) { + let o = 0, a = 0; + const s = i.length >>> 1; + for (; a < r;) { + const r = e[a + t]; + i[a << 1] = 0, i[1 + (a << 1)] = r, r > o && (o = r), a++ + } + for (; a < s;) i[a << 1] = 0, i[1 + (a << 1)] = 0, a++; + return o + }, e.H.n = function (t, r) { + const i = e.H.m, o = t.length; + let a, s, f; + let l; + const c = i.j; + for (var u = 0; u <= r; u++) c[u] = 0; + for (u = 1; u < o; u += 2) c[t[u]]++; + const h = i.K; + for (a = 0, c[0] = 0, s = 1; s <= r; s++) a = a + c[s - 1] << 1, h[s] = a; + for (f = 0; f < o; f += 2) l = t[f + 1], 0 != l && (t[f] = h[l], h[l]++) + }, e.H.A = function (t, r, i) { + const o = t.length, a = e.H.m.r; + for (let e = 0; e < o; e += 2) if (0 != t[e + 1]) { + const o = e >> 1, s = t[e + 1], f = o << 4 | s, l = r - s; + let c = t[e] << l; + const u = c + (1 << l); + for (; c != u;) { + i[a[c] >>> 15 - r] = f, c++ + } + } + }, e.H.l = function (t, r) { + const i = e.H.m.r, o = 15 - r; + for (let e = 0; e < t.length; e += 2) { + const a = t[e] << r - t[e + 1]; + t[e] = i[a] >>> o + } + }, e.H.M = function (e, t, r) { + r <<= 7 & t; + const i = t >>> 3; + e[i] |= r, e[i + 1] |= r >>> 8 + }, e.H.I = function (e, t, r) { + r <<= 7 & t; + const i = t >>> 3; + e[i] |= r, e[i + 1] |= r >>> 8, e[i + 2] |= r >>> 16 + }, e.H.e = function (e, t, r) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8) >>> (7 & t) & (1 << r) - 1 + }, e.H.b = function (e, t, r) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t) & (1 << r) - 1 + }, e.H.Z = function (e, t) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16) >>> (7 & t) + }, e.H.i = function (e, t) { + return (e[t >>> 3] | e[1 + (t >>> 3)] << 8 | e[2 + (t >>> 3)] << 16 | e[3 + (t >>> 3)] << 24) >>> (7 & t) + }, e.H.m = function () { + const e = Uint16Array, t = Uint32Array; + return { + K: new e(16), + j: new e(16), + X: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], + S: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999], + T: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0], + q: new e(32), + p: [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535], + z: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0], + c: new t(32), + J: new e(512), + _: [], + h: new e(32), + $: [], + w: new e(32768), + C: [], + v: [], + d: new e(32768), + D: [], + u: new e(512), + Q: [], + r: new e(32768), + s: new t(286), + Y: new t(30), + a: new t(19), + t: new t(15e3), + k: new e(65536), + g: new e(32768) + } + }(), function () { + const t = e.H.m; + for (var r = 0; r < 32768; r++) { + let e = r; + e = (2863311530 & e) >>> 1 | (1431655765 & e) << 1, e = (3435973836 & e) >>> 2 | (858993459 & e) << 2, e = (4042322160 & e) >>> 4 | (252645135 & e) << 4, e = (4278255360 & e) >>> 8 | (16711935 & e) << 8, t.r[r] = (e >>> 16 | e << 16) >>> 17 + } + + function n(e, t, r) { + for (; 0 != t--;) e.push(0, r) + } + + for (r = 0; r < 32; r++) t.q[r] = t.S[r] << 3 | t.T[r], t.c[r] = t.p[r] << 4 | t.z[r]; + n(t._, 144, 8), n(t._, 112, 9), n(t._, 24, 7), n(t._, 8, 8), e.H.n(t._, 9), e.H.A(t._, 9, t.J), e.H.l(t._, 9), n(t.$, 32, 5), e.H.n(t.$, 5), e.H.A(t.$, 5, t.h), e.H.l(t.$, 5), n(t.Q, 19, 0), n(t.C, 286, 0), n(t.D, 30, 0), n(t.v, 320, 0) + }(), e.H.N + }(); + + function _getBPP(e) { + return [1, null, 3, 1, 2, null, 4][e.ctype] * e.depth + } + + function _filterZero(e, t, r, i, o) { + let a = _getBPP(t); + const s = Math.ceil(i * a / 8); + let f, l; + a = Math.ceil(a / 8); + let c = e[r], u = 0; + if (c > 1 && (e[r] = [0, 0, 1][c - 2]), 3 == c) for (u = a; u < s; u++) e[u + 1] = e[u + 1] + (e[u + 1 - a] >>> 1) & 255; + for (let t = 0; t < o; t++) if (f = r + t * s, l = f + t + 1, c = e[l - 1], u = 0, 0 == c) for (; u < s; u++) e[f + u] = e[l + u]; else if (1 == c) { + for (; u < a; u++) e[f + u] = e[l + u]; + for (; u < s; u++) e[f + u] = e[l + u] + e[f + u - a] + } else if (2 == c) for (; u < s; u++) e[f + u] = e[l + u] + e[f + u - s]; else if (3 == c) { + for (; u < a; u++) e[f + u] = e[l + u] + (e[f + u - s] >>> 1); + for (; u < s; u++) e[f + u] = e[l + u] + (e[f + u - s] + e[f + u - a] >>> 1) + } else { + for (; u < a; u++) e[f + u] = e[l + u] + _paeth(0, e[f + u - s], 0); + for (; u < s; u++) e[f + u] = e[l + u] + _paeth(e[f + u - a], e[f + u - s], e[f + u - a - s]) + } + return e + } + + function _paeth(e, t, r) { + const i = e + t - r, o = i - e, a = i - t, s = i - r; + return o * o <= a * a && o * o <= s * s ? e : a * a <= s * s ? t : r + } + + function _IHDR(t, r, i) { + i.width = e.readUint(t, r), r += 4, i.height = e.readUint(t, r), r += 4, i.depth = t[r], r++, i.ctype = t[r], r++, i.compress = t[r], r++, i.filter = t[r], r++, i.interlace = t[r], r++ + } + + function _copyTile(e, t, r, i, o, a, s, f, l) { + const c = Math.min(t, o), u = Math.min(r, a); + let h = 0, d = 0; + for (let r = 0; r < u; r++) for (let a = 0; a < c; a++) if (s >= 0 && f >= 0 ? (h = r * t + a << 2, d = (f + r) * o + s + a << 2) : (h = (-f + r) * t - s + a << 2, d = r * o + a << 2), 0 == l) i[d] = e[h], i[d + 1] = e[h + 1], i[d + 2] = e[h + 2], i[d + 3] = e[h + 3]; else if (1 == l) { + var A = e[h + 3] * (1 / 255), g = e[h] * A, p = e[h + 1] * A, m = e[h + 2] * A, + w = i[d + 3] * (1 / 255), v = i[d] * w, b = i[d + 1] * w, y = i[d + 2] * w; + const t = 1 - A, r = A + w * t, o = 0 == r ? 0 : 1 / r; + i[d + 3] = 255 * r, i[d + 0] = (g + v * t) * o, i[d + 1] = (p + b * t) * o, i[d + 2] = (m + y * t) * o + } else if (2 == l) { + A = e[h + 3], g = e[h], p = e[h + 1], m = e[h + 2], w = i[d + 3], v = i[d], b = i[d + 1], y = i[d + 2]; + A == w && g == v && p == b && m == y ? (i[d] = 0, i[d + 1] = 0, i[d + 2] = 0, i[d + 3] = 0) : (i[d] = g, i[d + 1] = p, i[d + 2] = m, i[d + 3] = A) + } else if (3 == l) { + A = e[h + 3], g = e[h], p = e[h + 1], m = e[h + 2], w = i[d + 3], v = i[d], b = i[d + 1], y = i[d + 2]; + if (A == w && g == v && p == b && m == y) continue; + if (A < 220 && w > 20) return !1 + } + return !0 + } + + return { + decode: function decode(r) { + const i = new Uint8Array(r); + let o = 8; + const a = e, s = a.readUshort, f = a.readUint, l = {tabs: {}, frames: []}, + c = new Uint8Array(i.length); + let u, h = 0, d = 0; + const A = [137, 80, 78, 71, 13, 10, 26, 10]; + for (var g = 0; g < 8; g++) if (i[g] != A[g]) throw"The input is not a PNG file!"; + for (; o < i.length;) { + const e = a.readUint(i, o); + o += 4; + const r = a.readASCII(i, o, 4); + if (o += 4, "IHDR" == r) _IHDR(i, o, l); else if ("iCCP" == r) { + for (var p = o; 0 != i[p];) p++; + a.readASCII(i, o, p - o), i[p + 1]; + const s = i.slice(p + 2, o + e); + let f = null; + try { + f = _inflate(s) + } catch (e) { + f = t(s) + } + l.tabs[r] = f + } else if ("CgBI" == r) l.tabs[r] = i.slice(o, o + 4); else if ("IDAT" == r) { + for (g = 0; g < e; g++) c[h + g] = i[o + g]; + h += e + } else if ("acTL" == r) l.tabs[r] = { + num_frames: f(i, o), + num_plays: f(i, o + 4) + }, u = new Uint8Array(i.length); else if ("fcTL" == r) { + if (0 != d) (E = l.frames[l.frames.length - 1]).data = _decompress(l, u.slice(0, d), E.rect.width, E.rect.height), d = 0; + const e = {x: f(i, o + 12), y: f(i, o + 16), width: f(i, o + 4), height: f(i, o + 8)}; + let t = s(i, o + 22); + t = s(i, o + 20) / (0 == t ? 100 : t); + const r = {rect: e, delay: Math.round(1e3 * t), dispose: i[o + 24], blend: i[o + 25]}; + l.frames.push(r) + } else if ("fdAT" == r) { + for (g = 0; g < e - 4; g++) u[d + g] = i[o + g + 4]; + d += e - 4 + } else if ("pHYs" == r) l.tabs[r] = [a.readUint(i, o), a.readUint(i, o + 4), i[o + 8]]; else if ("cHRM" == r) { + l.tabs[r] = []; + for (g = 0; g < 8; g++) l.tabs[r].push(a.readUint(i, o + 4 * g)) + } else if ("tEXt" == r || "zTXt" == r) { + null == l.tabs[r] && (l.tabs[r] = {}); + var m = a.nextZero(i, o), w = a.readASCII(i, o, m - o), v = o + e - m - 1; + if ("tEXt" == r) y = a.readASCII(i, m + 1, v); else { + var b = _inflate(i.slice(m + 2, m + 2 + v)); + y = a.readUTF8(b, 0, b.length) + } + l.tabs[r][w] = y + } else if ("iTXt" == r) { + null == l.tabs[r] && (l.tabs[r] = {}); + m = 0, p = o; + m = a.nextZero(i, p); + w = a.readASCII(i, p, m - p); + const t = i[p = m + 1]; + var y; + i[p + 1], p += 2, m = a.nextZero(i, p), a.readASCII(i, p, m - p), p = m + 1, m = a.nextZero(i, p), a.readUTF8(i, p, m - p); + v = e - ((p = m + 1) - o); + if (0 == t) y = a.readUTF8(i, p, v); else { + b = _inflate(i.slice(p, p + v)); + y = a.readUTF8(b, 0, b.length) + } + l.tabs[r][w] = y + } else if ("PLTE" == r) l.tabs[r] = a.readBytes(i, o, e); else if ("hIST" == r) { + const e = l.tabs.PLTE.length / 3; + l.tabs[r] = []; + for (g = 0; g < e; g++) l.tabs[r].push(s(i, o + 2 * g)) + } else if ("tRNS" == r) 3 == l.ctype ? l.tabs[r] = a.readBytes(i, o, e) : 0 == l.ctype ? l.tabs[r] = s(i, o) : 2 == l.ctype && (l.tabs[r] = [s(i, o), s(i, o + 2), s(i, o + 4)]); else if ("gAMA" == r) l.tabs[r] = a.readUint(i, o) / 1e5; else if ("sRGB" == r) l.tabs[r] = i[o]; else if ("bKGD" == r) 0 == l.ctype || 4 == l.ctype ? l.tabs[r] = [s(i, o)] : 2 == l.ctype || 6 == l.ctype ? l.tabs[r] = [s(i, o), s(i, o + 2), s(i, o + 4)] : 3 == l.ctype && (l.tabs[r] = i[o]); else if ("IEND" == r) break; + o += e, a.readUint(i, o), o += 4 + } + var E; + return 0 != d && ((E = l.frames[l.frames.length - 1]).data = _decompress(l, u.slice(0, d), E.rect.width, E.rect.height)), l.data = _decompress(l, c, l.width, l.height), delete l.compress, delete l.interlace, delete l.filter, l + }, toRGBA8: function toRGBA8(e) { + const t = e.width, r = e.height; + if (null == e.tabs.acTL) return [decodeImage(e.data, t, r, e).buffer]; + const i = []; + null == e.frames[0].data && (e.frames[0].data = e.data); + const o = t * r * 4, a = new Uint8Array(o), s = new Uint8Array(o), f = new Uint8Array(o); + for (let c = 0; c < e.frames.length; c++) { + const u = e.frames[c], h = u.rect.x, d = u.rect.y, A = u.rect.width, g = u.rect.height, + p = decodeImage(u.data, A, g, e); + if (0 != c) for (var l = 0; l < o; l++) f[l] = a[l]; + if (0 == u.blend ? _copyTile(p, A, g, a, t, r, h, d, 0) : 1 == u.blend && _copyTile(p, A, g, a, t, r, h, d, 1), i.push(a.buffer.slice(0)), 0 == u.dispose) ; else if (1 == u.dispose) _copyTile(s, A, g, a, t, r, h, d, 0); else if (2 == u.dispose) for (l = 0; l < o; l++) a[l] = f[l] + } + return i + }, _paeth: _paeth, _copyTile: _copyTile, _bin: e + } + }(); + !function () { + const {_copyTile: e} = UPNG, {_bin: t} = UPNG, r = UPNG._paeth; + var i = { + table: function () { + const e = new Uint32Array(256); + for (let t = 0; t < 256; t++) { + let r = t; + for (let e = 0; e < 8; e++) 1 & r ? r = 3988292384 ^ r >>> 1 : r >>>= 1; + e[t] = r + } + return e + }(), update(e, t, r, o) { + for (let a = 0; a < o; a++) e = i.table[255 & (e ^ t[r + a])] ^ e >>> 8; + return e + }, crc: (e, t, r) => 4294967295 ^ i.update(4294967295, e, t, r) + }; + + function addErr(e, t, r, i) { + t[r] += e[0] * i >> 4, t[r + 1] += e[1] * i >> 4, t[r + 2] += e[2] * i >> 4, t[r + 3] += e[3] * i >> 4 + } + + function N(e) { + return Math.max(0, Math.min(255, e)) + } + + function D(e, t) { + const r = e[0] - t[0], i = e[1] - t[1], o = e[2] - t[2], a = e[3] - t[3]; + return r * r + i * i + o * o + a * a + } + + function dither(e, t, r, i, o, a, s) { + null == s && (s = 1); + const f = i.length, l = []; + for (var c = 0; c < f; c++) { + const e = i[c]; + l.push([e >>> 0 & 255, e >>> 8 & 255, e >>> 16 & 255, e >>> 24 & 255]) + } + for (c = 0; c < f; c++) { + let e = 4294967295; + for (var u = 0, h = 0; h < f; h++) { + var d = D(l[c], l[h]); + h != c && d < e && (e = d, u = h) + } + } + const A = new Uint32Array(o.buffer), g = new Int16Array(t * r * 4), + p = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5]; + for (c = 0; c < p.length; c++) p[c] = 255 * ((p[c] + .5) / 16 - .5); + for (let o = 0; o < r; o++) for (let w = 0; w < t; w++) { + var m; + c = 4 * (o * t + w); + if (2 != s) m = [N(e[c] + g[c]), N(e[c + 1] + g[c + 1]), N(e[c + 2] + g[c + 2]), N(e[c + 3] + g[c + 3])]; else { + d = p[4 * (3 & o) + (3 & w)]; + m = [N(e[c] + d), N(e[c + 1] + d), N(e[c + 2] + d), N(e[c + 3] + d)] + } + u = 0; + let v = 16777215; + for (h = 0; h < f; h++) { + const e = D(m, l[h]); + e < v && (v = e, u = h) + } + const b = l[u], y = [m[0] - b[0], m[1] - b[1], m[2] - b[2], m[3] - b[3]]; + 1 == s && (w != t - 1 && addErr(y, g, c + 4, 7), o != r - 1 && (0 != w && addErr(y, g, c + 4 * t - 4, 3), addErr(y, g, c + 4 * t, 5), w != t - 1 && addErr(y, g, c + 4 * t + 4, 1))), a[c >> 2] = u, A[c >> 2] = i[u] + } + } + + function _main(e, r, o, a, s) { + null == s && (s = {}); + const {crc: f} = i, l = t.writeUint, c = t.writeUshort, u = t.writeASCII; + let h = 8; + const d = e.frames.length > 1; + let A, g = !1, p = 33 + (d ? 20 : 0); + if (null != s.sRGB && (p += 13), null != s.pHYs && (p += 21), null != s.iCCP && (A = pako.deflate(s.iCCP), p += 21 + A.length + 4), 3 == e.ctype) { + for (var m = e.plte.length, w = 0; w < m; w++) e.plte[w] >>> 24 != 255 && (g = !0); + p += 8 + 3 * m + 4 + (g ? 8 + 1 * m + 4 : 0) + } + for (var v = 0; v < e.frames.length; v++) { + d && (p += 38), p += (F = e.frames[v]).cimg.length + 12, 0 != v && (p += 4) + } + p += 12; + const b = new Uint8Array(p), y = [137, 80, 78, 71, 13, 10, 26, 10]; + for (w = 0; w < 8; w++) b[w] = y[w]; + if (l(b, h, 13), h += 4, u(b, h, "IHDR"), h += 4, l(b, h, r), h += 4, l(b, h, o), h += 4, b[h] = e.depth, h++, b[h] = e.ctype, h++, b[h] = 0, h++, b[h] = 0, h++, b[h] = 0, h++, l(b, h, f(b, h - 17, 17)), h += 4, null != s.sRGB && (l(b, h, 1), h += 4, u(b, h, "sRGB"), h += 4, b[h] = s.sRGB, h++, l(b, h, f(b, h - 5, 5)), h += 4), null != s.iCCP) { + const e = 13 + A.length; + l(b, h, e), h += 4, u(b, h, "iCCP"), h += 4, u(b, h, "ICC profile"), h += 11, h += 2, b.set(A, h), h += A.length, l(b, h, f(b, h - (e + 4), e + 4)), h += 4 + } + if (null != s.pHYs && (l(b, h, 9), h += 4, u(b, h, "pHYs"), h += 4, l(b, h, s.pHYs[0]), h += 4, l(b, h, s.pHYs[1]), h += 4, b[h] = s.pHYs[2], h++, l(b, h, f(b, h - 13, 13)), h += 4), d && (l(b, h, 8), h += 4, u(b, h, "acTL"), h += 4, l(b, h, e.frames.length), h += 4, l(b, h, null != s.loop ? s.loop : 0), h += 4, l(b, h, f(b, h - 12, 12)), h += 4), 3 == e.ctype) { + l(b, h, 3 * (m = e.plte.length)), h += 4, u(b, h, "PLTE"), h += 4; + for (w = 0; w < m; w++) { + const t = 3 * w, r = e.plte[w], i = 255 & r, o = r >>> 8 & 255, a = r >>> 16 & 255; + b[h + t + 0] = i, b[h + t + 1] = o, b[h + t + 2] = a + } + if (h += 3 * m, l(b, h, f(b, h - 3 * m - 4, 3 * m + 4)), h += 4, g) { + l(b, h, m), h += 4, u(b, h, "tRNS"), h += 4; + for (w = 0; w < m; w++) b[h + w] = e.plte[w] >>> 24 & 255; + h += m, l(b, h, f(b, h - m - 4, m + 4)), h += 4 + } + } + let E = 0; + for (v = 0; v < e.frames.length; v++) { + var F = e.frames[v]; + d && (l(b, h, 26), h += 4, u(b, h, "fcTL"), h += 4, l(b, h, E++), h += 4, l(b, h, F.rect.width), h += 4, l(b, h, F.rect.height), h += 4, l(b, h, F.rect.x), h += 4, l(b, h, F.rect.y), h += 4, c(b, h, a[v]), h += 2, c(b, h, 1e3), h += 2, b[h] = F.dispose, h++, b[h] = F.blend, h++, l(b, h, f(b, h - 30, 30)), h += 4); + const t = F.cimg; + l(b, h, (m = t.length) + (0 == v ? 0 : 4)), h += 4; + const r = h; + u(b, h, 0 == v ? "IDAT" : "fdAT"), h += 4, 0 != v && (l(b, h, E++), h += 4), b.set(t, h), h += m, l(b, h, f(b, r, h - r)), h += 4 + } + return l(b, h, 0), h += 4, u(b, h, "IEND"), h += 4, l(b, h, f(b, h - 4, 4)), h += 4, b.buffer + } + + function compressPNG(e, t, r) { + for (let i = 0; i < e.frames.length; i++) { + const o = e.frames[i]; + o.rect.width; + const a = o.rect.height, s = new Uint8Array(a * o.bpl + a); + o.cimg = _filterZero(o.img, a, o.bpp, o.bpl, s, t, r) + } + } + + function compress(t, r, i, o, a) { + const s = a[0], f = a[1], l = a[2], c = a[3], u = a[4], h = a[5]; + let d = 6, A = 8, g = 255; + for (var p = 0; p < t.length; p++) { + const e = new Uint8Array(t[p]); + for (var m = e.length, w = 0; w < m; w += 4) g &= e[w + 3] + } + const v = 255 != g, b = function framize(t, r, i, o, a, s) { + const f = []; + for (var l = 0; l < t.length; l++) { + const h = new Uint8Array(t[l]), A = new Uint32Array(h.buffer); + var c; + let g = 0, p = 0, m = r, w = i, v = o ? 1 : 0; + if (0 != l) { + const b = s || o || 1 == l || 0 != f[l - 2].dispose ? 1 : 2; + let y = 0, E = 1e9; + for (let e = 0; e < b; e++) { + var u = new Uint8Array(t[l - 1 - e]); + const o = new Uint32Array(t[l - 1 - e]); + let s = r, f = i, c = -1, h = -1; + for (let e = 0; e < i; e++) for (let t = 0; t < r; t++) { + A[d = e * r + t] != o[d] && (t < s && (s = t), t > c && (c = t), e < f && (f = e), e > h && (h = e)) + } + -1 == c && (s = f = c = h = 0), a && (1 == (1 & s) && s--, 1 == (1 & f) && f--); + const v = (c - s + 1) * (h - f + 1); + v < E && (E = v, y = e, g = s, p = f, m = c - s + 1, w = h - f + 1) + } + u = new Uint8Array(t[l - 1 - y]); + 1 == y && (f[l - 1].dispose = 2), c = new Uint8Array(m * w * 4), e(u, r, i, c, m, w, -g, -p, 0), v = e(h, r, i, c, m, w, -g, -p, 3) ? 1 : 0, 1 == v ? _prepareDiff(h, r, i, c, { + x: g, + y: p, + width: m, + height: w + }) : e(h, r, i, c, m, w, -g, -p, 0) + } else c = h.slice(0); + f.push({rect: {x: g, y: p, width: m, height: w}, img: c, blend: v, dispose: 0}) + } + if (o) for (l = 0; l < f.length; l++) { + if (1 == (A = f[l]).blend) continue; + const e = A.rect, o = f[l - 1].rect, s = Math.min(e.x, o.x), c = Math.min(e.y, o.y), u = { + x: s, + y: c, + width: Math.max(e.x + e.width, o.x + o.width) - s, + height: Math.max(e.y + e.height, o.y + o.height) - c + }; + f[l - 1].dispose = 1, l - 1 != 0 && _updateFrame(t, r, i, f, l - 1, u, a), _updateFrame(t, r, i, f, l, u, a) + } + let h = 0; + if (1 != t.length) for (var d = 0; d < f.length; d++) { + var A; + h += (A = f[d]).rect.width * A.rect.height + } + return f + }(t, r, i, s, f, l), y = {}, E = [], F = []; + if (0 != o) { + const e = []; + for (w = 0; w < b.length; w++) e.push(b[w].img.buffer); + const t = function concatRGBA(e) { + let t = 0; + for (var r = 0; r < e.length; r++) t += e[r].byteLength; + const i = new Uint8Array(t); + let o = 0; + for (r = 0; r < e.length; r++) { + const t = new Uint8Array(e[r]), a = t.length; + for (let e = 0; e < a; e += 4) { + let r = t[e], a = t[e + 1], s = t[e + 2]; + const f = t[e + 3]; + 0 == f && (r = a = s = 0), i[o + e] = r, i[o + e + 1] = a, i[o + e + 2] = s, i[o + e + 3] = f + } + o += a + } + return i.buffer + }(e), r = quantize(t, o); + for (w = 0; w < r.plte.length; w++) E.push(r.plte[w].est.rgba); + let i = 0; + for (w = 0; w < b.length; w++) { + const e = (B = b[w]).img.length; + var _ = new Uint8Array(r.inds.buffer, i >> 2, e >> 2); + F.push(_); + const t = new Uint8Array(r.abuf, i, e); + h && dither(B.img, B.rect.width, B.rect.height, E, t, _), B.img.set(t), i += e + } + } else for (p = 0; p < b.length; p++) { + var B = b[p]; + const e = new Uint32Array(B.img.buffer); + var U = B.rect.width; + m = e.length, _ = new Uint8Array(m); + F.push(_); + for (w = 0; w < m; w++) { + const t = e[w]; + if (0 != w && t == e[w - 1]) _[w] = _[w - 1]; else if (w > U && t == e[w - U]) _[w] = _[w - U]; else { + let e = y[t]; + if (null == e && (y[t] = e = E.length, E.push(t), E.length >= 300)) break; + _[w] = e + } + } + } + const C = E.length; + C <= 256 && 0 == u && (A = C <= 2 ? 1 : C <= 4 ? 2 : C <= 16 ? 4 : 8, A = Math.max(A, c)); + for (p = 0; p < b.length; p++) { + (B = b[p]).rect.x, B.rect.y; + U = B.rect.width; + const e = B.rect.height; + let t = B.img; + new Uint32Array(t.buffer); + let r = 4 * U, i = 4; + if (C <= 256 && 0 == u) { + r = Math.ceil(A * U / 8); + var I = new Uint8Array(r * e); + const o = F[p]; + for (let t = 0; t < e; t++) { + w = t * r; + const e = t * U; + if (8 == A) for (var Q = 0; Q < U; Q++) I[w + Q] = o[e + Q]; else if (4 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 1)] |= o[e + Q] << 4 - 4 * (1 & Q); else if (2 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 2)] |= o[e + Q] << 6 - 2 * (3 & Q); else if (1 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 3)] |= o[e + Q] << 7 - 1 * (7 & Q) + } + t = I, d = 3, i = 1 + } else if (0 == v && 1 == b.length) { + I = new Uint8Array(U * e * 3); + const o = U * e; + for (w = 0; w < o; w++) { + const e = 3 * w, r = 4 * w; + I[e] = t[r], I[e + 1] = t[r + 1], I[e + 2] = t[r + 2] + } + t = I, d = 2, i = 3, r = 3 * U + } + B.img = t, B.bpl = r, B.bpp = i + } + return {ctype: d, depth: A, plte: E, frames: b} + } + + function _updateFrame(t, r, i, o, a, s, f) { + const l = Uint8Array, c = Uint32Array, u = new l(t[a - 1]), h = new c(t[a - 1]), + d = a + 1 < t.length ? new l(t[a + 1]) : null, A = new l(t[a]), g = new c(A.buffer); + let p = r, m = i, w = -1, v = -1; + for (let e = 0; e < s.height; e++) for (let t = 0; t < s.width; t++) { + const i = s.x + t, f = s.y + e, l = f * r + i, c = g[l]; + 0 == c || 0 == o[a - 1].dispose && h[l] == c && (null == d || 0 != d[4 * l + 3]) || (i < p && (p = i), i > w && (w = i), f < m && (m = f), f > v && (v = f)) + } + -1 == w && (p = m = w = v = 0), f && (1 == (1 & p) && p--, 1 == (1 & m) && m--), s = { + x: p, + y: m, + width: w - p + 1, + height: v - m + 1 + }; + const b = o[a]; + b.rect = s, b.blend = 1, b.img = new Uint8Array(s.width * s.height * 4), 0 == o[a - 1].dispose ? (e(u, r, i, b.img, s.width, s.height, -s.x, -s.y, 0), _prepareDiff(A, r, i, b.img, s)) : e(A, r, i, b.img, s.width, s.height, -s.x, -s.y, 0) + } + + function _prepareDiff(t, r, i, o, a) { + e(t, r, i, o, a.width, a.height, -a.x, -a.y, 2) + } + + function _filterZero(e, t, r, i, o, a, s) { + const f = []; + let l, c = [0, 1, 2, 3, 4]; + -1 != a ? c = [a] : (t * i > 5e5 || 1 == r) && (c = [0]), s && (l = {level: 0}); + const u = UZIP; + for (var h = 0; h < c.length; h++) { + for (let a = 0; a < t; a++) _filterLine(o, e, a, i, r, c[h]); + f.push(u.deflate(o, l)) + } + let d, A = 1e9; + for (h = 0; h < f.length; h++) f[h].length < A && (d = h, A = f[h].length); + return f[d] + } + + function _filterLine(e, t, i, o, a, s) { + const f = i * o; + let l = f + i; + if (e[l] = s, l++, 0 == s) if (o < 500) for (var c = 0; c < o; c++) e[l + c] = t[f + c]; else e.set(new Uint8Array(t.buffer, f, o), l); else if (1 == s) { + for (c = 0; c < a; c++) e[l + c] = t[f + c]; + for (c = a; c < o; c++) e[l + c] = t[f + c] - t[f + c - a] + 256 & 255 + } else if (0 == i) { + for (c = 0; c < a; c++) e[l + c] = t[f + c]; + if (2 == s) for (c = a; c < o; c++) e[l + c] = t[f + c]; + if (3 == s) for (c = a; c < o; c++) e[l + c] = t[f + c] - (t[f + c - a] >> 1) + 256 & 255; + if (4 == s) for (c = a; c < o; c++) e[l + c] = t[f + c] - r(t[f + c - a], 0, 0) + 256 & 255 + } else { + if (2 == s) for (c = 0; c < o; c++) e[l + c] = t[f + c] + 256 - t[f + c - o] & 255; + if (3 == s) { + for (c = 0; c < a; c++) e[l + c] = t[f + c] + 256 - (t[f + c - o] >> 1) & 255; + for (c = a; c < o; c++) e[l + c] = t[f + c] + 256 - (t[f + c - o] + t[f + c - a] >> 1) & 255 + } + if (4 == s) { + for (c = 0; c < a; c++) e[l + c] = t[f + c] + 256 - r(0, t[f + c - o], 0) & 255; + for (c = a; c < o; c++) e[l + c] = t[f + c] + 256 - r(t[f + c - a], t[f + c - o], t[f + c - a - o]) & 255 + } + } + } + + function quantize(e, t) { + const r = new Uint8Array(e), i = r.slice(0), o = new Uint32Array(i.buffer), a = getKDtree(i, t), + s = a[0], f = a[1], l = r.length, c = new Uint8Array(l >> 2); + let u; + if (r.length < 2e7) for (var h = 0; h < l; h += 4) { + u = getNearest(s, d = r[h] * (1 / 255), A = r[h + 1] * (1 / 255), g = r[h + 2] * (1 / 255), p = r[h + 3] * (1 / 255)), c[h >> 2] = u.ind, o[h >> 2] = u.est.rgba + } else for (h = 0; h < l; h += 4) { + var d = r[h] * (1 / 255), A = r[h + 1] * (1 / 255), g = r[h + 2] * (1 / 255), + p = r[h + 3] * (1 / 255); + for (u = s; u.left;) u = planeDst(u.est, d, A, g, p) <= 0 ? u.left : u.right; + c[h >> 2] = u.ind, o[h >> 2] = u.est.rgba + } + return {abuf: i.buffer, inds: c, plte: f} + } + + function getKDtree(e, t, r) { + null == r && (r = 1e-4); + const i = new Uint32Array(e.buffer), + o = {i0: 0, i1: e.length, bst: null, est: null, tdst: 0, left: null, right: null}; + o.bst = stats(e, o.i0, o.i1), o.est = estats(o.bst); + const a = [o]; + for (; a.length < t;) { + let t = 0, o = 0; + for (var s = 0; s < a.length; s++) a[s].est.L > t && (t = a[s].est.L, o = s); + if (t < r) break; + const f = a[o], l = splitPixels(e, i, f.i0, f.i1, f.est.e, f.est.eMq255); + if (f.i0 >= l || f.i1 <= l) { + f.est.L = 0; + continue + } + const c = {i0: f.i0, i1: l, bst: null, est: null, tdst: 0, left: null, right: null}; + c.bst = stats(e, c.i0, c.i1), c.est = estats(c.bst); + const u = {i0: l, i1: f.i1, bst: null, est: null, tdst: 0, left: null, right: null}; + u.bst = {R: [], m: [], N: f.bst.N - c.bst.N}; + for (s = 0; s < 16; s++) u.bst.R[s] = f.bst.R[s] - c.bst.R[s]; + for (s = 0; s < 4; s++) u.bst.m[s] = f.bst.m[s] - c.bst.m[s]; + u.est = estats(u.bst), f.left = c, f.right = u, a[o] = c, a.push(u) + } + a.sort(((e, t) => t.bst.N - e.bst.N)); + for (s = 0; s < a.length; s++) a[s].ind = s; + return [o, a] + } + + function getNearest(e, t, r, i, o) { + if (null == e.left) return e.tdst = function dist(e, t, r, i, o) { + const a = t - e[0], s = r - e[1], f = i - e[2], l = o - e[3]; + return a * a + s * s + f * f + l * l + }(e.est.q, t, r, i, o), e; + const a = planeDst(e.est, t, r, i, o); + let s = e.left, f = e.right; + a > 0 && (s = e.right, f = e.left); + const l = getNearest(s, t, r, i, o); + if (l.tdst <= a * a) return l; + const c = getNearest(f, t, r, i, o); + return c.tdst < l.tdst ? c : l + } + + function planeDst(e, t, r, i, o) { + const {e: a} = e; + return a[0] * t + a[1] * r + a[2] * i + a[3] * o - e.eMq + } + + function splitPixels(e, t, r, i, o, a) { + for (i -= 4; r < i;) { + for (; vecDot(e, r, o) <= a;) r += 4; + for (; vecDot(e, i, o) > a;) i -= 4; + if (r >= i) break; + const s = t[r >> 2]; + t[r >> 2] = t[i >> 2], t[i >> 2] = s, r += 4, i -= 4 + } + for (; vecDot(e, r, o) > a;) r -= 4; + return r + 4 + } + + function vecDot(e, t, r) { + return e[t] * r[0] + e[t + 1] * r[1] + e[t + 2] * r[2] + e[t + 3] * r[3] + } + + function stats(e, t, r) { + const i = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], o = [0, 0, 0, 0], a = r - t >> 2; + for (let a = t; a < r; a += 4) { + const t = e[a] * (1 / 255), r = e[a + 1] * (1 / 255), s = e[a + 2] * (1 / 255), + f = e[a + 3] * (1 / 255); + o[0] += t, o[1] += r, o[2] += s, o[3] += f, i[0] += t * t, i[1] += t * r, i[2] += t * s, i[3] += t * f, i[5] += r * r, i[6] += r * s, i[7] += r * f, i[10] += s * s, i[11] += s * f, i[15] += f * f + } + return i[4] = i[1], i[8] = i[2], i[9] = i[6], i[12] = i[3], i[13] = i[7], i[14] = i[11], { + R: i, + m: o, + N: a + } + } + + function estats(e) { + const {R: t} = e, {m: r} = e, {N: i} = e, a = r[0], s = r[1], f = r[2], l = r[3], + c = 0 == i ? 0 : 1 / i, + u = [t[0] - a * a * c, t[1] - a * s * c, t[2] - a * f * c, t[3] - a * l * c, t[4] - s * a * c, t[5] - s * s * c, t[6] - s * f * c, t[7] - s * l * c, t[8] - f * a * c, t[9] - f * s * c, t[10] - f * f * c, t[11] - f * l * c, t[12] - l * a * c, t[13] - l * s * c, t[14] - l * f * c, t[15] - l * l * c], + h = u, d = o; + let A = [Math.random(), Math.random(), Math.random(), Math.random()], g = 0, p = 0; + if (0 != i) for (let e = 0; e < 16 && (A = d.multVec(h, A), p = Math.sqrt(d.dot(A, A)), A = d.sml(1 / p, A), !(0 != e && Math.abs(p - g) < 1e-9)); e++) g = p; + const m = [a * c, s * c, f * c, l * c]; + return { + Cov: u, + q: m, + e: A, + L: g, + eMq255: d.dot(d.sml(255, m), A), + eMq: d.dot(A, m), + rgba: (Math.round(255 * m[3]) << 24 | Math.round(255 * m[2]) << 16 | Math.round(255 * m[1]) << 8 | Math.round(255 * m[0]) << 0) >>> 0 + } + } + + var o = { + multVec: (e, t) => [e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3], e[4] * t[0] + e[5] * t[1] + e[6] * t[2] + e[7] * t[3], e[8] * t[0] + e[9] * t[1] + e[10] * t[2] + e[11] * t[3], e[12] * t[0] + e[13] * t[1] + e[14] * t[2] + e[15] * t[3]], + dot: (e, t) => e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3], + sml: (e, t) => [e * t[0], e * t[1], e * t[2], e * t[3]] + }; + UPNG.encode = function encode(e, t, r, i, o, a, s) { + null == i && (i = 0), null == s && (s = !1); + const f = compress(e, t, r, i, [!1, !1, !1, 0, s, !1]); + return compressPNG(f, -1), _main(f, t, r, o, a) + }, UPNG.encodeLL = function encodeLL(e, t, r, i, o, a, s, f) { + const l = {ctype: 0 + (1 == i ? 0 : 2) + (0 == o ? 0 : 4), depth: a, frames: []}, c = (i + o) * a, + u = c * t; + for (let i = 0; i < e.length; i++) l.frames.push({ + rect: {x: 0, y: 0, width: t, height: r}, + img: new Uint8Array(e[i]), + blend: 0, + dispose: 1, + bpp: Math.ceil(c / 8), + bpl: Math.ceil(u / 8) + }); + return compressPNG(l, 0, !0), _main(l, t, r, s, f) + }, UPNG.encode.compress = compress, UPNG.encode.dither = dither, UPNG.quantize = quantize, UPNG.quantize.getKDtree = getKDtree, UPNG.quantize.getNearest = getNearest + }(); + const t = { + toArrayBuffer(e, r) { + const i = e.width, o = e.height, a = i << 2, s = e.getContext("2d").getImageData(0, 0, i, o), + f = new Uint32Array(s.data.buffer), l = (32 * i + 31) / 32 << 2, c = l * o, u = 122 + c, + h = new ArrayBuffer(u), d = new DataView(h), A = 1 << 20; + let g, p, m, w, v = A, b = 0, y = 0, E = 0; + + function set16(e) { + d.setUint16(y, e, !0), y += 2 + } + + function set32(e) { + d.setUint32(y, e, !0), y += 4 + } + + function seek(e) { + y += e + } + + set16(19778), set32(u), seek(4), set32(122), set32(108), set32(i), set32(-o >>> 0), set16(1), set16(32), set32(3), set32(c), set32(2835), set32(2835), seek(8), set32(16711680), set32(65280), set32(255), set32(4278190080), set32(1466527264), function convert() { + for (; b < o && v > 0;) { + for (w = 122 + b * l, g = 0; g < a;) v--, p = f[E++], m = p >>> 24, d.setUint32(w + g, p << 8 | m), g += 4; + b++ + } + E < f.length ? (v = A, setTimeout(convert, t._dly)) : r(h) + }() + }, toBlob(e, t) { + this.toArrayBuffer(e, (e => { + t(new Blob([e], {type: "image/bmp"})) + })) + }, _dly: 9 + }; + var r = { + CHROME: "CHROME", + FIREFOX: "FIREFOX", + DESKTOP_SAFARI: "DESKTOP_SAFARI", + IE: "IE", + IOS: "IOS", + ETC: "ETC" + }, i = { + [r.CHROME]: 16384, + [r.FIREFOX]: 11180, + [r.DESKTOP_SAFARI]: 16384, + [r.IE]: 8192, + [r.IOS]: 4096, + [r.ETC]: 8192 + }; + const o = "undefined" != typeof window, + a = "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope, + s = o && window.cordova && window.cordova.require && window.cordova.require("cordova/modulemapper"), + CustomFile = (o || a) && (s && s.getOriginalSymbol(window, "File") || "undefined" != typeof File && File), + CustomFileReader = (o || a) && (s && s.getOriginalSymbol(window, "FileReader") || "undefined" != typeof FileReader && FileReader); + + function getFilefromDataUrl(e, t, r = Date.now()) { + return new Promise((i => { + const o = e.split(","), a = o[0].match(/:(.*?);/)[1], s = globalThis.atob(o[1]); + let f = s.length; + const l = new Uint8Array(f); + for (; f--;) l[f] = s.charCodeAt(f); + const c = new Blob([l], {type: a}); + c.name = t, c.lastModified = r, i(c) + })) + } + + function getDataUrlFromFile(e) { + return new Promise(((t, r) => { + const i = new CustomFileReader; + i.onload = () => t(i.result), i.onerror = e => r(e), i.readAsDataURL(e) + })) + } + + function loadImage(e) { + return new Promise(((t, r) => { + const i = new Image; + i.onload = () => t(i), i.onerror = e => r(e), i.src = e + })) + } + + function getBrowserName() { + if (void 0 !== getBrowserName.cachedResult) return getBrowserName.cachedResult; + let e = r.ETC; + const {userAgent: t} = navigator; + return /Chrom(e|ium)/i.test(t) ? e = r.CHROME : /iP(ad|od|hone)/i.test(t) && /WebKit/i.test(t) ? e = r.IOS : /Safari/i.test(t) ? e = r.DESKTOP_SAFARI : /Firefox/i.test(t) ? e = r.FIREFOX : (/MSIE/i.test(t) || !0 == !!document.documentMode) && (e = r.IE), getBrowserName.cachedResult = e, getBrowserName.cachedResult + } + + function approximateBelowMaximumCanvasSizeOfBrowser(e, t) { + const r = getBrowserName(), o = i[r]; + let a = e, s = t, f = a * s; + const l = a > s ? s / a : a / s; + for (; f > o * o;) { + const e = (o + a) / 2, t = (o + s) / 2; + e < t ? (s = t, a = t * l) : (s = e * l, a = e), f = a * s + } + return {width: a, height: s} + } + + function getNewCanvasAndCtx(e, t) { + let r, i; + try { + if (r = new OffscreenCanvas(e, t), i = r.getContext("2d"), null === i) throw new Error("getContext of OffscreenCanvas returns null") + } catch (e) { + r = document.createElement("canvas"), i = r.getContext("2d") + } + return r.width = e, r.height = t, [r, i] + } + + function drawImageInCanvas(e, t) { + const { + width: r, + height: i + } = approximateBelowMaximumCanvasSizeOfBrowser(e.width, e.height), [o, a] = getNewCanvasAndCtx(r, i); + return t && /jpe?g/.test(t) && (a.fillStyle = "white", a.fillRect(0, 0, o.width, o.height)), a.drawImage(e, 0, 0, o.width, o.height), o + } + + function isIOS() { + return void 0 !== isIOS.cachedResult || (isIOS.cachedResult = ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "undefined" != typeof document && "ontouchend" in document), isIOS.cachedResult + } + + function drawFileInCanvas(e, t = {}) { + return new Promise((function (i, o) { + let a, s; + var $Try_2_Post = function () { + try { + return s = drawImageInCanvas(a, t.fileType || e.type), i([a, s]) + } catch (e) { + return o(e) + } + }, $Try_2_Catch = function (t) { + try { + 0; + var $Try_3_Catch = function (e) { + try { + throw e + } catch (e) { + return o(e) + } + }; + try { + let t; + return getDataUrlFromFile(e).then((function (e) { + try { + return t = e, loadImage(t).then((function (e) { + try { + return a = e, function () { + try { + return $Try_2_Post() + } catch (e) { + return o(e) + } + }() + } catch (e) { + return $Try_3_Catch(e) + } + }), $Try_3_Catch) + } catch (e) { + return $Try_3_Catch(e) + } + }), $Try_3_Catch) + } catch (e) { + $Try_3_Catch(e) + } + } catch (e) { + return o(e) + } + }; + try { + if (isIOS() || [r.DESKTOP_SAFARI, r.MOBILE_SAFARI].includes(getBrowserName())) throw new Error("Skip createImageBitmap on IOS and Safari"); + return createImageBitmap(e).then((function (e) { + try { + return a = e, $Try_2_Post() + } catch (e) { + return $Try_2_Catch() + } + }), $Try_2_Catch) + } catch (e) { + $Try_2_Catch() + } + })) + } + + function canvasToFile(e, r, i, o, a = 1) { + return new Promise((function (s, f) { + let l; + if ("image/png" === r) { + let c, u, h; + return c = e.getContext("2d"), ({data: u} = c.getImageData(0, 0, e.width, e.height)), h = UPNG.encode([u.buffer], e.width, e.height, 4096 * a), l = new Blob([h], {type: r}), l.name = i, l.lastModified = o, $If_4.call(this) + } + { + if ("image/bmp" === r) return new Promise((r => t.toBlob(e, r))).then(function (e) { + try { + return l = e, l.name = i, l.lastModified = o, $If_5.call(this) + } catch (e) { + return f(e) + } + }.bind(this), f); + { + if ("function" == typeof OffscreenCanvas && e instanceof OffscreenCanvas) return e.convertToBlob({ + type: r, + quality: a + }).then(function (e) { + try { + return l = e, l.name = i, l.lastModified = o, $If_6.call(this) + } catch (e) { + return f(e) + } + }.bind(this), f); + { + let d; + return d = e.toDataURL(r, a), getFilefromDataUrl(d, i, o).then(function (e) { + try { + return l = e, $If_6.call(this) + } catch (e) { + return f(e) + } + }.bind(this), f) + } + + function $If_6() { + return $If_5.call(this) + } + } + + function $If_5() { + return $If_4.call(this) + } + } + + function $If_4() { + return s(l) + } + })) + } + + function cleanupCanvasMemory(e) { + e.width = 0, e.height = 0 + } + + function isAutoOrientationInBrowser() { + return new Promise((function (e, t) { + let r, i, o, a, s; + return void 0 !== isAutoOrientationInBrowser.cachedResult ? e(isAutoOrientationInBrowser.cachedResult) : (r = "data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==", getFilefromDataUrl("data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==", "test.jpg", Date.now()).then((function (r) { + try { + return i = r, drawFileInCanvas(i).then((function (r) { + try { + return o = r[1], canvasToFile(o, i.type, i.name, i.lastModified).then((function (r) { + try { + return a = r, cleanupCanvasMemory(o), drawFileInCanvas(a).then((function (r) { + try { + return s = r[0], isAutoOrientationInBrowser.cachedResult = 1 === s.width && 2 === s.height, e(isAutoOrientationInBrowser.cachedResult) + } catch (e) { + return t(e) + } + }), t) + } catch (e) { + return t(e) + } + }), t) + } catch (e) { + return t(e) + } + }), t) + } catch (e) { + return t(e) + } + }), t)) + })) + } + + function getExifOrientation(e) { + return new Promise(((t, r) => { + const i = new CustomFileReader; + i.onload = e => { + const r = new DataView(e.target.result); + if (65496 != r.getUint16(0, !1)) return t(-2); + const i = r.byteLength; + let o = 2; + for (; o < i;) { + if (r.getUint16(o + 2, !1) <= 8) return t(-1); + const e = r.getUint16(o, !1); + if (o += 2, 65505 == e) { + if (1165519206 != r.getUint32(o += 2, !1)) return t(-1); + const e = 18761 == r.getUint16(o += 6, !1); + o += r.getUint32(o + 4, e); + const i = r.getUint16(o, e); + o += 2; + for (let a = 0; a < i; a++) if (274 == r.getUint16(o + 12 * a, e)) return t(r.getUint16(o + 12 * a + 8, e)) + } else { + if (65280 != (65280 & e)) break; + o += r.getUint16(o, !1) + } + } + return t(-1) + }, i.onerror = e => r(e), i.readAsArrayBuffer(e) + })) + } + + function handleMaxWidthOrHeight(e, t) { + const {width: r} = e, {height: i} = e, {maxWidthOrHeight: o} = t; + let a, s = e; + return isFinite(o) && (r > o || i > o) && ([s, a] = getNewCanvasAndCtx(r, i), r > i ? (s.width = o, s.height = i / r * o) : (s.width = r / i * o, s.height = o), a.drawImage(e, 0, 0, s.width, s.height), cleanupCanvasMemory(e)), s + } + + function followExifOrientation(e, t) { + const {width: r} = e, {height: i} = e, [o, a] = getNewCanvasAndCtx(r, i); + switch (t > 4 && t < 9 ? (o.width = i, o.height = r) : (o.width = r, o.height = i), t) { + case 2: + a.transform(-1, 0, 0, 1, r, 0); + break; + case 3: + a.transform(-1, 0, 0, -1, r, i); + break; + case 4: + a.transform(1, 0, 0, -1, 0, i); + break; + case 5: + a.transform(0, 1, 1, 0, 0, 0); + break; + case 6: + a.transform(0, 1, -1, 0, i, 0); + break; + case 7: + a.transform(0, -1, -1, 0, i, r); + break; + case 8: + a.transform(0, -1, 1, 0, 0, r) + } + return a.drawImage(e, 0, 0, r, i), cleanupCanvasMemory(e), o + } + + function compress(e, t, r = 0) { + return new Promise((function (i, o) { + let a, s, f, l, c, u, h, d, A, g, p, m, w, v, b, y, E, F, _, B; + + function incProgress(e = 5) { + if (t.signal && t.signal.aborted) throw t.signal.reason; + a += e, t.onProgress(Math.min(a, 100)) + } + + function setProgress(e) { + if (t.signal && t.signal.aborted) throw t.signal.reason; + a = Math.min(Math.max(e, a), 100), t.onProgress(a) + } + + return a = r, s = t.maxIteration || 10, f = 1024 * t.maxSizeMB * 1024, incProgress(), drawFileInCanvas(e, t).then(function (r) { + try { + return [, l] = r, incProgress(), c = handleMaxWidthOrHeight(l, t), incProgress(), new Promise((function (r, i) { + var o; + if (!(o = t.exifOrientation)) return getExifOrientation(e).then(function (e) { + try { + return o = e, $If_2.call(this) + } catch (e) { + return i(e) + } + }.bind(this), i); + + function $If_2() { + return r(o) + } + + return $If_2.call(this) + })).then(function (r) { + try { + return u = r, incProgress(), isAutoOrientationInBrowser().then(function (r) { + try { + return h = r ? c : followExifOrientation(c, u), incProgress(), d = t.initialQuality || 1, A = t.fileType || e.type, canvasToFile(h, A, e.name, e.lastModified, d).then(function (r) { + try { + { + if (g = r, incProgress(), p = g.size > f, m = g.size > e.size, !p && !m) return setProgress(100), i(g); + var a; + + function $Loop_3() { + if (s-- && (b > f || b > w)) { + let t, r; + return t = B ? .95 * _.width : _.width, r = B ? .95 * _.height : _.height, [E, F] = getNewCanvasAndCtx(t, r), F.drawImage(_, 0, 0, t, r), d *= "image/png" === A ? .85 : .95, canvasToFile(E, A, e.name, e.lastModified, d).then((function (e) { + try { + return y = e, cleanupCanvasMemory(_), _ = E, b = y.size, setProgress(Math.min(99, Math.floor((v - b) / (v - f) * 100))), $Loop_3 + } catch (e) { + return o(e) + } + }), o) + } + return [1] + } + + return w = e.size, v = g.size, b = v, _ = h, B = !t.alwaysKeepResolution && p, (a = function (e) { + for (; e;) { + if (e.then) return void e.then(a, o); + try { + if (e.pop) { + if (e.length) return e.pop() ? $Loop_3_exit.call(this) : e; + e = $Loop_3 + } else e = e.call(this) + } catch (e) { + return o(e) + } + } + }.bind(this))($Loop_3); + + function $Loop_3_exit() { + return cleanupCanvasMemory(_), cleanupCanvasMemory(E), cleanupCanvasMemory(c), cleanupCanvasMemory(h), cleanupCanvasMemory(l), setProgress(100), i(y) + } + } + } catch (u) { + return o(u) + } + }.bind(this), o) + } catch (e) { + return o(e) + } + }.bind(this), o) + } catch (e) { + return o(e) + } + }.bind(this), o) + } catch (e) { + return o(e) + } + }.bind(this), o) + })) + } + + const f = "\nlet scriptImported = false\nself.addEventListener('message', async (e) => {\n const { file, id, imageCompressionLibUrl, options } = e.data\n options.onProgress = (progress) => self.postMessage({ progress, id })\n try {\n if (!scriptImported) {\n // console.log('[worker] importScripts', imageCompressionLibUrl)\n self.importScripts(imageCompressionLibUrl)\n scriptImported = true\n }\n // console.log('[worker] self', self)\n const compressedFile = await imageCompression(file, options)\n self.postMessage({ file: compressedFile, id })\n } catch (e) {\n // console.error('[worker] error', e)\n self.postMessage({ error: e.message + '\\n' + e.stack, id })\n }\n})\n"; + let l; + + function compressOnWebWorker(e, t) { + return new Promise(((r, i) => { + l || (l = function createWorkerScriptURL(e) { + const t = []; + return "function" == typeof e ? t.push(`(${e})()`) : t.push(e), URL.createObjectURL(new Blob(t)) + }(f)); + const o = new Worker(l); + o.addEventListener("message", (function handler(e) { + if (t.signal && t.signal.aborted) o.terminate(); else if (void 0 === e.data.progress) { + if (e.data.error) return i(new Error(e.data.error)), void o.terminate(); + r(e.data.file), o.terminate() + } else t.onProgress(e.data.progress) + })), o.addEventListener("error", i), t.signal && t.signal.addEventListener("abort", (() => { + i(t.signal.reason), o.terminate() + })), o.postMessage({ + file: e, + imageCompressionLibUrl: t.libURL, + options: {...t, onProgress: void 0, signal: void 0} + }) + })) + } + + function imageCompression(e, t) { + return new Promise((function (r, i) { + let o, a, s, f, l, c; + if (o = {...t}, s = 0, ({onProgress: f} = o), o.maxSizeMB = o.maxSizeMB || Number.POSITIVE_INFINITY, l = "boolean" != typeof o.useWebWorker || o.useWebWorker, delete o.useWebWorker, o.onProgress = e => { + s = e, "function" == typeof f && f(s) + }, !(1 || e instanceof Blob || e instanceof CustomFile)) return i(new Error("The file given is not an instance of Blob or File")); + if (!/^image/.test(e.type)) return i(new Error("The file given is not an image")); + if (c = "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope, !l || "function" != typeof Worker || c) return compress(e, o).then(function (e) { + try { + return a = e, $If_4.call(this) + } catch (e) { + return i(e) + } + }.bind(this), i); + var u = function () { + try { + return $If_4.call(this) + } catch (e) { + return i(e) + } + }.bind(this), $Try_1_Catch = function (t) { + try { + return compress(e, o).then((function (e) { + try { + return a = e, u() + } catch (e) { + return i(e) + } + }), i) + } catch (e) { + return i(e) + } + }; + try { + return o.libURL = o.libURL || "https://cdn.bootcdn.net/ajax/libs/browser-image-compression/2.0.2/browser-image-compression.js", compressOnWebWorker(e, o).then((function (e) { + try { + return a = e, u() + } catch (e) { + return $Try_1_Catch() + } + }), $Try_1_Catch) + } catch (e) { + $Try_1_Catch() + } + + function $If_4() { + try { + a.name = e.name, a.lastModified = e.lastModified + } catch (e) { + } + try { + o.preserveExif && "image/jpeg" === e.type && (!o.fileType || o.fileType && o.fileType === e.type) && (a = copyExifWithoutOrientation(e, a)) + } catch (e) { + } + return r(a) + } + })) + } + + return imageCompression.getDataUrlFromFile = getDataUrlFromFile, imageCompression.getFilefromDataUrl = getFilefromDataUrl, imageCompression.loadImage = loadImage, imageCompression.drawImageInCanvas = drawImageInCanvas, imageCompression.drawFileInCanvas = drawFileInCanvas, imageCompression.canvasToFile = canvasToFile, imageCompression.getExifOrientation = getExifOrientation, imageCompression.handleMaxWidthOrHeight = handleMaxWidthOrHeight, imageCompression.followExifOrientation = followExifOrientation, imageCompression.cleanupCanvasMemory = cleanupCanvasMemory, imageCompression.isAutoOrientationInBrowser = isAutoOrientationInBrowser, imageCompression.approximateBelowMaximumCanvasSizeOfBrowser = approximateBelowMaximumCanvasSizeOfBrowser, imageCompression.copyExifWithoutOrientation = copyExifWithoutOrientation, imageCompression.getBrowserName = getBrowserName, imageCompression.version = "2.0.2", imageCompression + })); + return { + // { + // maxSizeMB: number, // (default: Number.POSITIVE_INFINITY) + // maxWidthOrHeight: number, // compressedFile will scale down by ratio to a point that width or height is smaller than maxWidthOrHeight (default: undefined) + // // but, automatically reduce the size to smaller than the maximum Canvas size supported by each browser. + // // Please check the Caveat part for details. + // onProgress: Function, // optional, a function takes one progress argument (percentage from 0 to 100) + // useWebWorker: boolean, // optional, use multi-thread web worker, fallback to run in main-thread (default: true) + // libURL: string, // optional, the libURL of this library for importing script in Web Worker (default: https://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.js) + // preserveExif: boolean, // optional, use preserve Exif metadata for JPEG image e.g., Camera model, Focal length, etc (default: false) + // + // signal: AbortSignal, // optional, to abort / cancel the compression + // + // // following options are for advanced users + // maxIteration: number, // optional, max number of iteration to compress the image (default: 10) + // exifOrientation: number, // optional, see https://stackoverflow.com/a/32490603/10395024 + // fileType: string, // optional, fileType override e.g., 'image/jpeg', 'image/png' (default: file.type) + // initialQuality: number, // optional, initial quality value between 0 and 1 (default: 1) + // alwaysKeepResolution: boolean // optional, only reduce quality, always keep width and height (default: false) + // } + compress: function (file, option) { + return imageCompression(file, option); + } + }; + })(); // core/dialog.js -UE.dialog = (function () { - return { - loadingPlaceholder: function (me) { - var loadingId = "loading_" + (+new Date()).toString(36); - me.focus(); - me.execCommand( - "inserthtml", - '' - ); - return loadingId; - }, - removeLoadingPlaceholder: function (me, loadingId) { - var loader = me.document.getElementById(loadingId); - if (loader) { - domUtils.remove(loader, false); - } - }, - tipError: function (me, title) { - me.fireEvent("showmessage", { - content: title, - type: "error", - timeout: 4000 - }); - } - } -})(); + UE.dialog = (function () { + return { + loadingPlaceholder: function (me) { + var loadingId = "loading_" + (+new Date()).toString(36); + me.focus(); + me.execCommand( + "inserthtml", + '' + ); + return loadingId; + }, + removeLoadingPlaceholder: function (me, loadingId) { + var loader = me.document.getElementById(loadingId); + if (loader) { + domUtils.remove(loader, false); + } + }, + tipError: function (me, title) { + me.fireEvent("showmessage", { + content: title, + type: "error", + timeout: 4000 + }); + } + } + })(); // core/filterword.js -/** - * UE过滤word的静态方法 - * @file - */ + /** + * UE过滤word的静态方法 + * @file + */ -/** - * UEditor公用空间,UEditor所有的功能都挂载在该空间下 - * @module UE - */ + /** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @module UE + */ -/** - * 根据传入html字符串过滤word - * @module UE - * @since 1.2.6.1 - * @method filterWord - * @param { String } html html字符串 - * @return { String } 已过滤后的结果字符串 - * @example - * ```javascript - * UE.filterWord(html); - * ``` - */ -var filterWord = (UE.filterWord = (function() { - //是否是word过来的内容 - function isWordDocument(str) { - return /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|<(v|o):|lang=)/gi.test( - str - ); - } - //去掉小数 - function transUnit(v) { - v = v.replace(/[\d.]+\w+/g, function(m) { - return utils.transUnitToPx(m); - }); - return v; - } - - function filterPasteWord(str) { - return ( - str - .replace(/[\t\r\n]+/g, " ") - .replace(//gi, "") - //转换图片 - .replace(/]*>[\s\S]*?.<\/v:shape>/gi, function(str) { - //opera能自己解析出image所这里直接返回空 - if (browser.opera) { - return ""; - } - try { - //有可能是bitmap占为图,无用,直接过滤掉,主要体现在粘贴excel表格中 - if (/Bitmap/i.test(str)) { - return ""; - } - var width = str.match(/width:([ \d.]*p[tx])/i)[1], - height = str.match(/height:([ \d.]*p[tx])/i)[1], - src = str.match(/src=\s*"([^"]*)"/i)[1]; - return ( - '' + /** + * 根据传入html字符串过滤word + * @module UE + * @since 1.2.6.1 + * @method filterWord + * @param { String } html html字符串 + * @return { String } 已过滤后的结果字符串 + * @example + * ```javascript + * UE.filterWord(html); + * ``` + */ + var filterWord = (UE.filterWord = (function () { + //是否是word过来的内容 + function isWordDocument(str) { + return /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|<(v|o):|lang=)/gi.test( + str ); - } catch (e) { - return ""; - } - }) - //针对wps添加的多余标签处理 - .replace(/<\/?div[^>]*>/g, "") - //去掉多余的属性 - .replace(/v:\w+=(["']?)[^'"]+\1/g, "") - .replace( - /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, - "" - ) - .replace( - /

]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, - "

$1

" - ) - //去掉多余的属性 - .replace(/\s+(class|lang|align)\s*=\s*(['"]?)([\w-]+)\2/gi, function( - str, - name, - marks, - val - ) { - //保留list的标示 - return name == "class" && val == "MsoListParagraph" ? str : ""; - }) - //清除多余的font/span不能匹配 有可能是空格 - .replace(/<(font|span)[^>]*>(\s*)<\/\1>/gi, function(a, b, c) { - return c.replace(/[\t\r\n ]+/g, " "); - }) - //处理style的问题 - .replace(/(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function( - str, - tag, - tmp, - style - ) { - var n = [], - s = style - .replace(/^\s+|\s+$/, "") - .replace(/'/g, "'") - .replace(/"/gi, "'") - .replace(/[\d.]+(cm|pt)/g, function(str) { - return utils.transUnitToPx(str); - }) - .split(/;\s*/g); + } - for (var i = 0, v; (v = s[i]); i++) { - var name, - value, - parts = v.split(":"); + //去掉小数 + function transUnit(v) { + v = v.replace(/[\d.]+\w+/g, function (m) { + return utils.transUnitToPx(m); + }); + return v; + } - if (parts.length == 2) { - name = parts[0].toLowerCase(); - value = parts[1].toLowerCase(); - if ( - (/^(background)\w*/.test(name) && - value.replace(/(initial|\s)/g, "").length == 0) || - (/^(margin)\w*/.test(name) && /^0\w+$/.test(value)) - ) { - continue; - } + function filterPasteWord(str) { + return ( + str + .replace(/[\t\r\n]+/g, " ") + .replace(//gi, "") + //转换图片 + .replace(/]*>[\s\S]*?.<\/v:shape>/gi, function (str) { + //opera能自己解析出image所这里直接返回空 + if (browser.opera) { + return ""; + } + try { + //有可能是bitmap占为图,无用,直接过滤掉,主要体现在粘贴excel表格中 + if (/Bitmap/i.test(str)) { + return ""; + } + var width = str.match(/width:([ \d.]*p[tx])/i)[1], + height = str.match(/height:([ \d.]*p[tx])/i)[1], + src = str.match(/src=\s*"([^"]*)"/i)[1]; + return ( + '' + ); + } catch (e) { + return ""; + } + }) + //针对wps添加的多余标签处理 + .replace(/<\/?div[^>]*>/g, "") + //去掉多余的属性 + .replace(/v:\w+=(["']?)[^'"]+\1/g, "") + .replace( + /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, + "" + ) + .replace( + /

]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, + "

$1

" + ) + //去掉多余的属性 + .replace(/\s+(class|lang|align)\s*=\s*(['"]?)([\w-]+)\2/gi, function ( + str, + name, + marks, + val + ) { + //保留list的标示 + return name == "class" && val == "MsoListParagraph" ? str : ""; + }) + //清除多余的font/span不能匹配 有可能是空格 + .replace(/<(font|span)[^>]*>(\s*)<\/\1>/gi, function (a, b, c) { + return c.replace(/[\t\r\n ]+/g, " "); + }) + //处理style的问题 + .replace(/(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function ( + str, + tag, + tmp, + style + ) { + var n = [], + s = style + .replace(/^\s+|\s+$/, "") + .replace(/'/g, "'") + .replace(/"/gi, "'") + .replace(/[\d.]+(cm|pt)/g, function (str) { + return utils.transUnitToPx(str); + }) + .split(/;\s*/g); - switch (name) { - case "mso-padding-alt": - case "mso-padding-top-alt": - case "mso-padding-right-alt": - case "mso-padding-bottom-alt": - case "mso-padding-left-alt": - case "mso-margin-alt": - case "mso-margin-top-alt": - case "mso-margin-right-alt": - case "mso-margin-bottom-alt": - case "mso-margin-left-alt": - //ie下会出现挤到一起的情况 - //case "mso-table-layout-alt": - case "mso-height": - case "mso-width": - case "mso-vertical-align-alt": - //trace:1819 ff下会解析出padding在table上 - if (!/]/.test(html)) { - return UE.htmlparser(html).children[0]; - } else { - return new uNode({ - type: "element", - children: [], - tagName: html - }); - } - }; - uNode.createText = function(data, noTrans) { - return new UE.uNode({ - type: "text", - data: noTrans ? data : utils.unhtml(data || "") - }); - }; - function nodeToHtml(node, arr, formatter, current) { - switch (node.type) { - case "root": - for (var i = 0, ci; (ci = node.children[i++]); ) { - //插入新行 - if ( - formatter && - ci.type == "element" && - !dtd.$inlineWithA[ci.tagName] && - i > 1 - ) { - insertLine(arr, current, true); - insertIndent(arr, current); - } - nodeToHtml(ci, arr, formatter, current); - } - break; - case "text": - isText(node, arr); - break; - case "element": - isElement(node, arr, formatter, current); - break; - case "comment": - isComment(node, arr, formatter); - } - return arr; - } - - function isText(node, arr) { - if (node.parentNode.tagName == "pre") { - //源码模式下输入html标签,不能做转换处理,直接输出 - arr.push(node.data); - } else { - arr.push( - notTransTagName[node.parentNode.tagName] - ? utils.html(node.data) - : node.data.replace(/[ ]{2}/g, "  ") - ); - } - } - - function isElement(node, arr, formatter, current) { - var attrhtml = ""; - if (node.attrs) { - attrhtml = []; - var attrs = node.attrs; - for (var a in attrs) { - //这里就针对 - //

'

- //这里边的\"做转换,要不用innerHTML直接被截断了,属性src - //有可能做的不够 - attrhtml.push( - a + - (attrs[a] !== undefined - ? '="' + - (notTransAttrs[a] - ? utils.html(attrs[a]).replace(/["]/g, function(a) { - return """; - }) - : utils.unhtml(attrs[a])) + - '"' - : "") - ); - } - attrhtml = attrhtml.join(" "); - } - arr.push( - "<" + - node.tagName + - (attrhtml ? " " + attrhtml : "") + - (dtd.$empty[node.tagName] ? "/" : "") + - ">" - ); - //插入新行 - if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != "pre") { - if (node.children && node.children.length) { - current = insertLine(arr, current, true); - insertIndent(arr, current); - } - } - if (node.children && node.children.length) { - for (var i = 0, ci; (ci = node.children[i++]); ) { - if ( - formatter && - ci.type == "element" && - !dtd.$inlineWithA[ci.tagName] && - i > 1 - ) { - insertLine(arr, current); - insertIndent(arr, current); - } - nodeToHtml(ci, arr, formatter, current); - } - } - if (!dtd.$empty[node.tagName]) { - if ( - formatter && - !dtd.$inlineWithA[node.tagName] && - node.tagName != "pre" - ) { - if (node.children && node.children.length) { - current = insertLine(arr, current); - insertIndent(arr, current); - } - } - arr.push(""); - } - } - - function isComment(node, arr) { - arr.push(""); - } - - function getNodeById(root, id) { - var node; - if (root.type == "element" && root.getAttr("id") == id) { - return root; - } - if (root.children && root.children.length) { - for (var i = 0, ci; (ci = root.children[i++]); ) { - if ((node = getNodeById(ci, id))) { - return node; - } - } - } - } - - function getNodesByTagName(node, tagName, arr) { - if (node.type == "element" && node.tagName == tagName) { - arr.push(node); - } - if (node.children && node.children.length) { - for (var i = 0, ci; (ci = node.children[i++]); ) { - getNodesByTagName(ci, tagName, arr); - } - } - } - function nodeTraversal(root, fn) { - if (root.children && root.children.length) { - for (var i = 0, ci; (ci = root.children[i]); ) { - nodeTraversal(ci, fn); - //ci被替换的情况,这里就不再走 fn了 - if (ci.parentNode) { - if (ci.children && ci.children.length) { - fn(ci); - } - if (ci.parentNode) i++; - } - } - } else { - fn(root); - } - } - uNode.prototype = { - /** - * 当前节点对象,转换成html文本 - * @method toHtml - * @return { String } 返回转换后的html字符串 - * @example - * ```javascript - * node.toHtml(); - * ``` + (function () { + /** + * 编辑器模拟的节点类 + * @unfile + * @module UE + * @class uNode */ - /** - * 当前节点对象,转换成html文本 - * @method toHtml - * @param { Boolean } formatter 是否格式化返回值 - * @return { String } 返回转换后的html字符串 + /** + * 通过一个键值对,创建一个uNode对象 + * @constructor + * @param { Object } attr 传入要创建的uNode的初始属性 * @example * ```javascript - * node.toHtml( true ); + * var node = new uNode({ + * type:'element', + * tagName:'span', + * attrs:{style:'font-size:14px;'} + * }) * ``` */ - toHtml: function(formatter) { - var arr = []; - nodeToHtml(this, arr, formatter, 0); - return arr.join(""); - }, - - /** - * 获取节点的html内容 - * @method innerHTML - * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 - * @return { String } 返回节点的html内容 - * @example - * ```javascript - * var htmlstr = node.innerHTML(); - * ``` - */ - - /** - * 设置节点的html内容 - * @method innerHTML - * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 - * @param { String } htmlstr 传入要设置的html内容 - * @return { UE.uNode } 返回节点本身 - * @example - * ```javascript - * node.innerHTML('text'); - * ``` - */ - innerHTML: function(htmlstr) { - if (this.type != "element" || dtd.$empty[this.tagName]) { - return this; - } - if (utils.isString(htmlstr)) { - if (this.children) { - for (var i = 0, ci; (ci = this.children[i++]); ) { - ci.parentNode = null; - } - } - this.children = []; - var tmpRoot = UE.htmlparser(htmlstr); - for (var i = 0, ci; (ci = tmpRoot.children[i++]); ) { - this.children.push(ci); - ci.parentNode = this; - } - return this; - } else { - var tmpRoot = new UE.uNode({ - type: "root", - children: this.children + var uNode = (UE.uNode = function (obj) { + this.type = obj.type; + this.data = obj.data; + this.tagName = obj.tagName; + this.parentNode = obj.parentNode; + this.attrs = obj.attrs || {}; + this.children = obj.children; }); - return tmpRoot.toHtml(); - } - }, - /** - * 获取节点的纯文本内容 - * @method innerText - * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 - * @return { String } 返回节点的存文本内容 - * @example - * ```javascript - * var textStr = node.innerText(); - * ``` - */ + var notTransAttrs = { + href: 1, + src: 1, + _src: 1, + _href: 1, + cdata_data: 1 + }; - /** - * 设置节点的纯文本内容 - * @method innerText - * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 - * @param { String } textStr 传入要设置的文本内容 - * @return { UE.uNode } 返回节点本身 - * @example - * ```javascript - * node.innerText('text'); - * ``` - */ - innerText: function(textStr, noTrans) { - if (this.type != "element" || dtd.$empty[this.tagName]) { - return this; - } - if (textStr) { - if (this.children) { - for (var i = 0, ci; (ci = this.children[i++]); ) { - ci.parentNode = null; - } - } - this.children = []; - this.appendChild(uNode.createText(textStr, noTrans)); - return this; - } else { - return this.toHtml().replace(/<[^>]+>/g, ""); - } - }, + var notTransTagName = { + style: 1, + script: 1 + }; - /** - * 获取当前对象的data属性 - * @method getData - * @return { Object } 若节点的type值是elemenet,返回空字符串,否则返回节点的data属性 - * @example - * ```javascript - * node.getData(); - * ``` - */ - getData: function() { - if (this.type == "element") return ""; - return this.data; - }, + var indentChar = " ", + breakChar = "\n"; - /** - * 获取当前节点下的第一个子节点 - * @method firstChild - * @return { UE.uNode } 返回第一个子节点 - * @example - * ```javascript - * node.firstChild(); //返回第一个子节点 - * ``` - */ - firstChild: function() { - // if (this.type != 'element' || dtd.$empty[this.tagName]) { - // return this; - // } - return this.children ? this.children[0] : null; - }, + function insertLine(arr, current, begin) { + arr.push(breakChar); + return current + (begin ? 1 : -1); + } - /** - * 获取当前节点下的最后一个子节点 - * @method lastChild - * @return { UE.uNode } 返回最后一个子节点 - * @example - * ```javascript - * node.lastChild(); //返回最后一个子节点 - * ``` - */ - lastChild: function() { - // if (this.type != 'element' || dtd.$empty[this.tagName] ) { - // return this; - // } - return this.children ? this.children[this.children.length - 1] : null; - }, - - /** - * 获取和当前节点有相同父亲节点的前一个节点 - * @method previousSibling - * @return { UE.uNode } 返回前一个节点 - * @example - * ```javascript - * node.children[2].previousSibling(); //返回子节点node.children[1] - * ``` - */ - previousSibling: function() { - var parent = this.parentNode; - for (var i = 0, ci; (ci = parent.children[i]); i++) { - if (ci === this) { - return i == 0 ? null : parent.children[i - 1]; - } - } - }, - - /** - * 获取和当前节点有相同父亲节点的后一个节点 - * @method nextSibling - * @return { UE.uNode } 返回后一个节点,找不到返回null - * @example - * ```javascript - * node.children[2].nextSibling(); //如果有,返回子节点node.children[3] - * ``` - */ - nextSibling: function() { - var parent = this.parentNode; - for (var i = 0, ci; (ci = parent.children[i++]); ) { - if (ci === this) { - return parent.children[i]; - } - } - }, - - /** - * 用新的节点替换当前节点 - * @method replaceChild - * @param { UE.uNode } target 要替换成该节点参数 - * @param { UE.uNode } source 要被替换掉的节点 - * @return { UE.uNode } 返回替换之后的节点对象 - * @example - * ```javascript - * node.replaceChild(newNode, childNode); //用newNode替换childNode,childNode是node的子节点 - * ``` - */ - replaceChild: function(target, source) { - if (this.children) { - if (target.parentNode) { - target.parentNode.removeChild(target); - } - for (var i = 0, ci; (ci = this.children[i]); i++) { - if (ci === source) { - this.children.splice(i, 1, target); - source.parentNode = null; - target.parentNode = this; - return target; - } - } - } - }, - - /** - * 在节点的子节点列表最后位置插入一个节点 - * @method appendChild - * @param { UE.uNode } node 要插入的节点 - * @return { UE.uNode } 返回刚插入的子节点 - * @example - * ```javascript - * node.appendChild( newNode ); //在node内插入子节点newNode - * ``` - */ - appendChild: function(node) { - if ( - this.type == "root" || - (this.type == "element" && !dtd.$empty[this.tagName]) - ) { - if (!this.children) { - this.children = []; - } - if (node.parentNode) { - node.parentNode.removeChild(node); - } - for (var i = 0, ci; (ci = this.children[i]); i++) { - if (ci === node) { - this.children.splice(i, 1); - break; - } - } - this.children.push(node); - node.parentNode = this; - return node; - } - }, - - /** - * 在传入节点的前面插入一个节点 - * @method insertBefore - * @param { UE.uNode } target 要插入的节点 - * @param { UE.uNode } source 在该参数节点前面插入 - * @return { UE.uNode } 返回刚插入的子节点 - * @example - * ```javascript - * node.parentNode.insertBefore(newNode, node); //在node节点后面插入newNode - * ``` - */ - insertBefore: function(target, source) { - if (this.children) { - if (target.parentNode) { - target.parentNode.removeChild(target); - } - for (var i = 0, ci; (ci = this.children[i]); i++) { - if (ci === source) { - this.children.splice(i, 0, target); - target.parentNode = this; - return target; - } - } - } - }, - - /** - * 在传入节点的后面插入一个节点 - * @method insertAfter - * @param { UE.uNode } target 要插入的节点 - * @param { UE.uNode } source 在该参数节点后面插入 - * @return { UE.uNode } 返回刚插入的子节点 - * @example - * ```javascript - * node.parentNode.insertAfter(newNode, node); //在node节点后面插入newNode - * ``` - */ - insertAfter: function(target, source) { - if (this.children) { - if (target.parentNode) { - target.parentNode.removeChild(target); - } - for (var i = 0, ci; (ci = this.children[i]); i++) { - if (ci === source) { - this.children.splice(i + 1, 0, target); - target.parentNode = this; - return target; - } - } - } - }, - - /** - * 从当前节点的子节点列表中,移除节点 - * @method removeChild - * @param { UE.uNode } node 要移除的节点引用 - * @param { Boolean } keepChildren 是否保留移除节点的子节点,若传入true,自动把移除节点的子节点插入到移除的位置 - * @return { * } 返回刚移除的子节点 - * @example - * ```javascript - * node.removeChild(childNode,true); //在node的子节点列表中移除child节点,并且吧child的子节点插入到移除的位置 - * ``` - */ - removeChild: function(node, keepChildren) { - if (this.children) { - for (var i = 0, ci; (ci = this.children[i]); i++) { - if (ci === node) { - this.children.splice(i, 1); - ci.parentNode = null; - if (keepChildren && ci.children && ci.children.length) { - for (var j = 0, cj; (cj = ci.children[j]); j++) { - this.children.splice(i + j, 0, cj); - cj.parentNode = this; - } + function insertIndent(arr, current) { + //插入缩进 + for (var i = 0; i < current; i++) { + arr.push(indentChar); } - return ci; - } } - } - }, - /** - * 获取当前节点所代表的元素属性,即获取attrs对象下的属性值 - * @method getAttr - * @param { String } attrName 要获取的属性名称 - * @return { * } 返回attrs对象下的属性值 - * @example - * ```javascript - * node.getAttr('title'); - * ``` - */ - getAttr: function(attrName) { - return this.attrs && this.attrs[attrName.toLowerCase()]; - }, + //创建uNode的静态方法 + //支持标签和html + uNode.createElement = function (html) { + if (/[<>]/.test(html)) { + return UE.htmlparser(html).children[0]; + } else { + return new uNode({ + type: "element", + children: [], + tagName: html + }); + } + }; + uNode.createText = function (data, noTrans) { + return new UE.uNode({ + type: "text", + data: noTrans ? data : utils.unhtml(data || "") + }); + }; - /** - * 设置当前节点所代表的元素属性,即设置attrs对象下的属性值 - * @method setAttr - * @param { String } attrName 要设置的属性名称 - * @param { * } attrVal 要设置的属性值,类型视设置的属性而定 - * @return { * } 返回attrs对象下的属性值 - * @example - * ```javascript - * node.setAttr('title','标题'); - * ``` - */ - setAttr: function(attrName, attrVal) { - if (!attrName) { - delete this.attrs; - return; - } - if (!this.attrs) { - this.attrs = {}; - } - if (utils.isObject(attrName)) { - for (var a in attrName) { - if (!attrName[a]) { - delete this.attrs[a]; - } else { - this.attrs[a.toLowerCase()] = attrName[a]; - } + function nodeToHtml(node, arr, formatter, current) { + switch (node.type) { + case "root": + for (var i = 0, ci; (ci = node.children[i++]);) { + //插入新行 + if ( + formatter && + ci.type == "element" && + !dtd.$inlineWithA[ci.tagName] && + i > 1 + ) { + insertLine(arr, current, true); + insertIndent(arr, current); + } + nodeToHtml(ci, arr, formatter, current); + } + break; + case "text": + isText(node, arr); + break; + case "element": + isElement(node, arr, formatter, current); + break; + case "comment": + isComment(node, arr, formatter); + } + return arr; } - } else { - if (!attrVal) { - delete this.attrs[attrName]; - } else { - this.attrs[attrName.toLowerCase()] = attrVal; + + function isText(node, arr) { + if (node.parentNode.tagName == "pre") { + //源码模式下输入html标签,不能做转换处理,直接输出 + arr.push(node.data); + } else { + arr.push( + notTransTagName[node.parentNode.tagName] + ? utils.html(node.data) + : node.data.replace(/[ ]{2}/g, "  ") + ); + } } - } - }, - /** - * 获取当前节点在父节点下的位置索引 - * @method getIndex - * @return { Number } 返回索引数值,如果没有父节点,返回-1 - * @example - * ```javascript - * node.getIndex(); - * ``` - */ - getIndex: function() { - var parent = this.parentNode; - for (var i = 0, ci; (ci = parent.children[i]); i++) { - if (ci === this) { - return i; + function isElement(node, arr, formatter, current) { + var attrhtml = ""; + if (node.attrs) { + attrhtml = []; + var attrs = node.attrs; + for (var a in attrs) { + //这里就针对 + //

'

+ //这里边的\"做转换,要不用innerHTML直接被截断了,属性src + //有可能做的不够 + attrhtml.push( + a + + (attrs[a] !== undefined + ? '="' + + (notTransAttrs[a] + ? utils.html(attrs[a]).replace(/["]/g, function (a) { + return """; + }) + : utils.unhtml(attrs[a])) + + '"' + : "") + ); + } + attrhtml = attrhtml.join(" "); + } + arr.push( + "<" + + node.tagName + + (attrhtml ? " " + attrhtml : "") + + (dtd.$empty[node.tagName] ? "/" : "") + + ">" + ); + //插入新行 + if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != "pre") { + if (node.children && node.children.length) { + current = insertLine(arr, current, true); + insertIndent(arr, current); + } + } + if (node.children && node.children.length) { + for (var i = 0, ci; (ci = node.children[i++]);) { + if ( + formatter && + ci.type == "element" && + !dtd.$inlineWithA[ci.tagName] && + i > 1 + ) { + insertLine(arr, current); + insertIndent(arr, current); + } + nodeToHtml(ci, arr, formatter, current); + } + } + if (!dtd.$empty[node.tagName]) { + if ( + formatter && + !dtd.$inlineWithA[node.tagName] && + node.tagName != "pre" + ) { + if (node.children && node.children.length) { + current = insertLine(arr, current); + insertIndent(arr, current); + } + } + arr.push(""); + } } - } - return -1; - }, - /** - * 在当前节点下,根据id查找节点 - * @method getNodeById - * @param { String } id 要查找的id - * @return { UE.uNode } 返回找到的节点 - * @example - * ```javascript - * node.getNodeById('textId'); - * ``` - */ - getNodeById: function(id) { - var node; - if (this.children && this.children.length) { - for (var i = 0, ci; (ci = this.children[i++]); ) { - if ((node = getNodeById(ci, id))) { - return node; - } + function isComment(node, arr) { + arr.push(""); } - } - }, - /** - * 在当前节点下,根据元素名称查找节点列表 - * @method getNodesByTagName - * @param { String } tagNames 要查找的元素名称 - * @return { Array } 返回找到的节点列表 - * @example - * ```javascript - * node.getNodesByTagName('span'); - * ``` - */ - getNodesByTagName: function(tagNames) { - tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, " ").split(" "); - var arr = [], - me = this; - utils.each(tagNames, function(tagName) { - if (me.children && me.children.length) { - for (var i = 0, ci; (ci = me.children[i++]); ) { - getNodesByTagName(ci, tagName, arr); - } + function getNodeById(root, id) { + var node; + if (root.type == "element" && root.getAttr("id") == id) { + return root; + } + if (root.children && root.children.length) { + for (var i = 0, ci; (ci = root.children[i++]);) { + if ((node = getNodeById(ci, id))) { + return node; + } + } + } } - }); - return arr; - }, - /** - * 根据样式名称,获取节点的样式值 - * @method getStyle - * @param { String } name 要获取的样式名称 - * @return { String } 返回样式值 - * @example - * ```javascript - * node.getStyle('font-size'); - * ``` - */ - getStyle: function(name) { - var cssStyle = this.getAttr("style"); - if (!cssStyle) { - return ""; - } - var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+)", "i"); - var match = cssStyle.match(reg); - if (match && match[0]) { - return match[2]; - } - return ""; - }, - - /** - * 给节点设置样式 - * @method setStyle - * @param { String } name 要设置的的样式名称 - * @param { String } val 要设置的的样值 - * @example - * ```javascript - * node.setStyle('font-size', '12px'); - * ``` - */ - setStyle: function(name, val) { - function exec(name, val) { - var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+;?)", "gi"); - cssStyle = cssStyle.replace(reg, "$1"); - if (val) { - cssStyle = name + ":" + utils.unhtml(val) + ";" + cssStyle; + function getNodesByTagName(node, tagName, arr) { + if (node.type == "element" && node.tagName == tagName) { + arr.push(node); + } + if (node.children && node.children.length) { + for (var i = 0, ci; (ci = node.children[i++]);) { + getNodesByTagName(ci, tagName, arr); + } + } } - } - var cssStyle = this.getAttr("style"); - if (!cssStyle) { - cssStyle = ""; - } - if (utils.isObject(name)) { - for (var a in name) { - exec(a, name[a]); + function nodeTraversal(root, fn) { + if (root.children && root.children.length) { + for (var i = 0, ci; (ci = root.children[i]);) { + nodeTraversal(ci, fn); + //ci被替换的情况,这里就不再走 fn了 + if (ci.parentNode) { + if (ci.children && ci.children.length) { + fn(ci); + } + if (ci.parentNode) i++; + } + } + } else { + fn(root); + } } - } else { - exec(name, val); - } - this.setAttr("style", utils.trim(cssStyle)); - }, - /** - * 传入一个函数,递归遍历当前节点下的所有节点 - * @method traversal - * @param { Function } fn 遍历到节点的时,传入节点作为参数,运行此函数 - * @example - * ```javascript - * traversal(node, function(){ - * console.log(node.type); - * }); - * ``` - */ - traversal: function(fn) { - if (this.children && this.children.length) { - nodeTraversal(this, fn); - } - return this; - } - }; -})(); + uNode.prototype = { + /** + * 当前节点对象,转换成html文本 + * @method toHtml + * @return { String } 返回转换后的html字符串 + * @example + * ```javascript + * node.toHtml(); + * ``` + */ + + /** + * 当前节点对象,转换成html文本 + * @method toHtml + * @param { Boolean } formatter 是否格式化返回值 + * @return { String } 返回转换后的html字符串 + * @example + * ```javascript + * node.toHtml( true ); + * ``` + */ + toHtml: function (formatter) { + var arr = []; + nodeToHtml(this, arr, formatter, 0); + return arr.join(""); + }, + + /** + * 获取节点的html内容 + * @method innerHTML + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @return { String } 返回节点的html内容 + * @example + * ```javascript + * var htmlstr = node.innerHTML(); + * ``` + */ + + /** + * 设置节点的html内容 + * @method innerHTML + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @param { String } htmlstr 传入要设置的html内容 + * @return { UE.uNode } 返回节点本身 + * @example + * ```javascript + * node.innerHTML('text'); + * ``` + */ + innerHTML: function (htmlstr) { + if (this.type != "element" || dtd.$empty[this.tagName]) { + return this; + } + if (utils.isString(htmlstr)) { + if (this.children) { + for (var i = 0, ci; (ci = this.children[i++]);) { + ci.parentNode = null; + } + } + this.children = []; + var tmpRoot = UE.htmlparser(htmlstr); + for (var i = 0, ci; (ci = tmpRoot.children[i++]);) { + this.children.push(ci); + ci.parentNode = this; + } + return this; + } else { + var tmpRoot = new UE.uNode({ + type: "root", + children: this.children + }); + return tmpRoot.toHtml(); + } + }, + + /** + * 获取节点的纯文本内容 + * @method innerText + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @return { String } 返回节点的存文本内容 + * @example + * ```javascript + * var textStr = node.innerText(); + * ``` + */ + + /** + * 设置节点的纯文本内容 + * @method innerText + * @warning 假如节点的type不是'element',或节点的标签名称不在dtd列表里,直接返回当前节点 + * @param { String } textStr 传入要设置的文本内容 + * @return { UE.uNode } 返回节点本身 + * @example + * ```javascript + * node.innerText('text'); + * ``` + */ + innerText: function (textStr, noTrans) { + if (this.type != "element" || dtd.$empty[this.tagName]) { + return this; + } + if (textStr) { + if (this.children) { + for (var i = 0, ci; (ci = this.children[i++]);) { + ci.parentNode = null; + } + } + this.children = []; + this.appendChild(uNode.createText(textStr, noTrans)); + return this; + } else { + return this.toHtml().replace(/<[^>]+>/g, ""); + } + }, + + /** + * 获取当前对象的data属性 + * @method getData + * @return { Object } 若节点的type值是elemenet,返回空字符串,否则返回节点的data属性 + * @example + * ```javascript + * node.getData(); + * ``` + */ + getData: function () { + if (this.type == "element") return ""; + return this.data; + }, + + /** + * 获取当前节点下的第一个子节点 + * @method firstChild + * @return { UE.uNode } 返回第一个子节点 + * @example + * ```javascript + * node.firstChild(); //返回第一个子节点 + * ``` + */ + firstChild: function () { + // if (this.type != 'element' || dtd.$empty[this.tagName]) { + // return this; + // } + return this.children ? this.children[0] : null; + }, + + /** + * 获取当前节点下的最后一个子节点 + * @method lastChild + * @return { UE.uNode } 返回最后一个子节点 + * @example + * ```javascript + * node.lastChild(); //返回最后一个子节点 + * ``` + */ + lastChild: function () { + // if (this.type != 'element' || dtd.$empty[this.tagName] ) { + // return this; + // } + return this.children ? this.children[this.children.length - 1] : null; + }, + + /** + * 获取和当前节点有相同父亲节点的前一个节点 + * @method previousSibling + * @return { UE.uNode } 返回前一个节点 + * @example + * ```javascript + * node.children[2].previousSibling(); //返回子节点node.children[1] + * ``` + */ + previousSibling: function () { + var parent = this.parentNode; + for (var i = 0, ci; (ci = parent.children[i]); i++) { + if (ci === this) { + return i == 0 ? null : parent.children[i - 1]; + } + } + }, + + /** + * 获取和当前节点有相同父亲节点的后一个节点 + * @method nextSibling + * @return { UE.uNode } 返回后一个节点,找不到返回null + * @example + * ```javascript + * node.children[2].nextSibling(); //如果有,返回子节点node.children[3] + * ``` + */ + nextSibling: function () { + var parent = this.parentNode; + for (var i = 0, ci; (ci = parent.children[i++]);) { + if (ci === this) { + return parent.children[i]; + } + } + }, + + /** + * 用新的节点替换当前节点 + * @method replaceChild + * @param { UE.uNode } target 要替换成该节点参数 + * @param { UE.uNode } source 要被替换掉的节点 + * @return { UE.uNode } 返回替换之后的节点对象 + * @example + * ```javascript + * node.replaceChild(newNode, childNode); //用newNode替换childNode,childNode是node的子节点 + * ``` + */ + replaceChild: function (target, source) { + if (this.children) { + if (target.parentNode) { + target.parentNode.removeChild(target); + } + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === source) { + this.children.splice(i, 1, target); + source.parentNode = null; + target.parentNode = this; + return target; + } + } + } + }, + + /** + * 在节点的子节点列表最后位置插入一个节点 + * @method appendChild + * @param { UE.uNode } node 要插入的节点 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.appendChild( newNode ); //在node内插入子节点newNode + * ``` + */ + appendChild: function (node) { + if ( + this.type == "root" || + (this.type == "element" && !dtd.$empty[this.tagName]) + ) { + if (!this.children) { + this.children = []; + } + if (node.parentNode) { + node.parentNode.removeChild(node); + } + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === node) { + this.children.splice(i, 1); + break; + } + } + this.children.push(node); + node.parentNode = this; + return node; + } + }, + + /** + * 在传入节点的前面插入一个节点 + * @method insertBefore + * @param { UE.uNode } target 要插入的节点 + * @param { UE.uNode } source 在该参数节点前面插入 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.parentNode.insertBefore(newNode, node); //在node节点后面插入newNode + * ``` + */ + insertBefore: function (target, source) { + if (this.children) { + if (target.parentNode) { + target.parentNode.removeChild(target); + } + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === source) { + this.children.splice(i, 0, target); + target.parentNode = this; + return target; + } + } + } + }, + + /** + * 在传入节点的后面插入一个节点 + * @method insertAfter + * @param { UE.uNode } target 要插入的节点 + * @param { UE.uNode } source 在该参数节点后面插入 + * @return { UE.uNode } 返回刚插入的子节点 + * @example + * ```javascript + * node.parentNode.insertAfter(newNode, node); //在node节点后面插入newNode + * ``` + */ + insertAfter: function (target, source) { + if (this.children) { + if (target.parentNode) { + target.parentNode.removeChild(target); + } + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === source) { + this.children.splice(i + 1, 0, target); + target.parentNode = this; + return target; + } + } + } + }, + + /** + * 从当前节点的子节点列表中,移除节点 + * @method removeChild + * @param { UE.uNode } node 要移除的节点引用 + * @param { Boolean } keepChildren 是否保留移除节点的子节点,若传入true,自动把移除节点的子节点插入到移除的位置 + * @return { * } 返回刚移除的子节点 + * @example + * ```javascript + * node.removeChild(childNode,true); //在node的子节点列表中移除child节点,并且吧child的子节点插入到移除的位置 + * ``` + */ + removeChild: function (node, keepChildren) { + if (this.children) { + for (var i = 0, ci; (ci = this.children[i]); i++) { + if (ci === node) { + this.children.splice(i, 1); + ci.parentNode = null; + if (keepChildren && ci.children && ci.children.length) { + for (var j = 0, cj; (cj = ci.children[j]); j++) { + this.children.splice(i + j, 0, cj); + cj.parentNode = this; + } + } + return ci; + } + } + } + }, + + /** + * 获取当前节点所代表的元素属性,即获取attrs对象下的属性值 + * @method getAttr + * @param { String } attrName 要获取的属性名称 + * @return { * } 返回attrs对象下的属性值 + * @example + * ```javascript + * node.getAttr('title'); + * ``` + */ + getAttr: function (attrName) { + return this.attrs && this.attrs[attrName.toLowerCase()]; + }, + + /** + * 设置当前节点所代表的元素属性,即设置attrs对象下的属性值 + * @method setAttr + * @param { String } attrName 要设置的属性名称 + * @param { * } attrVal 要设置的属性值,类型视设置的属性而定 + * @return { * } 返回attrs对象下的属性值 + * @example + * ```javascript + * node.setAttr('title','标题'); + * ``` + */ + setAttr: function (attrName, attrVal) { + if (!attrName) { + delete this.attrs; + return; + } + if (!this.attrs) { + this.attrs = {}; + } + if (utils.isObject(attrName)) { + for (var a in attrName) { + if (!attrName[a]) { + delete this.attrs[a]; + } else { + this.attrs[a.toLowerCase()] = attrName[a]; + } + } + } else { + if (!attrVal) { + delete this.attrs[attrName]; + } else { + this.attrs[attrName.toLowerCase()] = attrVal; + } + } + }, + + /** + * 获取当前节点在父节点下的位置索引 + * @method getIndex + * @return { Number } 返回索引数值,如果没有父节点,返回-1 + * @example + * ```javascript + * node.getIndex(); + * ``` + */ + getIndex: function () { + var parent = this.parentNode; + for (var i = 0, ci; (ci = parent.children[i]); i++) { + if (ci === this) { + return i; + } + } + return -1; + }, + + /** + * 在当前节点下,根据id查找节点 + * @method getNodeById + * @param { String } id 要查找的id + * @return { UE.uNode } 返回找到的节点 + * @example + * ```javascript + * node.getNodeById('textId'); + * ``` + */ + getNodeById: function (id) { + var node; + if (this.children && this.children.length) { + for (var i = 0, ci; (ci = this.children[i++]);) { + if ((node = getNodeById(ci, id))) { + return node; + } + } + } + }, + + /** + * 在当前节点下,根据元素名称查找节点列表 + * @method getNodesByTagName + * @param { String } tagNames 要查找的元素名称 + * @return { Array } 返回找到的节点列表 + * @example + * ```javascript + * node.getNodesByTagName('span'); + * ``` + */ + getNodesByTagName: function (tagNames) { + tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, " ").split(" "); + var arr = [], + me = this; + utils.each(tagNames, function (tagName) { + if (me.children && me.children.length) { + for (var i = 0, ci; (ci = me.children[i++]);) { + getNodesByTagName(ci, tagName, arr); + } + } + }); + return arr; + }, + + /** + * 根据样式名称,获取节点的样式值 + * @method getStyle + * @param { String } name 要获取的样式名称 + * @return { String } 返回样式值 + * @example + * ```javascript + * node.getStyle('font-size'); + * ``` + */ + getStyle: function (name) { + var cssStyle = this.getAttr("style"); + if (!cssStyle) { + return ""; + } + var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+)", "i"); + var match = cssStyle.match(reg); + if (match && match[0]) { + return match[2]; + } + return ""; + }, + + /** + * 给节点设置样式 + * @method setStyle + * @param { String } name 要设置的的样式名称 + * @param { String } val 要设置的的样值 + * @example + * ```javascript + * node.setStyle('font-size', '12px'); + * ``` + */ + setStyle: function (name, val) { + function exec(name, val) { + var reg = new RegExp("(^|;)\\s*" + name + ":([^;]+;?)", "gi"); + cssStyle = cssStyle.replace(reg, "$1"); + if (val) { + cssStyle = name + ":" + utils.unhtml(val) + ";" + cssStyle; + } + } + + var cssStyle = this.getAttr("style"); + if (!cssStyle) { + cssStyle = ""; + } + if (utils.isObject(name)) { + for (var a in name) { + exec(a, name[a]); + } + } else { + exec(name, val); + } + this.setAttr("style", utils.trim(cssStyle)); + }, + + /** + * 传入一个函数,递归遍历当前节点下的所有节点 + * @method traversal + * @param { Function } fn 遍历到节点的时,传入节点作为参数,运行此函数 + * @example + * ```javascript + * traversal(node, function(){ + * console.log(node.type); + * }); + * ``` + */ + traversal: function (fn) { + if (this.children && this.children.length) { + nodeTraversal(this, fn); + } + return this; + } + }; + })(); // core/htmlparser.js -/** - * html字符串转换成uNode节点 - * @file - * @module UE - * @since 1.2.6.1 - */ + /** + * html字符串转换成uNode节点 + * @file + * @module UE + * @since 1.2.6.1 + */ -/** - * UEditor公用空间,UEditor所有的功能都挂载在该空间下 - * @unfile - * @module UE - */ + /** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @unfile + * @module UE + */ -/** - * html字符串转换成uNode节点的静态方法 - * @method htmlparser - * @param { String } htmlstr 要转换的html代码 - * @param { Boolean } ignoreBlank 若设置为true,转换的时候忽略\n\r\t等空白字符 - * @return { uNode } 给定的html片段转换形成的uNode对象 - * @example - * ```javascript - * var root = UE.htmlparser('

htmlparser

', true); - * ``` - */ + /** + * html字符串转换成uNode节点的静态方法 + * @method htmlparser + * @param { String } htmlstr 要转换的html代码 + * @param { Boolean } ignoreBlank 若设置为true,转换的时候忽略\n\r\t等空白字符 + * @return { uNode } 给定的html片段转换形成的uNode对象 + * @example + * ```javascript + * var root = UE.htmlparser('

htmlparser

', true); + * ``` + */ -var htmlparser = (UE.htmlparser = function(htmlstr, ignoreBlank) { - //todo 原来的方式 [^"'<>\/] 有\/就不能配对上 "); + tempIndex === 0 && tmpl.push(""); - tmpl.push( - '' - ); + tmpl.push( + '' + ); - tempIndex === 2 && tmpl.push(""); - } + tempIndex === 2 && tmpl.push(""); + } - return ( - '
' + - '
' + - '
这样的标签了 - //先去掉了,加上的原因忘了,这里先记录 - //var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g, - //以上的正则表达式无法匹配:

- //修改为如下正则表达式: - var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g, - re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g; + var htmlparser = (UE.htmlparser = function (htmlstr, ignoreBlank) { + //todo 原来的方式 [^"'<>\/] 有\/就不能配对上
这样的标签了 + //先去掉了,加上的原因忘了,这里先记录 + //var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g, + //以上的正则表达式无法匹配:

+ //修改为如下正则表达式: + var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g, + re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g; - //ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除 - var allowEmptyTags = { - b: 1, - code: 1, - i: 1, - u: 1, - strike: 1, - s: 1, - tt: 1, - strong: 1, - q: 1, - samp: 1, - em: 1, - span: 1, - sub: 1, - img: 1, - sup: 1, - font: 1, - big: 1, - small: 1, - iframe: 1, - a: 1, - br: 1, - pre: 1 - }; - htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, "g"), ""); - if (!ignoreBlank) { - htmlstr = htmlstr.replace( - new RegExp( - "[\\r\\t\\n" + - (ignoreBlank ? "" : " ") + - "]*]*)>[\\r\\t\\n" + - (ignoreBlank ? "" : " ") + - "]*", - "g" - ), - function(a, b) { - //br暂时单独处理 - if (b && allowEmptyTags[b.toLowerCase()]) { - return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, ""); + //ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除 + var allowEmptyTags = { + b: 1, + code: 1, + i: 1, + u: 1, + strike: 1, + s: 1, + tt: 1, + strong: 1, + q: 1, + samp: 1, + em: 1, + span: 1, + sub: 1, + img: 1, + sup: 1, + font: 1, + big: 1, + small: 1, + iframe: 1, + a: 1, + br: 1, + pre: 1 + }; + htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, "g"), ""); + if (!ignoreBlank) { + htmlstr = htmlstr.replace( + new RegExp( + "[\\r\\t\\n" + + (ignoreBlank ? "" : " ") + + "]*]*)>[\\r\\t\\n" + + (ignoreBlank ? "" : " ") + + "]*", + "g" + ), + function (a, b) { + //br暂时单独处理 + if (b && allowEmptyTags[b.toLowerCase()]) { + return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, ""); + } + return a + .replace(new RegExp("^[\\r\\n" + (ignoreBlank ? "" : " ") + "]+"), "") + .replace( + new RegExp("[\\r\\n" + (ignoreBlank ? "" : " ") + "]+$"), + "" + ); + } + ); } - return a - .replace(new RegExp("^[\\r\\n" + (ignoreBlank ? "" : " ") + "]+"), "") - .replace( - new RegExp("[\\r\\n" + (ignoreBlank ? "" : " ") + "]+$"), - "" - ); - } - ); - } - var notTransAttrs = { - href: 1, - src: 1 - }; + var notTransAttrs = { + href: 1, + src: 1 + }; - var uNode = UE.uNode, - needParentNode = { - td: "tr", - tr: ["tbody", "thead", "tfoot"], - tbody: "table", - th: "tr", - thead: "table", - tfoot: "table", - caption: "table", - li: ["ul", "ol"], - dt: "dl", - dd: "dl", - option: "select" - }, - needChild = { - ol: "li", - ul: "li" - }; + var uNode = UE.uNode, + needParentNode = { + td: "tr", + tr: ["tbody", "thead", "tfoot"], + tbody: "table", + th: "tr", + thead: "table", + tfoot: "table", + caption: "table", + li: ["ul", "ol"], + dt: "dl", + dd: "dl", + option: "select" + }, + needChild = { + ol: "li", + ul: "li" + }; - function text(parent, data) { - if (needChild[parent.tagName]) { - var tmpNode = uNode.createElement(needChild[parent.tagName]); - parent.appendChild(tmpNode); - tmpNode.appendChild(uNode.createText(data)); - parent = tmpNode; - } else { - parent.appendChild(uNode.createText(data)); - } - } - - function element(parent, tagName, htmlattr) { - var needParentTag; - if ((needParentTag = needParentNode[tagName])) { - var tmpParent = parent, - hasParent; - while (tmpParent.type != "root") { - if ( - utils.isArray(needParentTag) - ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 - : needParentTag == tmpParent.tagName - ) { - parent = tmpParent; - hasParent = true; - break; - } - tmpParent = tmpParent.parentNode; - } - if (!hasParent) { - parent = element( - parent, - utils.isArray(needParentTag) ? needParentTag[0] : needParentTag - ); - } - } - //按dtd处理嵌套 - // if(parent.type != 'root' && !dtd[parent.tagName][tagName]) - // parent = parent.parentNode; - var elm = new uNode({ - parentNode: parent, - type: "element", - tagName: tagName.toLowerCase(), - //是自闭合的处理一下 - children: dtd.$empty[tagName] ? null : [] - }); - //如果属性存在,处理属性 - if (htmlattr) { - var attrs = {}, - match; - while ((match = re_attr.exec(htmlattr))) { - attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] - ? match[2] || match[3] || match[4] - : utils.unhtml(match[2] || match[3] || match[4]); - } - elm.attrs = attrs; - } - //trace:3970 - // //如果parent下不能放elm - // if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){ - // parent = parent.parentNode; - // elm.parentNode = parent; - // } - parent.children.push(elm); - //如果是自闭合节点返回父亲节点 - return dtd.$empty[tagName] ? parent : elm; - } - - function comment(parent, data) { - parent.children.push( - new uNode({ - type: "comment", - data: data, - parentNode: parent - }) - ); - } - - var match, - currentIndex = 0, - nextIndex = 0; - //设置根节点 - var root = new uNode({ - type: "root", - children: [] - }); - var currentParent = root; - - while ((match = re_tag.exec(htmlstr))) { - currentIndex = match.index; - try { - if (currentIndex > nextIndex) { - //text node - text(currentParent, htmlstr.slice(nextIndex, currentIndex)); - } - if (match[3]) { - if (dtd.$cdata[currentParent.tagName]) { - text(currentParent, match[0]); - } else { - //start tag - currentParent = element( - currentParent, - match[3].toLowerCase(), - match[4] - ); - } - } else if (match[1]) { - if (currentParent.type != "root") { - if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) { - text(currentParent, match[0]); - } else { - var tmpParent = currentParent; - while ( - currentParent.type == "element" && - currentParent.tagName != match[1].toLowerCase() - ) { - currentParent = currentParent.parentNode; - if (currentParent.type == "root") { - currentParent = tmpParent; - throw "break"; - } + function text(parent, data) { + if (needChild[parent.tagName]) { + var tmpNode = uNode.createElement(needChild[parent.tagName]); + parent.appendChild(tmpNode); + tmpNode.appendChild(uNode.createText(data)); + parent = tmpNode; + } else { + parent.appendChild(uNode.createText(data)); } - //end tag - currentParent = currentParent.parentNode; - } } - } else if (match[2]) { - //comment - comment(currentParent, match[2]); - } - } catch (e) {} - nextIndex = re_tag.lastIndex; - } - //如果结束是文本,就有可能丢掉,所以这里手动判断一下 - //例如
  • sdfsdfsdf
  • sdfsdfsdfsdf - if (nextIndex < htmlstr.length) { - text(currentParent, htmlstr.slice(nextIndex)); - } - return root; -}); + function element(parent, tagName, htmlattr) { + var needParentTag; + if ((needParentTag = needParentNode[tagName])) { + var tmpParent = parent, + hasParent; + while (tmpParent.type != "root") { + if ( + utils.isArray(needParentTag) + ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 + : needParentTag == tmpParent.tagName + ) { + parent = tmpParent; + hasParent = true; + break; + } + tmpParent = tmpParent.parentNode; + } + if (!hasParent) { + parent = element( + parent, + utils.isArray(needParentTag) ? needParentTag[0] : needParentTag + ); + } + } + //按dtd处理嵌套 + // if(parent.type != 'root' && !dtd[parent.tagName][tagName]) + // parent = parent.parentNode; + var elm = new uNode({ + parentNode: parent, + type: "element", + tagName: tagName.toLowerCase(), + //是自闭合的处理一下 + children: dtd.$empty[tagName] ? null : [] + }); + //如果属性存在,处理属性 + if (htmlattr) { + var attrs = {}, + match; + while ((match = re_attr.exec(htmlattr))) { + attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] + ? match[2] || match[3] || match[4] + : utils.unhtml(match[2] || match[3] || match[4]); + } + elm.attrs = attrs; + } + //trace:3970 + // //如果parent下不能放elm + // if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){ + // parent = parent.parentNode; + // elm.parentNode = parent; + // } + parent.children.push(elm); + //如果是自闭合节点返回父亲节点 + return dtd.$empty[tagName] ? parent : elm; + } + + function comment(parent, data) { + parent.children.push( + new uNode({ + type: "comment", + data: data, + parentNode: parent + }) + ); + } + + var match, + currentIndex = 0, + nextIndex = 0; + //设置根节点 + var root = new uNode({ + type: "root", + children: [] + }); + var currentParent = root; + + while ((match = re_tag.exec(htmlstr))) { + currentIndex = match.index; + try { + if (currentIndex > nextIndex) { + //text node + text(currentParent, htmlstr.slice(nextIndex, currentIndex)); + } + if (match[3]) { + if (dtd.$cdata[currentParent.tagName]) { + text(currentParent, match[0]); + } else { + //start tag + currentParent = element( + currentParent, + match[3].toLowerCase(), + match[4] + ); + } + } else if (match[1]) { + if (currentParent.type != "root") { + if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) { + text(currentParent, match[0]); + } else { + var tmpParent = currentParent; + while ( + currentParent.type == "element" && + currentParent.tagName != match[1].toLowerCase() + ) { + currentParent = currentParent.parentNode; + if (currentParent.type == "root") { + currentParent = tmpParent; + throw "break"; + } + } + //end tag + currentParent = currentParent.parentNode; + } + } + } else if (match[2]) { + //comment + comment(currentParent, match[2]); + } + } catch (e) { + } + + nextIndex = re_tag.lastIndex; + } + //如果结束是文本,就有可能丢掉,所以这里手动判断一下 + //例如
  • sdfsdfsdf
  • sdfsdfsdfsdf + if (nextIndex < htmlstr.length) { + text(currentParent, htmlstr.slice(nextIndex)); + } + return root; + }); // core/filternode.js -/** - * UE过滤节点的静态方法 - * @file - */ + /** + * UE过滤节点的静态方法 + * @file + */ -/** - * UEditor公用空间,UEditor所有的功能都挂载在该空间下 - * @module UE - */ + /** + * UEditor公用空间,UEditor所有的功能都挂载在该空间下 + * @module UE + */ -/** - * 根据传入节点和过滤规则过滤相应节点 - * @module UE - * @since 1.2.6.1 - * @method filterNode - * @param { Object } root 指定root节点 - * @param { Object } rules 过滤规则json对象 - * @example - * ```javascript - * UE.filterNode(root,editor.options.filterRules); - * ``` - */ -var filterNode = (UE.filterNode = (function() { - function filterNode(node, rules) { - switch (node.type) { - case "text": - break; - case "element": - var val; - if ((val = rules[node.tagName])) { - if (val === "-") { - node.parentNode.removeChild(node); - } else if (utils.isFunction(val)) { - var parentNode = node.parentNode, - index = node.getIndex(); - val(node); - if (node.parentNode) { - if (node.children) { - for (var i = 0, ci; (ci = node.children[i]); ) { - filterNode(ci, rules); - if (ci.parentNode) { - i++; - } - } - } - } else { - for (var i = index, ci; (ci = parentNode.children[i]); ) { - filterNode(ci, rules); - if (ci.parentNode) { - i++; - } - } - } - } else { - var attrs = val["$"]; - if (attrs && node.attrs) { - var tmpAttrs = {}, - tmpVal; - for (var a in attrs) { - tmpVal = node.getAttr(a); - //todo 只先对style单独处理 - if (a == "style" && utils.isArray(attrs[a])) { - var tmpCssStyle = []; - utils.each(attrs[a], function(v) { - var tmp; - if ((tmp = node.getStyle(v))) { - tmpCssStyle.push(v + ":" + tmp); + /** + * 根据传入节点和过滤规则过滤相应节点 + * @module UE + * @since 1.2.6.1 + * @method filterNode + * @param { Object } root 指定root节点 + * @param { Object } rules 过滤规则json对象 + * @example + * ```javascript + * UE.filterNode(root,editor.options.filterRules); + * ``` + */ + var filterNode = (UE.filterNode = (function () { + function filterNode(node, rules) { + switch (node.type) { + case "text": + break; + case "element": + var val; + if ((val = rules[node.tagName])) { + if (val === "-") { + node.parentNode.removeChild(node); + } else if (utils.isFunction(val)) { + var parentNode = node.parentNode, + index = node.getIndex(); + val(node); + if (node.parentNode) { + if (node.children) { + for (var i = 0, ci; (ci = node.children[i]);) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + } + } else { + for (var i = index, ci; (ci = parentNode.children[i]);) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + } + } else { + var attrs = val["$"]; + if (attrs && node.attrs) { + var tmpAttrs = {}, + tmpVal; + for (var a in attrs) { + tmpVal = node.getAttr(a); + //todo 只先对style单独处理 + if (a == "style" && utils.isArray(attrs[a])) { + var tmpCssStyle = []; + utils.each(attrs[a], function (v) { + var tmp; + if ((tmp = node.getStyle(v))) { + tmpCssStyle.push(v + ":" + tmp); + } + }); + tmpVal = tmpCssStyle.join(";"); + } + if (tmpVal) { + tmpAttrs[a] = tmpVal; + } + } + node.attrs = tmpAttrs; + } + if (node.children) { + for (var i = 0, ci; (ci = node.children[i]);) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + } + } + } else { + //如果不在名单里扣出子节点并删除该节点,cdata除外 + if (dtd.$cdata[node.tagName]) { + node.parentNode.removeChild(node); + } else { + var parentNode = node.parentNode, + index = node.getIndex(); + node.parentNode.removeChild(node, true); + for (var i = index, ci; (ci = parentNode.children[i]);) { + filterNode(ci, rules); + if (ci.parentNode) { + i++; + } + } + } } - }); - tmpVal = tmpCssStyle.join(";"); - } - if (tmpVal) { - tmpAttrs[a] = tmpVal; - } - } - node.attrs = tmpAttrs; + break; + case "comment": + node.parentNode.removeChild(node); } - if (node.children) { - for (var i = 0, ci; (ci = node.children[i]); ) { + } + + return function (root, rules) { + if (utils.isEmptyObject(rules)) { + return root; + } + var val; + if ((val = rules["-"])) { + utils.each(val.split(" "), function (k) { + rules[k] = "-"; + }); + } + for (var i = 0, ci; (ci = root.children[i]);) { filterNode(ci, rules); if (ci.parentNode) { - i++; + i++; } - } } - } - } else { - //如果不在名单里扣出子节点并删除该节点,cdata除外 - if (dtd.$cdata[node.tagName]) { - node.parentNode.removeChild(node); - } else { - var parentNode = node.parentNode, - index = node.getIndex(); - node.parentNode.removeChild(node, true); - for (var i = index, ci; (ci = parentNode.children[i]); ) { - filterNode(ci, rules); - if (ci.parentNode) { - i++; - } - } - } - } - break; - case "comment": - node.parentNode.removeChild(node); - } - } - return function(root, rules) { - if (utils.isEmptyObject(rules)) { - return root; - } - var val; - if ((val = rules["-"])) { - utils.each(val.split(" "), function(k) { - rules[k] = "-"; - }); - } - for (var i = 0, ci; (ci = root.children[i]); ) { - filterNode(ci, rules); - if (ci.parentNode) { - i++; - } - } - return root; - }; -})()); + return root; + }; + })()); // core/plugin.js -/** - * Created with JetBrains PhpStorm. - * User: campaign - * Date: 10/8/13 - * Time: 6:15 PM - * To change this template use File | Settings | File Templates. - */ -UE.plugin = (function() { - var _plugins = {}; - return { - register: function(pluginName, fn, oldOptionName, afterDisabled) { - if (oldOptionName && utils.isFunction(oldOptionName)) { - afterDisabled = oldOptionName; - oldOptionName = null; - } - _plugins[pluginName] = { - optionName: oldOptionName || pluginName, - execFn: fn, - //当插件被禁用时执行 - afterDisabled: afterDisabled - }; - }, - load: function(editor) { - utils.each(_plugins, function(plugin) { - var _export = plugin.execFn.call(editor); - if (editor.options[plugin.optionName] !== false) { - if (_export) { - //后边需要再做扩展 - utils.each(_export, function(v, k) { - switch (k.toLowerCase()) { - case "shortcutkey": - editor.addshortcutkey(v); - break; - case "bindevents": - utils.each(v, function(fn, eventName) { - editor.addListener(eventName, fn); - }); - break; - case "bindmultievents": - utils.each(utils.isArray(v) ? v : [v], function(event) { - var types = utils.trim(event.type).split(/\s+/); - utils.each(types, function(eventName) { - editor.addListener(eventName, event.handler); - }); - }); - break; - case "commands": - utils.each(v, function(execFn, execName) { - editor.commands[execName] = execFn; - }); - break; - case "outputrule": - editor.addOutputRule(v); - break; - case "inputrule": - editor.addInputRule(v); - break; - case "defaultoptions": - editor.setOpt(v); - } - }); - } - } else if (plugin.afterDisabled) { - plugin.afterDisabled.call(editor); - } - }); - //向下兼容 - utils.each(UE.plugins, function(plugin) { - plugin.call(editor); - }); - }, - run: function(pluginName, editor) { - var plugin = _plugins[pluginName]; - if (plugin) { - plugin.exeFn.call(editor); - } - } - }; -})(); + /** + * Created with JetBrains PhpStorm. + * User: campaign + * Date: 10/8/13 + * Time: 6:15 PM + * To change this template use File | Settings | File Templates. + */ + UE.plugin = (function () { + var _plugins = {}; + return { + register: function (pluginName, fn, oldOptionName, afterDisabled) { + if (oldOptionName && utils.isFunction(oldOptionName)) { + afterDisabled = oldOptionName; + oldOptionName = null; + } + _plugins[pluginName] = { + optionName: oldOptionName || pluginName, + execFn: fn, + //当插件被禁用时执行 + afterDisabled: afterDisabled + }; + }, + load: function (editor) { + utils.each(_plugins, function (plugin) { + var _export = plugin.execFn.call(editor); + if (editor.options[plugin.optionName] !== false) { + if (_export) { + //后边需要再做扩展 + utils.each(_export, function (v, k) { + switch (k.toLowerCase()) { + case "shortcutkey": + editor.addshortcutkey(v); + break; + case "bindevents": + utils.each(v, function (fn, eventName) { + editor.addListener(eventName, fn); + }); + break; + case "bindmultievents": + utils.each(utils.isArray(v) ? v : [v], function (event) { + var types = utils.trim(event.type).split(/\s+/); + utils.each(types, function (eventName) { + editor.addListener(eventName, event.handler); + }); + }); + break; + case "commands": + utils.each(v, function (execFn, execName) { + editor.commands[execName] = execFn; + }); + break; + case "outputrule": + editor.addOutputRule(v); + break; + case "inputrule": + editor.addInputRule(v); + break; + case "defaultoptions": + editor.setOpt(v); + } + }); + } + } else if (plugin.afterDisabled) { + plugin.afterDisabled.call(editor); + } + }); + //向下兼容 + utils.each(UE.plugins, function (plugin) { + plugin.call(editor); + }); + }, + run: function (pluginName, editor) { + var plugin = _plugins[pluginName]; + if (plugin) { + plugin.exeFn.call(editor); + } + } + }; + })(); // core/keymap.js -var keymap = (UE.keymap = { - Backspace: 8, - Tab: 9, - Enter: 13, + var keymap = (UE.keymap = { + Backspace: 8, + Tab: 9, + Enter: 13, - Shift: 16, - Control: 17, - Alt: 18, - CapsLock: 20, + Shift: 16, + Control: 17, + Alt: 18, + CapsLock: 20, - Esc: 27, + Esc: 27, - Spacebar: 32, + Spacebar: 32, - PageUp: 33, - PageDown: 34, - End: 35, - Home: 36, + PageUp: 33, + PageDown: 34, + End: 35, + Home: 36, - Left: 37, - Up: 38, - Right: 39, - Down: 40, + Left: 37, + Up: 38, + Right: 39, + Down: 40, - Insert: 45, + Insert: 45, - Del: 46, + Del: 46, - NumLock: 144, + NumLock: 144, - Cmd: 91, + Cmd: 91, - "=": 187, - "-": 189, + "=": 187, + "-": 189, - b: 66, - i: 73, - //回退 - z: 90, - y: 89, - //粘贴 - v: 86, - x: 88, + b: 66, + i: 73, + //回退 + z: 90, + y: 89, + //粘贴 + v: 86, + x: 88, - s: 83, + s: 83, - n: 78 -}); + n: 78 + }); // core/localstorage.js -var LocalStorage = (UE.LocalStorage = (function () { + var LocalStorage = (UE.LocalStorage = (function () { - var storage = window.localStorage + var storage = window.localStorage - return { - saveLocalData: function (key, data) { - // console.log('saveLocalData', key, data); - if (!storage) { - return false; + return { + saveLocalData: function (key, data) { + // console.log('saveLocalData', key, data); + if (!storage) { + return false; + } + storage.setItem(key, data); + return true; + }, + getLocalData: function (key) { + // console.log('getLocalData', key); + if (!storage) { + return null; + } + return storage.getItem(key) || null; + }, + removeItem: function (key) { + // console.log('removeItem', key); + storage && storage.removeItem(key); } - storage.setItem(key, data); - return true; - }, - getLocalData: function (key) { - // console.log('getLocalData', key); - if (!storage) { - return null; + }; + + })()); + + (function () { + + var ROOT_KEY = "UEditorPlusPref"; + + UE.Editor.prototype.setPreferences = function (key, value) { + // console.log('setPreferences', key, value); + var obj = {}; + if (utils.isString(key)) { + obj[key] = value; + } else { + obj = key; } - return storage.getItem(key) || null; - }, - removeItem: function (key) { - // console.log('removeItem', key); - storage && storage.removeItem(key); - } - }; + var data = LocalStorage.getLocalData(ROOT_KEY); + if (data && (data = utils.str2json(data))) { + utils.extend(data, obj); + } else { + data = obj; + } + data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data)); + }; -})()); + UE.Editor.prototype.getPreferences = function (key) { + // console.log('getPreferences', key); + var data = LocalStorage.getLocalData(ROOT_KEY); + if (data && (data = utils.str2json(data))) { + return key ? data[key] : data; + } + return null; + }; -(function () { - - var ROOT_KEY = "UEditorPlusPref"; - - UE.Editor.prototype.setPreferences = function (key, value) { - // console.log('setPreferences', key, value); - var obj = {}; - if (utils.isString(key)) { - obj[key] = value; - } else { - obj = key; - } - var data = LocalStorage.getLocalData(ROOT_KEY); - if (data && (data = utils.str2json(data))) { - utils.extend(data, obj); - } else { - data = obj; - } - data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data)); - }; - - UE.Editor.prototype.getPreferences = function (key) { - // console.log('getPreferences', key); - var data = LocalStorage.getLocalData(ROOT_KEY); - if (data && (data = utils.str2json(data))) { - return key ? data[key] : data; - } - return null; - }; - - UE.Editor.prototype.removePreferences = function (key) { - // console.log('removePreferences', key); - var data = LocalStorage.getLocalData(ROOT_KEY); - if (data && (data = utils.str2json(data))) { - data[key] = undefined; - delete data[key]; - } - data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data)); - }; -})(); + UE.Editor.prototype.removePreferences = function (key) { + // console.log('removePreferences', key); + var data = LocalStorage.getLocalData(ROOT_KEY); + if (data && (data = utils.str2json(data))) { + data[key] = undefined; + delete data[key]; + } + data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data)); + }; + })(); // plugins/defaultfilter.js ///import core ///plugin 编辑器默认的过滤转换机制 -UE.plugins["defaultfilter"] = function() { - var me = this; - me.setOpt({ - allowDivTransToP: true, - disabledTableInTable: true, - rgb2Hex: true - }); - //默认的过滤处理 - //进入编辑器的内容处理 - me.addInputRule(function(root) { - var allowDivTransToP = this.options.allowDivTransToP; - var val; - function tdParent(node) { - while (node && node.type == "element") { - if (node.tagName == "td") { - return true; - } - node = node.parentNode; - } - return false; - } - //进行默认的处理 - root.traversal(function(node) { - if (node.type == "element") { - if ( - !dtd.$cdata[node.tagName] && - me.options.autoClearEmptyNode && - dtd.$inline[node.tagName] && - !dtd.$empty[node.tagName] && - (!node.attrs || utils.isEmptyObject(node.attrs)) - ) { - if (!node.firstChild()) node.parentNode.removeChild(node); - else if ( - node.tagName == "span" && - (!node.attrs || utils.isEmptyObject(node.attrs)) - ) { - node.parentNode.removeChild(node, true); - } - return; - } - switch (node.tagName) { - case "style": - case "script": - node.setAttr({ - cdata_tag: node.tagName, - cdata_data: node.innerHTML() || "", - _ue_custom_node_: "true" - }); - node.tagName = "div"; - node.innerHTML(""); - break; - case "a": - if ((val = node.getAttr("href"))) { - node.setAttr("_href", val); - } - break; - case "img": - //todo base64暂时去掉,后边做远程图片上传后,干掉这个 - if ((val = node.getAttr("src"))) { - if (/^data:/.test(val)) { - node.parentNode.removeChild(node); - break; - } - } - node.setAttr("_src", node.getAttr("src")); - break; - case "span": - if (browser.webkit && (val = node.getStyle("white-space"))) { - if (/nowrap|normal/.test(val)) { - node.setStyle("white-space", ""); - if ( - me.options.autoClearEmptyNode && - utils.isEmptyObject(node.attrs) - ) { - node.parentNode.removeChild(node, true); - } - } - } - val = node.getAttr("id"); - if (val && /^_baidu_bookmark_/i.test(val)) { - node.parentNode.removeChild(node); - } - break; - case "p": - if ((val = node.getAttr("align"))) { - node.setAttr("align"); - node.setStyle("text-align", val); - } - //trace:3431 - // var cssStyle = node.getAttr('style'); - // if (cssStyle) { - // cssStyle = cssStyle.replace(/(margin|padding)[^;]+/g, ''); - // node.setAttr('style', cssStyle) - // - // } - //p标签不允许嵌套 - utils.each(node.children, function(n) { - if (n.type == "element" && n.tagName == "p") { - var next = n.nextSibling(); - node.parentNode.insertAfter(n, node); - var last = n; - while (next) { - var tmp = next.nextSibling(); - node.parentNode.insertAfter(next, last); - last = next; - next = tmp; + UE.plugins["defaultfilter"] = function () { + var me = this; + me.setOpt({ + allowDivTransToP: true, + disabledTableInTable: true, + rgb2Hex: true + }); + //默认的过滤处理 + //进入编辑器的内容处理 + me.addInputRule(function (root) { + var allowDivTransToP = this.options.allowDivTransToP; + var val; + + function tdParent(node) { + while (node && node.type == "element") { + if (node.tagName == "td") { + return true; + } + node = node.parentNode; } return false; - } - }); - if (!node.firstChild()) { - node.innerHTML(browser.ie ? " " : "
    "); } - break; - case "div": - if (node.getAttr("cdata_tag")) { - break; - } - //针对代码这里不处理插入代码的div - val = node.getAttr("class"); - if (val && /^line number\d+/.test(val)) { - break; - } - if (!allowDivTransToP) { - break; - } - var tmpNode, - p = UE.uNode.createElement("p"); - while ((tmpNode = node.firstChild())) { - if ( - tmpNode.type == "text" || - !UE.dom.dtd.$block[tmpNode.tagName] - ) { - p.appendChild(tmpNode); - } else { - if (p.firstChild()) { - node.parentNode.insertBefore(p, node); - p = UE.uNode.createElement("p"); - } else { - node.parentNode.insertBefore(tmpNode, node); - } - } - } - if (p.firstChild()) { - node.parentNode.insertBefore(p, node); - } - node.parentNode.removeChild(node); - break; - case "dl": - node.tagName = "ul"; - break; - case "dt": - case "dd": - node.tagName = "li"; - break; - case "li": - var className = node.getAttr("class"); - if (!className || !/list\-/.test(className)) { - node.setAttr(); - } - var tmpNodes = node.getNodesByTagName("ol ul"); - UE.utils.each(tmpNodes, function(n) { - node.parentNode.insertAfter(n, node); - }); - break; - case "td": - case "th": - case "caption": - if (!node.children || !node.children.length) { - node.appendChild( - browser.ie11below - ? UE.uNode.createText(" ") - : UE.uNode.createElement("br") - ); - } - break; - case "table": - if (me.options.disabledTableInTable && tdParent(node)) { - node.parentNode.insertBefore( - UE.uNode.createText(node.innerText()), - node - ); - node.parentNode.removeChild(node); - } - } - } - // if(node.type == 'comment'){ - // node.parentNode.removeChild(node); - // } - }); - }); - //从编辑器出去的内容处理 - me.addOutputRule(function(root) { - var val; - root.traversal(function(node) { - if (node.type == "element") { - if ( - me.options.autoClearEmptyNode && - dtd.$inline[node.tagName] && - !dtd.$empty[node.tagName] && - (!node.attrs || utils.isEmptyObject(node.attrs)) - ) { - if (!node.firstChild()) node.parentNode.removeChild(node); - else if ( - node.tagName == "span" && - (!node.attrs || utils.isEmptyObject(node.attrs)) - ) { - node.parentNode.removeChild(node, true); - } - return; - } - switch (node.tagName) { - case "div": - if ((val = node.getAttr("cdata_tag"))) { - node.tagName = val; - node.appendChild(UE.uNode.createText(node.getAttr("cdata_data"))); - node.setAttr({ - cdata_tag: "", - cdata_data: "", - _ue_custom_node_: "" - }); - } - break; - case "a": - if ((val = node.getAttr("_href"))) { - node.setAttr({ - href: utils.html(val), - _href: "" - }); - } - break; - break; - case "span": - val = node.getAttr("id"); - if (val && /^_baidu_bookmark_/i.test(val)) { - node.parentNode.removeChild(node); - } - //将color的rgb格式转换为#16进制格式 - if (me.getOpt("rgb2Hex")) { - var cssStyle = node.getAttr("style"); - if (cssStyle) { - node.setAttr( - "style", - cssStyle.replace(/rgba?\(([\d,\s]+)\)/g, function(a, value) { - var array = value.split(","); - if (array.length > 3) return ""; - value = "#"; - for (var i = 0, color; (color = array[i++]); ) { - color = parseInt( - color.replace(/[^\d]/gi, ""), - 10 - ).toString(16); - value += color.length == 1 ? "0" + color : color; + //进行默认的处理 + root.traversal(function (node) { + if (node.type == "element") { + if ( + !dtd.$cdata[node.tagName] && + me.options.autoClearEmptyNode && + dtd.$inline[node.tagName] && + !dtd.$empty[node.tagName] && + (!node.attrs || utils.isEmptyObject(node.attrs)) + ) { + if (!node.firstChild()) node.parentNode.removeChild(node); + else if ( + node.tagName == "span" && + (!node.attrs || utils.isEmptyObject(node.attrs)) + ) { + node.parentNode.removeChild(node, true); + } + return; } - return value.toUpperCase(); - }) - ); - } - } - break; - case "img": - if ((val = node.getAttr("_src"))) { - node.setAttr({ - src: node.getAttr("_src"), - _src: "" - }); - } - } - } - }); - }); -}; + switch (node.tagName) { + case "style": + case "script": + node.setAttr({ + cdata_tag: node.tagName, + cdata_data: node.innerHTML() || "", + _ue_custom_node_: "true" + }); + node.tagName = "div"; + node.innerHTML(""); + break; + case "a": + if ((val = node.getAttr("href"))) { + node.setAttr("_href", val); + } + break; + case "img": + //todo base64暂时去掉,后边做远程图片上传后,干掉这个 + if ((val = node.getAttr("src"))) { + if (/^data:/.test(val)) { + node.parentNode.removeChild(node); + break; + } + } + node.setAttr("_src", node.getAttr("src")); + break; + case "span": + if (browser.webkit && (val = node.getStyle("white-space"))) { + if (/nowrap|normal/.test(val)) { + node.setStyle("white-space", ""); + if ( + me.options.autoClearEmptyNode && + utils.isEmptyObject(node.attrs) + ) { + node.parentNode.removeChild(node, true); + } + } + } + val = node.getAttr("id"); + if (val && /^_baidu_bookmark_/i.test(val)) { + node.parentNode.removeChild(node); + } + break; + case "p": + if ((val = node.getAttr("align"))) { + node.setAttr("align"); + node.setStyle("text-align", val); + } + //trace:3431 + // var cssStyle = node.getAttr('style'); + // if (cssStyle) { + // cssStyle = cssStyle.replace(/(margin|padding)[^;]+/g, ''); + // node.setAttr('style', cssStyle) + // + // } + //p标签不允许嵌套 + utils.each(node.children, function (n) { + if (n.type == "element" && n.tagName == "p") { + var next = n.nextSibling(); + node.parentNode.insertAfter(n, node); + var last = n; + while (next) { + var tmp = next.nextSibling(); + node.parentNode.insertAfter(next, last); + last = next; + next = tmp; + } + return false; + } + }); + if (!node.firstChild()) { + node.innerHTML(browser.ie ? " " : "
    "); + } + break; + case "div": + if (node.getAttr("cdata_tag")) { + break; + } + //针对代码这里不处理插入代码的div + val = node.getAttr("class"); + if (val && /^line number\d+/.test(val)) { + break; + } + if (!allowDivTransToP) { + break; + } + var tmpNode, + p = UE.uNode.createElement("p"); + while ((tmpNode = node.firstChild())) { + if ( + tmpNode.type == "text" || + !UE.dom.dtd.$block[tmpNode.tagName] + ) { + p.appendChild(tmpNode); + } else { + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + p = UE.uNode.createElement("p"); + } else { + node.parentNode.insertBefore(tmpNode, node); + } + } + } + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + } + node.parentNode.removeChild(node); + break; + case "dl": + node.tagName = "ul"; + break; + case "dt": + case "dd": + node.tagName = "li"; + break; + case "li": + var className = node.getAttr("class"); + if (!className || !/list\-/.test(className)) { + node.setAttr(); + } + var tmpNodes = node.getNodesByTagName("ol ul"); + UE.utils.each(tmpNodes, function (n) { + node.parentNode.insertAfter(n, node); + }); + break; + case "td": + case "th": + case "caption": + if (!node.children || !node.children.length) { + node.appendChild( + browser.ie11below + ? UE.uNode.createText(" ") + : UE.uNode.createElement("br") + ); + } + break; + case "table": + if (me.options.disabledTableInTable && tdParent(node)) { + node.parentNode.insertBefore( + UE.uNode.createText(node.innerText()), + node + ); + node.parentNode.removeChild(node); + } + } + } + // if(node.type == 'comment'){ + // node.parentNode.removeChild(node); + // } + }); + }); + + //从编辑器出去的内容处理 + me.addOutputRule(function (root) { + var val; + root.traversal(function (node) { + if (node.type == "element") { + if ( + me.options.autoClearEmptyNode && + dtd.$inline[node.tagName] && + !dtd.$empty[node.tagName] && + (!node.attrs || utils.isEmptyObject(node.attrs)) + ) { + if (!node.firstChild()) node.parentNode.removeChild(node); + else if ( + node.tagName == "span" && + (!node.attrs || utils.isEmptyObject(node.attrs)) + ) { + node.parentNode.removeChild(node, true); + } + return; + } + switch (node.tagName) { + case "div": + if ((val = node.getAttr("cdata_tag"))) { + node.tagName = val; + node.appendChild(UE.uNode.createText(node.getAttr("cdata_data"))); + node.setAttr({ + cdata_tag: "", + cdata_data: "", + _ue_custom_node_: "" + }); + } + break; + case "a": + if ((val = node.getAttr("_href"))) { + node.setAttr({ + href: utils.html(val), + _href: "" + }); + } + break; + break; + case "span": + val = node.getAttr("id"); + if (val && /^_baidu_bookmark_/i.test(val)) { + node.parentNode.removeChild(node); + } + //将color的rgb格式转换为#16进制格式 + if (me.getOpt("rgb2Hex")) { + var cssStyle = node.getAttr("style"); + if (cssStyle) { + node.setAttr( + "style", + cssStyle.replace(/rgba?\(([\d,\s]+)\)/g, function (a, value) { + var array = value.split(","); + if (array.length > 3) return ""; + value = "#"; + for (var i = 0, color; (color = array[i++]);) { + color = parseInt( + color.replace(/[^\d]/gi, ""), + 10 + ).toString(16); + value += color.length == 1 ? "0" + color : color; + } + return value.toUpperCase(); + }) + ); + } + } + break; + case "img": + if ((val = node.getAttr("_src"))) { + node.setAttr({ + src: node.getAttr("_src"), + _src: "" + }); + } + } + } + }); + }); + }; // plugins/inserthtml.js -/** - * 插入html字符串插件 - * @file - * @since 1.2.6.1 - */ + /** + * 插入html字符串插件 + * @file + * @since 1.2.6.1 + */ -/** - * 插入html代码 - * @command inserthtml - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } html 插入的html字符串 - * @remaind 插入的标签内容是在当前的选区位置上插入,如果当前是闭合状态,那直接插入内容, 如果当前是选中状态,将先清除当前选中内容后,再做插入 - * @warning 注意:该命令会对当前选区的位置,对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。 - * @example - * ```javascript - * //xxx[BB]xxx 当前选区为非闭合选区,选中BB这两个文本 - * //执行命令,插入CC - * //插入后的效果 xxxCCxxx - * //

    xx|xxx

    当前选区为闭合状态 - * //插入

    CC

    - * //结果

    xx

    CC

    xxx

    - * //

    xxxx

    |

    xxx

    当前选区在两个p标签之间 - * //插入 xxxx - * //结果

    xxxx

    xxxx

    xxx

    - * ``` - */ + /** + * 插入html代码 + * @command inserthtml + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } html 插入的html字符串 + * @remaind 插入的标签内容是在当前的选区位置上插入,如果当前是闭合状态,那直接插入内容, 如果当前是选中状态,将先清除当前选中内容后,再做插入 + * @warning 注意:该命令会对当前选区的位置,对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。 + * @example + * ```javascript + * //xxx[BB]xxx 当前选区为非闭合选区,选中BB这两个文本 + * //执行命令,插入CC + * //插入后的效果 xxxCCxxx + * //

    xx|xxx

    当前选区为闭合状态 + * //插入

    CC

    + * //结果

    xx

    CC

    xxx

    + * //

    xxxx

    |

    xxx

    当前选区在两个p标签之间 + * //插入 xxxx + * //结果

    xxxx

    xxxx

    xxx

    + * ``` + */ -UE.commands["inserthtml"] = { - execCommand: function(command, html, notNeedFilter) { - var me = this, - range, - div; - if (!html) { - return; - } - if (me.fireEvent("beforeinserthtml", html) === true) { - return; - } - range = me.selection.getRange(); - div = range.document.createElement("div"); - div.style.display = "inline"; - - if (!notNeedFilter) { - var root = UE.htmlparser(html); - //如果给了过滤规则就先进行过滤 - if (me.options.filterRules) { - UE.filterNode(root, me.options.filterRules); - } - //执行默认的处理 - me.filterInputRule(root); - html = root.toHtml(); - } - div.innerHTML = utils.trim(html); - - if (!range.collapsed) { - var tmpNode = range.startContainer; - if (domUtils.isFillChar(tmpNode)) { - range.setStartBefore(tmpNode); - } - tmpNode = range.endContainer; - if (domUtils.isFillChar(tmpNode)) { - range.setEndAfter(tmpNode); - } - range.txtToElmBoundary(); - //结束边界可能放到了br的前边,要把br包含进来 - // x[xxx]
    - if (range.endContainer && range.endContainer.nodeType == 1) { - tmpNode = range.endContainer.childNodes[range.endOffset]; - if (tmpNode && domUtils.isBr(tmpNode)) { - range.setEndAfter(tmpNode); - } - } - if (range.startOffset == 0) { - tmpNode = range.startContainer; - if (domUtils.isBoundaryNode(tmpNode, "firstChild")) { - tmpNode = range.endContainer; - if ( - range.endOffset == - (tmpNode.nodeType == 3 - ? tmpNode.nodeValue.length - : tmpNode.childNodes.length) && - domUtils.isBoundaryNode(tmpNode, "lastChild") - ) { - me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; - range.setStart(me.body.firstChild, 0).collapse(true); - } - } - } - !range.collapsed && range.deleteContents(); - if (range.startContainer.nodeType == 1) { - var child = range.startContainer.childNodes[range.startOffset], - pre; - if ( - child && - domUtils.isBlockElm(child) && - (pre = child.previousSibling) && - domUtils.isBlockElm(pre) - ) { - range.setEnd(pre, pre.childNodes.length).collapse(); - while (child.firstChild) { - pre.appendChild(child.firstChild); - } - domUtils.remove(child); - } - } - } - - var child, - parent, - pre, - tmp, - hadBreak = 0, - nextNode; - //如果当前位置选中了fillchar要干掉,要不会产生空行 - if (range.inFillChar()) { - child = range.startContainer; - if (domUtils.isFillChar(child)) { - range.setStartBefore(child).collapse(true); - domUtils.remove(child); - } else if (domUtils.isFillChar(child, true)) { - child.nodeValue = child.nodeValue.replace(fillCharReg, ""); - range.startOffset--; - range.collapsed && range.collapse(true); - } - } - //列表单独处理 - var li = domUtils.findParentByTagName(range.startContainer, "li", true); - if (li) { - var next, last; - while ((child = div.firstChild)) { - //针对hr单独处理一下先 - while ( - child && - (child.nodeType == 3 || - !domUtils.isBlockElm(child) || - child.tagName == "HR") - ) { - next = child.nextSibling; - range.insertNode(child).collapse(); - last = child; - child = next; - } - if (child) { - if (/^(ol|ul)$/i.test(child.tagName)) { - while (child.firstChild) { - last = child.firstChild; - domUtils.insertAfter(li, child.firstChild); - li = li.nextSibling; + UE.commands["inserthtml"] = { + execCommand: function (command, html, notNeedFilter) { + var me = this, + range, + div; + if (!html) { + return; } - domUtils.remove(child); - } else { - var tmpLi; - next = child.nextSibling; - tmpLi = me.document.createElement("li"); - domUtils.insertAfter(li, tmpLi); - tmpLi.appendChild(child); - last = child; - child = next; - li = tmpLi; - } - } - } - li = domUtils.findParentByTagName(range.startContainer, "li", true); - if (domUtils.isEmptyBlock(li)) { - domUtils.remove(li); - } - if (last) { - range.setStartAfter(last).collapse(true).select(true); - } - } else { - while ((child = div.firstChild)) { - if (hadBreak) { - var p = me.document.createElement("p"); - while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) { - nextNode = child.nextSibling; - p.appendChild(child); - child = nextNode; - } - if (p.firstChild) { - child = p; - } - } - range.insertNode(child); - nextNode = child.nextSibling; - if ( - !hadBreak && - child.nodeType == domUtils.NODE_ELEMENT && - domUtils.isBlockElm(child) - ) { - parent = domUtils.findParent(child, function(node) { - return domUtils.isBlockElm(node); - }); - if ( - parent && - parent.tagName.toLowerCase() != "body" && - !( - dtd[parent.tagName][child.nodeName] && child.parentNode === parent - ) - ) { - if (!dtd[parent.tagName][child.nodeName]) { - pre = parent; + if (me.fireEvent("beforeinserthtml", html) === true) { + return; + } + range = me.selection.getRange(); + div = range.document.createElement("div"); + div.style.display = "inline"; + + if (!notNeedFilter) { + var root = UE.htmlparser(html); + //如果给了过滤规则就先进行过滤 + if (me.options.filterRules) { + UE.filterNode(root, me.options.filterRules); + } + //执行默认的处理 + me.filterInputRule(root); + html = root.toHtml(); + } + div.innerHTML = utils.trim(html); + + if (!range.collapsed) { + var tmpNode = range.startContainer; + if (domUtils.isFillChar(tmpNode)) { + range.setStartBefore(tmpNode); + } + tmpNode = range.endContainer; + if (domUtils.isFillChar(tmpNode)) { + range.setEndAfter(tmpNode); + } + range.txtToElmBoundary(); + //结束边界可能放到了br的前边,要把br包含进来 + // x[xxx]
    + if (range.endContainer && range.endContainer.nodeType == 1) { + tmpNode = range.endContainer.childNodes[range.endOffset]; + if (tmpNode && domUtils.isBr(tmpNode)) { + range.setEndAfter(tmpNode); + } + } + if (range.startOffset == 0) { + tmpNode = range.startContainer; + if (domUtils.isBoundaryNode(tmpNode, "firstChild")) { + tmpNode = range.endContainer; + if ( + range.endOffset == + (tmpNode.nodeType == 3 + ? tmpNode.nodeValue.length + : tmpNode.childNodes.length) && + domUtils.isBoundaryNode(tmpNode, "lastChild") + ) { + me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; + range.setStart(me.body.firstChild, 0).collapse(true); + } + } + } + !range.collapsed && range.deleteContents(); + if (range.startContainer.nodeType == 1) { + var child = range.startContainer.childNodes[range.startOffset], + pre; + if ( + child && + domUtils.isBlockElm(child) && + (pre = child.previousSibling) && + domUtils.isBlockElm(pre) + ) { + range.setEnd(pre, pre.childNodes.length).collapse(); + while (child.firstChild) { + pre.appendChild(child.firstChild); + } + domUtils.remove(child); + } + } + } + + var child, + parent, + pre, + tmp, + hadBreak = 0, + nextNode; + //如果当前位置选中了fillchar要干掉,要不会产生空行 + if (range.inFillChar()) { + child = range.startContainer; + if (domUtils.isFillChar(child)) { + range.setStartBefore(child).collapse(true); + domUtils.remove(child); + } else if (domUtils.isFillChar(child, true)) { + child.nodeValue = child.nodeValue.replace(fillCharReg, ""); + range.startOffset--; + range.collapsed && range.collapse(true); + } + } + //列表单独处理 + var li = domUtils.findParentByTagName(range.startContainer, "li", true); + if (li) { + var next, last; + while ((child = div.firstChild)) { + //针对hr单独处理一下先 + while ( + child && + (child.nodeType == 3 || + !domUtils.isBlockElm(child) || + child.tagName == "HR") + ) { + next = child.nextSibling; + range.insertNode(child).collapse(); + last = child; + child = next; + } + if (child) { + if (/^(ol|ul)$/i.test(child.tagName)) { + while (child.firstChild) { + last = child.firstChild; + domUtils.insertAfter(li, child.firstChild); + li = li.nextSibling; + } + domUtils.remove(child); + } else { + var tmpLi; + next = child.nextSibling; + tmpLi = me.document.createElement("li"); + domUtils.insertAfter(li, tmpLi); + tmpLi.appendChild(child); + last = child; + child = next; + li = tmpLi; + } + } + } + li = domUtils.findParentByTagName(range.startContainer, "li", true); + if (domUtils.isEmptyBlock(li)) { + domUtils.remove(li); + } + if (last) { + range.setStartAfter(last).collapse(true).select(true); + } } else { - tmp = child.parentNode; - while (tmp !== parent) { - pre = tmp; - tmp = tmp.parentNode; - } + while ((child = div.firstChild)) { + if (hadBreak) { + var p = me.document.createElement("p"); + while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) { + nextNode = child.nextSibling; + p.appendChild(child); + child = nextNode; + } + if (p.firstChild) { + child = p; + } + } + range.insertNode(child); + nextNode = child.nextSibling; + if ( + !hadBreak && + child.nodeType == domUtils.NODE_ELEMENT && + domUtils.isBlockElm(child) + ) { + parent = domUtils.findParent(child, function (node) { + return domUtils.isBlockElm(node); + }); + if ( + parent && + parent.tagName.toLowerCase() != "body" && + !( + dtd[parent.tagName][child.nodeName] && child.parentNode === parent + ) + ) { + if (!dtd[parent.tagName][child.nodeName]) { + pre = parent; + } else { + tmp = child.parentNode; + while (tmp !== parent) { + pre = tmp; + tmp = tmp.parentNode; + } + } + + domUtils.breakParent(child, pre || tmp); + //去掉break后前一个多余的节点

    |<[p> ==>

    |

    + var pre = child.previousSibling; + domUtils.trimWhiteTextNode(pre); + if (!pre.childNodes.length) { + domUtils.remove(pre); + } + //trace:2012,在非ie的情况,切开后剩下的节点有可能不能点入光标添加br占位 + + if ( + !browser.ie && + (next = child.nextSibling) && + domUtils.isBlockElm(next) && + next.lastChild && + !domUtils.isBr(next.lastChild) + ) { + next.appendChild(me.document.createElement("br")); + } + hadBreak = 1; + } + } + var next = child.nextSibling; + if (!div.firstChild && next && domUtils.isBlockElm(next)) { + range.setStart(next, 0).collapse(true); + break; + } + range.setEndAfter(child).collapse(); + } + + child = range.startContainer; + + if (nextNode && domUtils.isBr(nextNode)) { + domUtils.remove(nextNode); + } + //用chrome可能有空白展位符 + if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) { + if ((nextNode = child.nextSibling)) { + domUtils.remove(child); + if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) { + range.setStart(nextNode, 0).collapse(true).shrinkBoundary(); + } + } else { + try { + child.innerHTML = browser.ie ? domUtils.fillChar : "
    "; + } catch (e) { + range.setStartBefore(child); + domUtils.remove(child); + } + } + } + //加上true因为在删除表情等时会删两次,第一次是删的fillData + try { + range.select(true); + } catch (e) { + } } - domUtils.breakParent(child, pre || tmp); - //去掉break后前一个多余的节点

    |<[p> ==>

    |

    - var pre = child.previousSibling; - domUtils.trimWhiteTextNode(pre); - if (!pre.childNodes.length) { - domUtils.remove(pre); - } - //trace:2012,在非ie的情况,切开后剩下的节点有可能不能点入光标添加br占位 - - if ( - !browser.ie && - (next = child.nextSibling) && - domUtils.isBlockElm(next) && - next.lastChild && - !domUtils.isBr(next.lastChild) - ) { - next.appendChild(me.document.createElement("br")); - } - hadBreak = 1; - } + setTimeout(function () { + range = me.selection.getRange(); + range.scrollToView( + me.autoHeightEnabled, + me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0 + ); + me.fireEvent("afterinserthtml", html); + }, 200); } - var next = child.nextSibling; - if (!div.firstChild && next && domUtils.isBlockElm(next)) { - range.setStart(next, 0).collapse(true); - break; - } - range.setEndAfter(child).collapse(); - } - - child = range.startContainer; - - if (nextNode && domUtils.isBr(nextNode)) { - domUtils.remove(nextNode); - } - //用chrome可能有空白展位符 - if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) { - if ((nextNode = child.nextSibling)) { - domUtils.remove(child); - if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) { - range.setStart(nextNode, 0).collapse(true).shrinkBoundary(); - } - } else { - try { - child.innerHTML = browser.ie ? domUtils.fillChar : "
    "; - } catch (e) { - range.setStartBefore(child); - domUtils.remove(child); - } - } - } - //加上true因为在删除表情等时会删两次,第一次是删的fillData - try { - range.select(true); - } catch (e) {} - } - - setTimeout(function() { - range = me.selection.getRange(); - range.scrollToView( - me.autoHeightEnabled, - me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0 - ); - me.fireEvent("afterinserthtml", html); - }, 200); - } -}; + }; // plugins/autotypeset.js -/** - * 自动排版 - * @file - * @since 1.2.6.1 - */ + /** + * 自动排版 + * @file + * @since 1.2.6.1 + */ -/** - * 对当前编辑器的内容执行自动排版, 排版的行为根据config配置文件里的“autotypeset”选项进行控制。 - * @command autotypeset - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'autotypeset' ); - * ``` - */ + /** + * 对当前编辑器的内容执行自动排版, 排版的行为根据config配置文件里的“autotypeset”选项进行控制。 + * @command autotypeset + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'autotypeset' ); + * ``` + */ -UE.plugins["autotypeset"] = function() { - this.setOpt({ - // 自动排版参数 - autotypeset: { - // 合并空行 - mergeEmptyline: true, - // 去掉冗余的class - removeClass: true, - // 去掉空行 - removeEmptyline: false, - // 段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版 - textAlign: "left", - // 图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版 - imageBlockLine: "center", - // 根据规则过滤没事粘贴进来的内容 - pasteFilter: false, - // 去掉所有的内嵌字号,使用编辑器默认的字号 - clearFontSize: false, - // 去掉所有的内嵌字体,使用编辑器默认的字体 - clearFontFamily: false, - // 去掉空节点 - removeEmptyNode: false, - // 可以去掉的标签 - removeTagNames: utils.extend({ div: 1 }, dtd.$removeEmpty), - // 行首缩进 - indent: false, - // 行首缩进的大小 - indentValue: "2em", - // 全角转半角 - bdc2sb: false, - // 半角转全角 - tobdc: false - } - }); - - var me = this, - opt = me.options.autotypeset, - remainClass = { - selectTdClass: 1, - pagebreak: 1, - anchorclass: 1 - }, - remainTag = { - li: 1 - }, - tags = { - div: 1, - p: 1, - //trace:2183 这些也认为是行 - blockquote: 1, - center: 1, - h1: 1, - h2: 1, - h3: 1, - h4: 1, - h5: 1, - h6: 1, - span: 1 - }, - highlightCont; - //升级了版本,但配置项目里没有autotypeset - if (!opt) { - return; - } - - readLocalOpts(); - - function isLine(node, notEmpty) { - if (!node || node.nodeType == 3) return 0; - if (domUtils.isBr(node)) return 1; - if (node && node.parentNode && tags[node.tagName.toLowerCase()]) { - if ( - (highlightCont && highlightCont.contains(node)) || - node.getAttribute("pagebreak") - ) { - return 0; - } - - return notEmpty - ? !domUtils.isEmptyBlock(node) - : domUtils.isEmptyBlock( - node, - new RegExp("[\\s" + domUtils.fillChar + "]", "g") - ); - } - } - - function removeNotAttributeSpan(node) { - if (!node.style.cssText) { - domUtils.removeAttributes(node, ["style"]); - if ( - node.tagName.toLowerCase() == "span" && - domUtils.hasNoAttributes(node) - ) { - domUtils.remove(node, true); - } - } - } - function autotype(type, html) { - var me = this, - cont; - if (html) { - if (!opt.pasteFilter) { - return; - } - cont = me.document.createElement("div"); - cont.innerHTML = html.html; - } else { - cont = me.document.body; - } - var nodes = domUtils.getElementsByTagName(cont, "*"); - - // 行首缩进,段落方向,段间距,段内间距 - for (var i = 0, ci; (ci = nodes[i++]); ) { - if (me.fireEvent("excludeNodeinautotype", ci) === true) { - continue; - } - //font-size - if (opt.clearFontSize && ci.style.fontSize) { - domUtils.removeStyle(ci, "font-size"); - - removeNotAttributeSpan(ci); - } - //font-family - if (opt.clearFontFamily && ci.style.fontFamily) { - domUtils.removeStyle(ci, "font-family"); - removeNotAttributeSpan(ci); - } - - if (isLine(ci)) { - //合并空行 - if (opt.mergeEmptyline) { - var next = ci.nextSibling, - tmpNode, - isBr = domUtils.isBr(ci); - while (isLine(next)) { - tmpNode = next; - next = tmpNode.nextSibling; - if (isBr && (!next || (next && !domUtils.isBr(next)))) { - break; + UE.plugins["autotypeset"] = function () { + this.setOpt({ + // 自动排版参数 + autotypeset: { + // 合并空行 + mergeEmptyline: true, + // 去掉冗余的class + removeClass: true, + // 去掉空行 + removeEmptyline: false, + // 段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版 + textAlign: "left", + // 图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版 + imageBlockLine: "center", + // 根据规则过滤没事粘贴进来的内容 + pasteFilter: false, + // 去掉所有的内嵌字号,使用编辑器默认的字号 + clearFontSize: false, + // 去掉所有的内嵌字体,使用编辑器默认的字体 + clearFontFamily: false, + // 去掉空节点 + removeEmptyNode: false, + // 可以去掉的标签 + removeTagNames: utils.extend({div: 1}, dtd.$removeEmpty), + // 行首缩进 + indent: false, + // 行首缩进的大小 + indentValue: "2em", + // 全角转半角 + bdc2sb: false, + // 半角转全角 + tobdc: false } - domUtils.remove(tmpNode); - } - } - //去掉空行,保留占位的空行 - if ( - opt.removeEmptyline && - domUtils.inDoc(ci, cont) && - !remainTag[ci.parentNode.tagName.toLowerCase()] - ) { - if (domUtils.isBr(ci)) { - next = ci.nextSibling; - if (next && !domUtils.isBr(next)) { - continue; - } - } - domUtils.remove(ci); - continue; - } - } - if (isLine(ci, true) && ci.tagName != "SPAN") { - if (opt.indent) { - ci.style.textIndent = opt.indentValue; - } - if (opt.textAlign) { - ci.style.textAlign = opt.textAlign; - } - // if(opt.lineHeight) - // ci.style.lineHeight = opt.lineHeight + 'cm'; - } + }); - //去掉class,保留的class不去掉 - if ( - opt.removeClass && - ci.className && - !remainClass[ci.className.toLowerCase()] - ) { - if (highlightCont && highlightCont.contains(ci)) { - continue; + var me = this, + opt = me.options.autotypeset, + remainClass = { + selectTdClass: 1, + pagebreak: 1, + anchorclass: 1 + }, + remainTag = { + li: 1 + }, + tags = { + div: 1, + p: 1, + //trace:2183 这些也认为是行 + blockquote: 1, + center: 1, + h1: 1, + h2: 1, + h3: 1, + h4: 1, + h5: 1, + h6: 1, + span: 1 + }, + highlightCont; + //升级了版本,但配置项目里没有autotypeset + if (!opt) { + return; } - domUtils.removeAttributes(ci, ["class"]); - } - //表情不处理 - if ( - opt.imageBlockLine && - ci.tagName.toLowerCase() == "img" && - !ci.getAttribute("emotion") - ) { - if (html) { - var img = ci; - switch (opt.imageBlockLine) { - case "left": - case "right": - case "none": - var pN = img.parentNode, - tmpNode, - pre, - next; - while (dtd.$inline[pN.tagName] || pN.tagName == "A") { - pN = pN.parentNode; - } - tmpNode = pN; - if ( - tmpNode.tagName == "P" && - domUtils.getStyle(tmpNode, "text-align") == "center" - ) { + readLocalOpts(); + + function isLine(node, notEmpty) { + if (!node || node.nodeType == 3) return 0; + if (domUtils.isBr(node)) return 1; + if (node && node.parentNode && tags[node.tagName.toLowerCase()]) { if ( - !domUtils.isBody(tmpNode) && - domUtils.getChildCount(tmpNode, function(node) { - return !domUtils.isBr(node) && !domUtils.isWhitespace(node); - }) == 1 + (highlightCont && highlightCont.contains(node)) || + node.getAttribute("pagebreak") ) { - pre = tmpNode.previousSibling; - next = tmpNode.nextSibling; - if ( - pre && - next && - pre.nodeType == 1 && - next.nodeType == 1 && - pre.tagName == next.tagName && - domUtils.isBlockElm(pre) - ) { - pre.appendChild(tmpNode.firstChild); - while (next.firstChild) { - pre.appendChild(next.firstChild); + return 0; + } + + return notEmpty + ? !domUtils.isEmptyBlock(node) + : domUtils.isEmptyBlock( + node, + new RegExp("[\\s" + domUtils.fillChar + "]", "g") + ); + } + } + + function removeNotAttributeSpan(node) { + if (!node.style.cssText) { + domUtils.removeAttributes(node, ["style"]); + if ( + node.tagName.toLowerCase() == "span" && + domUtils.hasNoAttributes(node) + ) { + domUtils.remove(node, true); + } + } + } + + function autotype(type, html) { + var me = this, + cont; + if (html) { + if (!opt.pasteFilter) { + return; + } + cont = me.document.createElement("div"); + cont.innerHTML = html.html; + } else { + cont = me.document.body; + } + var nodes = domUtils.getElementsByTagName(cont, "*"); + + // 行首缩进,段落方向,段间距,段内间距 + for (var i = 0, ci; (ci = nodes[i++]);) { + if (me.fireEvent("excludeNodeinautotype", ci) === true) { + continue; + } + //font-size + if (opt.clearFontSize && ci.style.fontSize) { + domUtils.removeStyle(ci, "font-size"); + + removeNotAttributeSpan(ci); + } + //font-family + if (opt.clearFontFamily && ci.style.fontFamily) { + domUtils.removeStyle(ci, "font-family"); + removeNotAttributeSpan(ci); + } + + if (isLine(ci)) { + //合并空行 + if (opt.mergeEmptyline) { + var next = ci.nextSibling, + tmpNode, + isBr = domUtils.isBr(ci); + while (isLine(next)) { + tmpNode = next; + next = tmpNode.nextSibling; + if (isBr && (!next || (next && !domUtils.isBr(next)))) { + break; + } + domUtils.remove(tmpNode); + } + } + //去掉空行,保留占位的空行 + if ( + opt.removeEmptyline && + domUtils.inDoc(ci, cont) && + !remainTag[ci.parentNode.tagName.toLowerCase()] + ) { + if (domUtils.isBr(ci)) { + next = ci.nextSibling; + if (next && !domUtils.isBr(next)) { + continue; + } + } + domUtils.remove(ci); + continue; } - domUtils.remove(tmpNode); - domUtils.remove(next); - } else { - domUtils.setStyle(tmpNode, "text-align", ""); - } } - } - domUtils.setStyle(img, "float", opt.imageBlockLine); - break; - case "center": - if (me.queryCommandValue("imagefloat") != "center") { - pN = img.parentNode; - domUtils.setStyle(img, "float", "none"); - tmpNode = img; - while ( - pN && - domUtils.getChildCount(pN, function(node) { - return !domUtils.isBr(node) && !domUtils.isWhitespace(node); - }) == 1 && - (dtd.$inline[pN.tagName] || pN.tagName == "A") + if (isLine(ci, true) && ci.tagName != "SPAN") { + if (opt.indent) { + ci.style.textIndent = opt.indentValue; + } + if (opt.textAlign) { + ci.style.textAlign = opt.textAlign; + } + // if(opt.lineHeight) + // ci.style.lineHeight = opt.lineHeight + 'cm'; + } + + //去掉class,保留的class不去掉 + if ( + opt.removeClass && + ci.className && + !remainClass[ci.className.toLowerCase()] ) { - tmpNode = pN; - pN = pN.parentNode; + if (highlightCont && highlightCont.contains(ci)) { + continue; + } + domUtils.removeAttributes(ci, ["class"]); } - var pNode = me.document.createElement("p"); - domUtils.setAttributes(pNode, { - style: "text-align:center" + + //表情不处理 + if ( + opt.imageBlockLine && + ci.tagName.toLowerCase() == "img" && + !ci.getAttribute("emotion") + ) { + if (html) { + var img = ci; + switch (opt.imageBlockLine) { + case "left": + case "right": + case "none": + var pN = img.parentNode, + tmpNode, + pre, + next; + while (dtd.$inline[pN.tagName] || pN.tagName == "A") { + pN = pN.parentNode; + } + tmpNode = pN; + if ( + tmpNode.tagName == "P" && + domUtils.getStyle(tmpNode, "text-align") == "center" + ) { + if ( + !domUtils.isBody(tmpNode) && + domUtils.getChildCount(tmpNode, function (node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 + ) { + pre = tmpNode.previousSibling; + next = tmpNode.nextSibling; + if ( + pre && + next && + pre.nodeType == 1 && + next.nodeType == 1 && + pre.tagName == next.tagName && + domUtils.isBlockElm(pre) + ) { + pre.appendChild(tmpNode.firstChild); + while (next.firstChild) { + pre.appendChild(next.firstChild); + } + domUtils.remove(tmpNode); + domUtils.remove(next); + } else { + domUtils.setStyle(tmpNode, "text-align", ""); + } + } + } + domUtils.setStyle(img, "float", opt.imageBlockLine); + break; + case "center": + if (me.queryCommandValue("imagefloat") != "center") { + pN = img.parentNode; + domUtils.setStyle(img, "float", "none"); + tmpNode = img; + while ( + pN && + domUtils.getChildCount(pN, function (node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 && + (dtd.$inline[pN.tagName] || pN.tagName == "A") + ) { + tmpNode = pN; + pN = pN.parentNode; + } + var pNode = me.document.createElement("p"); + domUtils.setAttributes(pNode, { + style: "text-align:center" + }); + tmpNode.parentNode.insertBefore(pNode, tmpNode); + pNode.appendChild(tmpNode); + domUtils.setStyle(tmpNode, "float", ""); + } + } + } else { + var range = me.selection.getRange(); + range.selectNode(ci).select(); + me.execCommand("imagefloat", opt.imageBlockLine); + } + } + + //去掉冗余的标签 + if (opt.removeEmptyNode) { + if ( + opt.removeTagNames[ci.tagName.toLowerCase()] && + domUtils.hasNoAttributes(ci) && + domUtils.isEmptyBlock(ci) + ) { + domUtils.remove(ci); + } + } + } + if (opt.tobdc) { + var root = UE.htmlparser(cont.innerHTML); + root.traversal(function (node) { + if (node.type == "text") { + node.data = ToDBC(node.data); + } }); - tmpNode.parentNode.insertBefore(pNode, tmpNode); - pNode.appendChild(tmpNode); - domUtils.setStyle(tmpNode, "float", ""); - } - } - } else { - var range = me.selection.getRange(); - range.selectNode(ci).select(); - me.execCommand("imagefloat", opt.imageBlockLine); + cont.innerHTML = root.toHtml(); + } + if (opt.bdc2sb) { + var root = UE.htmlparser(cont.innerHTML); + root.traversal(function (node) { + if (node.type == "text") { + node.data = DBC2SB(node.data); + } + }); + cont.innerHTML = root.toHtml(); + } + if (html) { + html.html = cont.innerHTML; + } } - } - //去掉冗余的标签 - if (opt.removeEmptyNode) { - if ( - opt.removeTagNames[ci.tagName.toLowerCase()] && - domUtils.hasNoAttributes(ci) && - domUtils.isEmptyBlock(ci) - ) { - domUtils.remove(ci); + if (opt.pasteFilter) { + me.addListener("beforepaste", autotype); } - } - } - if (opt.tobdc) { - var root = UE.htmlparser(cont.innerHTML); - root.traversal(function(node) { - if (node.type == "text") { - node.data = ToDBC(node.data); + + function DBC2SB(str) { + var result = ""; + for (var i = 0; i < str.length; i++) { + var code = str.charCodeAt(i); //获取当前字符的unicode编码 + if (code >= 65281 && code <= 65373) { + //在这个unicode编码范围中的是所有的英文字母已经各种字符 + result += String.fromCharCode(str.charCodeAt(i) - 65248); //把全角字符的unicode编码转换为对应半角字符的unicode码 + } else if (code == 12288) { + //空格 + result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32); + } else { + result += str.charAt(i); + } + } + return result; } - }); - cont.innerHTML = root.toHtml(); - } - if (opt.bdc2sb) { - var root = UE.htmlparser(cont.innerHTML); - root.traversal(function(node) { - if (node.type == "text") { - node.data = DBC2SB(node.data); + + function ToDBC(txtstring) { + txtstring = utils.html(txtstring); + var tmp = ""; + var mark = ""; /*用于判断,如果是html尖括里的标记,则不进行全角的转换*/ + for (var i = 0; i < txtstring.length; i++) { + if (txtstring.charCodeAt(i) == 32) { + tmp = tmp + String.fromCharCode(12288); + } else if (txtstring.charCodeAt(i) < 127) { + tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248); + } else { + tmp += txtstring.charAt(i); + } + } + return tmp; } - }); - cont.innerHTML = root.toHtml(); - } - if (html) { - html.html = cont.innerHTML; - } - } - if (opt.pasteFilter) { - me.addListener("beforepaste", autotype); - } - function DBC2SB(str) { - var result = ""; - for (var i = 0; i < str.length; i++) { - var code = str.charCodeAt(i); //获取当前字符的unicode编码 - if (code >= 65281 && code <= 65373) { - //在这个unicode编码范围中的是所有的英文字母已经各种字符 - result += String.fromCharCode(str.charCodeAt(i) - 65248); //把全角字符的unicode编码转换为对应半角字符的unicode码 - } else if (code == 12288) { - //空格 - result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32); - } else { - result += str.charAt(i); - } - } - return result; - } - function ToDBC(txtstring) { - txtstring = utils.html(txtstring); - var tmp = ""; - var mark = ""; /*用于判断,如果是html尖括里的标记,则不进行全角的转换*/ - for (var i = 0; i < txtstring.length; i++) { - if (txtstring.charCodeAt(i) == 32) { - tmp = tmp + String.fromCharCode(12288); - } else if (txtstring.charCodeAt(i) < 127) { - tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248); - } else { - tmp += txtstring.charAt(i); - } - } - return tmp; - } + function readLocalOpts() { + var cookieOpt = me.getPreferences("autotypeset"); + utils.extend(me.options.autotypeset, cookieOpt); + } - function readLocalOpts() { - var cookieOpt = me.getPreferences("autotypeset"); - utils.extend(me.options.autotypeset, cookieOpt); - } - - me.commands["autotypeset"] = { - execCommand: function() { - me.removeListener("beforepaste", autotype); - if (opt.pasteFilter) { - me.addListener("beforepaste", autotype); - } - autotype.call(me); - } - }; -}; + me.commands["autotypeset"] = { + execCommand: function () { + me.removeListener("beforepaste", autotype); + if (opt.pasteFilter) { + me.addListener("beforepaste", autotype); + } + autotype.call(me); + } + }; + }; // plugins/autosubmit.js -/** - * 快捷键提交 - * @file - * @since 1.2.6.1 - */ + /** + * 快捷键提交 + * @file + * @since 1.2.6.1 + */ -/** - * 提交表单 - * @command autosubmit - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'autosubmit' ); - * ``` - */ + /** + * 提交表单 + * @command autosubmit + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'autosubmit' ); + * ``` + */ -UE.plugin.register("autosubmit", function() { - return { - shortcutkey: { - autosubmit: "ctrl+13" //手动提交 - }, - commands: { - autosubmit: { - execCommand: function() { - var me = this, - form = domUtils.findParentByTagName(me.iframe, "form", false); - if (form) { - if (me.fireEvent("beforesubmit") === false) { - return; + UE.plugin.register("autosubmit", function () { + return { + shortcutkey: { + autosubmit: "ctrl+13" //手动提交 + }, + commands: { + autosubmit: { + execCommand: function () { + var me = this, + form = domUtils.findParentByTagName(me.iframe, "form", false); + if (form) { + if (me.fireEvent("beforesubmit") === false) { + return; + } + me.sync(); + form.submit(); + } + } + } } - me.sync(); - form.submit(); - } - } - } - } - }; -}); + }; + }); // plugins/background.js -/** - * 背景插件,为UEditor提供设置背景功能 - * @file - * @since 1.2.6.1 - */ -UE.plugin.register("background", function() { - var me = this, - cssRuleId = "editor_background", - isSetColored, - reg = new RegExp("body[\\s]*\\{(.+)\\}", "i"); + /** + * 背景插件,为UEditor提供设置背景功能 + * @file + * @since 1.2.6.1 + */ + UE.plugin.register("background", function () { + var me = this, + cssRuleId = "editor_background", + isSetColored, + reg = new RegExp("body[\\s]*\\{(.+)\\}", "i"); - function stringToObj(str) { - var obj = {}, - styles = str.split(";"); - utils.each(styles, function(v) { - var index = v.indexOf(":"), - key = utils.trim(v.substr(0, index)).toLowerCase(); - key && (obj[key] = utils.trim(v.substr(index + 1) || "")); - }); - return obj; - } - - function setBackground(obj) { - if (obj) { - var styles = []; - for (var name in obj) { - if (obj.hasOwnProperty(name)) { - styles.push(name + ":" + obj[name] + "; "); + function stringToObj(str) { + var obj = {}, + styles = str.split(";"); + utils.each(styles, function (v) { + var index = v.indexOf(":"), + key = utils.trim(v.substr(0, index)).toLowerCase(); + key && (obj[key] = utils.trim(v.substr(index + 1) || "")); + }); + return obj; } - } - utils.cssRule( - cssRuleId, - styles.length ? "body{" + styles.join("") + "}" : "", - me.document - ); - } else { - utils.cssRule(cssRuleId, "", me.document); - } - } - //重写editor.hasContent方法 - var orgFn = me.hasContents; - me.hasContents = function() { - if (me.queryCommandValue("background")) { - return true; - } - return orgFn.apply(me, arguments); - }; - return { - bindEvents: { - getAllHtml: function(type, headHtml) { - var body = this.body, - su = domUtils.getComputedStyle(body, "background-image"), - url = ""; - if (su.indexOf(me.options.imagePath) > 0) { - url = su - .substring(su.indexOf(me.options.imagePath), su.length - 1) - .replace(/"|\(|\)/gi, ""); - } else { - url = su != "none" ? su.replace(/url\("?|"?\)/gi, "") : ""; + function setBackground(obj) { + if (obj) { + var styles = []; + for (var name in obj) { + if (obj.hasOwnProperty(name)) { + styles.push(name + ":" + obj[name] + "; "); + } + } + utils.cssRule( + cssRuleId, + styles.length ? "body{" + styles.join("") + "}" : "", + me.document + ); + } else { + utils.cssRule(cssRuleId, "", me.document); + } } - var html = ' "; - headHtml.push(html); - }, - aftersetcontent: function() { - if (isSetColored == false) setBackground(); - } - }, - inputRule: function(root) { - isSetColored = false; - utils.each(root.getNodesByTagName("p"), function(p) { - var styles = p.getAttr("data-background"); - if (styles) { - isSetColored = true; - setBackground(stringToObj(styles)); - p.parentNode.removeChild(p); - } - }); - }, - outputRule: function(root) { - var me = this, - styles = (utils.cssRule(cssRuleId, me.document) || "") - .replace(/[\n\r]+/g, "") - .match(reg); - if (styles) { - root.appendChild( - UE.uNode.createElement( - '


    ' - ) - ); - } - }, - commands: { - background: { - execCommand: function(cmd, obj) { - setBackground(obj); - }, - queryCommandValue: function() { - var me = this, - styles = (utils.cssRule(cssRuleId, me.document) || "") - .replace(/[\n\r]+/g, "") - .match(reg); - return styles ? stringToObj(styles[1]) : null; - }, - notNeedUndo: true - } - } - }; -}); + return { + bindEvents: { + getAllHtml: function (type, headHtml) { + var body = this.body, + su = domUtils.getComputedStyle(body, "background-image"), + url = ""; + if (su.indexOf(me.options.imagePath) > 0) { + url = su + .substring(su.indexOf(me.options.imagePath), su.length - 1) + .replace(/"|\(|\)/gi, ""); + } else { + url = su != "none" ? su.replace(/url\("?|"?\)/gi, "") : ""; + } + var html = ' "; + headHtml.push(html); + }, + aftersetcontent: function () { + if (isSetColored == false) setBackground(); + } + }, + inputRule: function (root) { + isSetColored = false; + utils.each(root.getNodesByTagName("p"), function (p) { + var styles = p.getAttr("data-background"); + if (styles) { + isSetColored = true; + setBackground(stringToObj(styles)); + p.parentNode.removeChild(p); + } + }); + }, + outputRule: function (root) { + var me = this, + styles = (utils.cssRule(cssRuleId, me.document) || "") + .replace(/[\n\r]+/g, "") + .match(reg); + if (styles) { + root.appendChild( + UE.uNode.createElement( + '


    ' + ) + ); + } + }, + commands: { + background: { + execCommand: function (cmd, obj) { + setBackground(obj); + }, + queryCommandValue: function () { + var me = this, + styles = (utils.cssRule(cssRuleId, me.document) || "") + .replace(/[\n\r]+/g, "") + .match(reg); + return styles ? stringToObj(styles[1]) : null; + }, + notNeedUndo: true + } + } + }; + }); // plugins/image.js -/** - * 图片插入、排版插件 - * @file - * @since 1.2.6.1 - */ + /** + * 图片插入、排版插件 + * @file + * @since 1.2.6.1 + */ -/** - * 图片对齐方式 - * @command imagefloat - * @method execCommand - * @remind 值center为独占一行居中 - * @param { String } cmd 命令字符串 - * @param { String } align 对齐方式,可传left、right、none、center - * @remaind center表示图片独占一行 - * @example - * ```javascript - * editor.execCommand( 'imagefloat', 'center' ); - * ``` - */ + /** + * 图片对齐方式 + * @command imagefloat + * @method execCommand + * @remind 值center为独占一行居中 + * @param { String } cmd 命令字符串 + * @param { String } align 对齐方式,可传left、right、none、center + * @remaind center表示图片独占一行 + * @example + * ```javascript + * editor.execCommand( 'imagefloat', 'center' ); + * ``` + */ -/** - * 如果选区所在位置是图片区域 - * @command imagefloat - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回图片对齐方式 - * @example - * ```javascript - * editor.queryCommandValue( 'imagefloat' ); - * ``` - */ + /** + * 如果选区所在位置是图片区域 + * @command imagefloat + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回图片对齐方式 + * @example + * ```javascript + * editor.queryCommandValue( 'imagefloat' ); + * ``` + */ -UE.commands["imagefloat"] = { - execCommand: function(cmd, align) { - var me = this, - range = me.selection.getRange(); - if (!range.collapsed) { - var img = range.getClosedNode(); - if (img && img.tagName == "IMG") { - switch (align) { - case "left": - case "right": - case "none": - var pN = img.parentNode, - tmpNode, - pre, - next; - while (dtd.$inline[pN.tagName] || pN.tagName == "A") { - pN = pN.parentNode; - } - tmpNode = pN; - if ( - tmpNode.tagName == "P" && - domUtils.getStyle(tmpNode, "text-align") == "center" - ) { - if ( - !domUtils.isBody(tmpNode) && - domUtils.getChildCount(tmpNode, function(node) { - return !domUtils.isBr(node) && !domUtils.isWhitespace(node); - }) == 1 - ) { - pre = tmpNode.previousSibling; - next = tmpNode.nextSibling; - if ( - pre && - next && - pre.nodeType == 1 && - next.nodeType == 1 && - pre.tagName == next.tagName && - domUtils.isBlockElm(pre) - ) { - pre.appendChild(tmpNode.firstChild); - while (next.firstChild) { - pre.appendChild(next.firstChild); - } - domUtils.remove(tmpNode); - domUtils.remove(next); - } else { - domUtils.setStyle(tmpNode, "text-align", ""); + UE.commands["imagefloat"] = { + execCommand: function (cmd, align) { + var me = this, + range = me.selection.getRange(); + if (!range.collapsed) { + var img = range.getClosedNode(); + if (img && img.tagName === "IMG") { + switch (align) { + case "left": + case "right": + case "none": + var pN = img.parentNode, + tmpNode, + pre, + next; + while (dtd.$inline[pN.tagName] || pN.tagName == "A") { + pN = pN.parentNode; + } + tmpNode = pN; + if ( + tmpNode.tagName == "P" && + domUtils.getStyle(tmpNode, "text-align") == "center" + ) { + if ( + !domUtils.isBody(tmpNode) && + domUtils.getChildCount(tmpNode, function (node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 + ) { + pre = tmpNode.previousSibling; + next = tmpNode.nextSibling; + if ( + pre && + next && + pre.nodeType == 1 && + next.nodeType == 1 && + pre.tagName == next.tagName && + domUtils.isBlockElm(pre) + ) { + pre.appendChild(tmpNode.firstChild); + while (next.firstChild) { + pre.appendChild(next.firstChild); + } + domUtils.remove(tmpNode); + domUtils.remove(next); + } else { + domUtils.setStyle(tmpNode, "text-align", ""); + } + } + + range.selectNode(img).select(); + } + domUtils.setStyle(img, "float", align == "none" ? "" : align); + if (align == "none") { + domUtils.removeAttributes(img, "align"); + } + + break; + case "center": + if (me.queryCommandValue("imagefloat") != "center") { + pN = img.parentNode; + domUtils.setStyle(img, "float", ""); + domUtils.removeAttributes(img, "align"); + tmpNode = img; + while ( + pN && + domUtils.getChildCount(pN, function (node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }) == 1 && + (dtd.$inline[pN.tagName] || pN.tagName == "A") + ) { + tmpNode = pN; + pN = pN.parentNode; + } + range.setStartBefore(tmpNode).setCursor(false); + pN = me.document.createElement("div"); + pN.appendChild(tmpNode); + domUtils.setStyle(tmpNode, "float", ""); + + me.execCommand( + "insertHtml", + '

    ' + + pN.innerHTML + + "

    " + ); + + tmpNode = me.document.getElementById("_img_parent_tmp"); + tmpNode.removeAttribute("id"); + tmpNode = tmpNode.firstChild; + range.selectNode(tmpNode).select(); + //去掉后边多余的元素 + next = tmpNode.parentNode.nextSibling; + if (next && domUtils.isEmptyNode(next)) { + domUtils.remove(next); + } + } + + break; + } } - } - - range.selectNode(img).select(); } - domUtils.setStyle(img, "float", align == "none" ? "" : align); - if (align == "none") { - domUtils.removeAttributes(img, "align"); + }, + queryCommandValue: function () { + var range = this.selection.getRange(), + startNode, + floatStyle; + if (range.collapsed) { + return "none"; + } + startNode = range.getClosedNode(); + if (startNode && startNode.nodeType == 1 && startNode.tagName == "IMG") { + floatStyle = + domUtils.getComputedStyle(startNode, "float") || + startNode.getAttribute("align"); + + if (floatStyle == "none") { + floatStyle = domUtils.getComputedStyle( + startNode.parentNode, + "text-align" + ) == "center" + ? "center" + : floatStyle; + } + return { + left: 1, + right: 1, + center: 1 + }[floatStyle] + ? floatStyle + : "none"; + } + return "none"; + }, + queryCommandState: function () { + var range = this.selection.getRange(), + startNode; + + if (range.collapsed) return -1; + + startNode = range.getClosedNode(); + if (startNode && startNode.nodeType === 1 && startNode.tagName === "IMG") { + return 0; + } + return -1; + } + }; + + /** + * 插入图片 + * @command insertimage + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } opt 属性键值对,这些属性都将被复制到当前插入图片 + * @remind 该命令第二个参数可接受一个图片配置项对象的数组,可以插入多张图片, + * 此时数组的每一个元素都是一个Object类型的图片属性集合。 + * @example + * ```javascript + * editor.execCommand( 'insertimage', { + * src:'a/b/c.jpg', + * width:'100', + * height:'100' + * } ); + * ``` + * @example + * ```javascript + * editor.execCommand( 'insertimage', [{ + * src:'a/b/c.jpg', + * width:'100', + * height:'100' + * },{ + * src:'a/b/d.jpg', + * width:'100', + * height:'100' + * }] ); + * ``` + */ + + UE.commands["insertimage"] = { + execCommand: function (cmd, opt) { + opt = utils.isArray(opt) ? opt : [opt]; + if (!opt.length) { + return; + } + var me = this, + range = me.selection.getRange(), + img = range.getClosedNode(); + + if (me.fireEvent("beforeinsertimage", opt) === true) { + return; } - break; - case "center": - if (me.queryCommandValue("imagefloat") != "center") { - pN = img.parentNode; - domUtils.setStyle(img, "float", ""); - domUtils.removeAttributes(img, "align"); - tmpNode = img; - while ( - pN && - domUtils.getChildCount(pN, function(node) { - return !domUtils.isBr(node) && !domUtils.isWhitespace(node); - }) == 1 && - (dtd.$inline[pN.tagName] || pN.tagName == "A") - ) { - tmpNode = pN; - pN = pN.parentNode; - } - range.setStartBefore(tmpNode).setCursor(false); - pN = me.document.createElement("div"); - pN.appendChild(tmpNode); - domUtils.setStyle(tmpNode, "float", ""); + if ( + img && + /img/i.test(img.tagName) && + (img.className != "edui-faked-video" || + img.className.indexOf("edui-upload-video") != -1) && + !img.getAttribute("data-word-image") + ) { + var first = opt.shift(); + var floatStyle = first["floatStyle"]; + delete first["floatStyle"]; + //// img.style.border = (first.border||0) +"px solid #000"; + //// img.style.margin = (first.margin||0) +"px"; + // img.style.cssText += ';margin:' + (first.margin||0) +"px;" + 'border:' + (first.border||0) +"px solid #000"; + domUtils.setAttributes(img, first); + me.execCommand("imagefloat", floatStyle); + if (opt.length > 0) { + range.setStartAfter(img).setCursor(false, true); + me.execCommand("insertimage", opt); + } + } else { + var html = [], + str = "", + ci; + ci = opt[0]; + if (opt.length == 1) { + str = + '' + ci.alt + '"; + if (ci["floatStyle"] == "center") { + str = '

    ' + str + "

    "; + } + html.push(str); + } else { + for (var i = 0; (ci = opt[i++]);) { + str = + "

    "; + html.push(str); + } + } - me.execCommand( - "insertHtml", - '

    ' + - pN.innerHTML + - "

    " - ); - - tmpNode = me.document.getElementById("_img_parent_tmp"); - tmpNode.removeAttribute("id"); - tmpNode = tmpNode.firstChild; - range.selectNode(tmpNode).select(); - //去掉后边多余的元素 - next = tmpNode.parentNode.nextSibling; - if (next && domUtils.isEmptyNode(next)) { - domUtils.remove(next); - } + me.execCommand("insertHtml", html.join("")); } - break; + me.fireEvent("afterinsertimage", opt); } - } - } - }, - queryCommandValue: function() { - var range = this.selection.getRange(), - startNode, - floatStyle; - if (range.collapsed) { - return "none"; - } - startNode = range.getClosedNode(); - if (startNode && startNode.nodeType == 1 && startNode.tagName == "IMG") { - floatStyle = - domUtils.getComputedStyle(startNode, "float") || - startNode.getAttribute("align"); - - if (floatStyle == "none") { - floatStyle = domUtils.getComputedStyle( - startNode.parentNode, - "text-align" - ) == "center" - ? "center" - : floatStyle; - } - return { - left: 1, - right: 1, - center: 1 - }[floatStyle] - ? floatStyle - : "none"; - } - return "none"; - }, - queryCommandState: function() { - var range = this.selection.getRange(), - startNode; - - if (range.collapsed) return -1; - - startNode = range.getClosedNode(); - if (startNode && startNode.nodeType == 1 && startNode.tagName == "IMG") { - return 0; - } - return -1; - } -}; - -/** - * 插入图片 - * @command insertimage - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { Object } opt 属性键值对,这些属性都将被复制到当前插入图片 - * @remind 该命令第二个参数可接受一个图片配置项对象的数组,可以插入多张图片, - * 此时数组的每一个元素都是一个Object类型的图片属性集合。 - * @example - * ```javascript - * editor.execCommand( 'insertimage', { - * src:'a/b/c.jpg', - * width:'100', - * height:'100' - * } ); - * ``` - * @example - * ```javascript - * editor.execCommand( 'insertimage', [{ - * src:'a/b/c.jpg', - * width:'100', - * height:'100' - * },{ - * src:'a/b/d.jpg', - * width:'100', - * height:'100' - * }] ); - * ``` - */ - -UE.commands["insertimage"] = { - execCommand: function(cmd, opt) { - opt = utils.isArray(opt) ? opt : [opt]; - if (!opt.length) { - return; - } - var me = this, - range = me.selection.getRange(), - img = range.getClosedNode(); - - if (me.fireEvent("beforeinsertimage", opt) === true) { - return; - } - - if ( - img && - /img/i.test(img.tagName) && - (img.className != "edui-faked-video" || - img.className.indexOf("edui-upload-video") != -1) && - !img.getAttribute("data-word-image") - ) { - var first = opt.shift(); - var floatStyle = first["floatStyle"]; - delete first["floatStyle"]; - //// img.style.border = (first.border||0) +"px solid #000"; - //// img.style.margin = (first.margin||0) +"px"; - // img.style.cssText += ';margin:' + (first.margin||0) +"px;" + 'border:' + (first.border||0) +"px solid #000"; - domUtils.setAttributes(img, first); - me.execCommand("imagefloat", floatStyle); - if (opt.length > 0) { - range.setStartAfter(img).setCursor(false, true); - me.execCommand("insertimage", opt); - } - } else { - var html = [], - str = "", - ci; - ci = opt[0]; - if (opt.length == 1) { - str = - '' + ci.alt + '"; - if (ci["floatStyle"] == "center") { - str = '

    ' + str + "

    "; - } - html.push(str); - } else { - for (var i = 0; (ci = opt[i++]); ) { - str = - "

    "; - html.push(str); - } - } - - me.execCommand("insertHtml", html.join("")); - } - - me.fireEvent("afterinsertimage", opt); - } -}; + }; // plugins/justify.js -/** - * 段落格式 - * @file - * @since 1.2.6.1 - */ + /** + * 段落格式 + * @file + * @since 1.2.6.1 + */ -/** - * 段落对齐方式 - * @command justify - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } align 对齐方式:left => 居左,right => 居右,center => 居中,justify => 两端对齐 - * @example - * ```javascript - * editor.execCommand( 'justify', 'center' ); - * ``` - */ -/** - * 如果选区所在位置是段落区域,返回当前段落对齐方式 - * @command justify - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回段落对齐方式 - * @example - * ```javascript - * editor.queryCommandValue( 'justify' ); - * ``` - */ + /** + * 段落对齐方式 + * @command justify + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } align 对齐方式:left => 居左,right => 居右,center => 居中,justify => 两端对齐 + * @example + * ```javascript + * editor.execCommand( 'justify', 'center' ); + * ``` + */ + /** + * 如果选区所在位置是段落区域,返回当前段落对齐方式 + * @command justify + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回段落对齐方式 + * @example + * ```javascript + * editor.queryCommandValue( 'justify' ); + * ``` + */ -UE.plugins["justify"] = function() { - var me = this, - block = domUtils.isBlockElm, - defaultValue = { - left: 1, - right: 1, - center: 1, - justify: 1 - }, - doJustify = function(range, style) { - var bookmark = range.createBookmark(), - filterFn = function(node) { - return node.nodeType == 1 - ? node.tagName.toLowerCase() != "br" && - !domUtils.isBookmarkNode(node) - : !domUtils.isWhitespace(node); + UE.plugins["justify"] = function () { + var me = this, + block = domUtils.isBlockElm, + defaultValue = { + left: 1, + right: 1, + center: 1, + justify: 1 + }, + doJustify = function (range, style) { + var bookmark = range.createBookmark(), + filterFn = function (node) { + return node.nodeType == 1 + ? node.tagName.toLowerCase() != "br" && + !domUtils.isBookmarkNode(node) + : !domUtils.isWhitespace(node); + }; + + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode; + while ( + current && + !( + domUtils.getPosition(current, bookmark2.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + if (current.nodeType == 3 || !block(current)) { + tmpRange.setStartBefore(current); + while (current && current !== bookmark2.end && !block(current)) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function ( + node + ) { + return !block(node); + }); + } + tmpRange.setEndAfter(tmpNode); + var common = tmpRange.getCommonAncestor(); + if (!domUtils.isBody(common) && block(common)) { + domUtils.setStyles( + common, + utils.isString(style) ? {"text-align": style} : style + ); + current = common; + } else { + var p = range.document.createElement("p"); + domUtils.setStyles( + p, + utils.isString(style) ? {"text-align": style} : style + ); + var frag = tmpRange.extractContents(); + p.appendChild(frag); + tmpRange.insertNode(p); + current = p; + } + current = domUtils.getNextDomNode(current, false, filterFn); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); + }; + + UE.commands["justify"] = { + execCommand: function (cmdName, align) { + var range = this.selection.getRange(), + txt; + + //闭合时单独处理 + if (range.collapsed) { + txt = this.document.createTextNode("p"); + range.insertNode(txt); + } + doJustify(range, align); + if (txt) { + range.setStartBefore(txt).collapse(true); + domUtils.remove(txt); + } + + range.select(); + + return true; + }, + queryCommandValue: function () { + var startNode = this.selection.getStart(), + value = domUtils.getComputedStyle(startNode, "text-align"); + return defaultValue[value] ? value : "left"; + }, + queryCommandState: function () { + var start = this.selection.getStart(), + cell = + start && + domUtils.findParentByTagName(start, ["td", "th", "caption"], true); + + return cell ? -1 : 0; + } }; - - range.enlarge(true); - var bookmark2 = range.createBookmark(), - current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), - tmpRange = range.cloneRange(), - tmpNode; - while ( - current && - !( - domUtils.getPosition(current, bookmark2.end) & - domUtils.POSITION_FOLLOWING - ) - ) { - if (current.nodeType == 3 || !block(current)) { - tmpRange.setStartBefore(current); - while (current && current !== bookmark2.end && !block(current)) { - tmpNode = current; - current = domUtils.getNextDomNode(current, false, null, function( - node - ) { - return !block(node); - }); - } - tmpRange.setEndAfter(tmpNode); - var common = tmpRange.getCommonAncestor(); - if (!domUtils.isBody(common) && block(common)) { - domUtils.setStyles( - common, - utils.isString(style) ? { "text-align": style } : style - ); - current = common; - } else { - var p = range.document.createElement("p"); - domUtils.setStyles( - p, - utils.isString(style) ? { "text-align": style } : style - ); - var frag = tmpRange.extractContents(); - p.appendChild(frag); - tmpRange.insertNode(p); - current = p; - } - current = domUtils.getNextDomNode(current, false, filterFn); - } else { - current = domUtils.getNextDomNode(current, true, filterFn); - } - } - return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); }; - UE.commands["justify"] = { - execCommand: function(cmdName, align) { - var range = this.selection.getRange(), - txt; - - //闭合时单独处理 - if (range.collapsed) { - txt = this.document.createTextNode("p"); - range.insertNode(txt); - } - doJustify(range, align); - if (txt) { - range.setStartBefore(txt).collapse(true); - domUtils.remove(txt); - } - - range.select(); - - return true; - }, - queryCommandValue: function() { - var startNode = this.selection.getStart(), - value = domUtils.getComputedStyle(startNode, "text-align"); - return defaultValue[value] ? value : "left"; - }, - queryCommandState: function() { - var start = this.selection.getStart(), - cell = - start && - domUtils.findParentByTagName(start, ["td", "th", "caption"], true); - - return cell ? -1 : 0; - } - }; -}; - // plugins/font.js -/** - * 字体颜色,背景色,字号,字体,下划线,删除线 - * @file - * @since 1.2.6.1 - */ + /** + * 字体颜色,背景色,字号,字体,下划线,删除线 + * @file + * @since 1.2.6.1 + */ -/** - * 字体颜色 - * @command forecolor - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } value 色值(必须十六进制) - * @example - * ```javascript - * editor.execCommand( 'forecolor', '#000' ); - * ``` - */ -/** - * 返回选区字体颜色 - * @command forecolor - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回字体颜色 - * @example - * ```javascript - * editor.queryCommandValue( 'forecolor' ); - * ``` - */ + /** + * 字体颜色 + * @command forecolor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 色值(必须十六进制) + * @example + * ```javascript + * editor.execCommand( 'forecolor', '#000' ); + * ``` + */ + /** + * 返回选区字体颜色 + * @command forecolor + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体颜色 + * @example + * ```javascript + * editor.queryCommandValue( 'forecolor' ); + * ``` + */ -/** - * 字体背景颜色 - * @command backcolor - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } value 色值(必须十六进制) - * @example - * ```javascript - * editor.execCommand( 'backcolor', '#000' ); - * ``` - */ -/** - * 返回选区字体颜色 - * @command backcolor - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回字体背景颜色 - * @example - * ```javascript - * editor.queryCommandValue( 'backcolor' ); - * ``` - */ + /** + * 字体背景颜色 + * @command backcolor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 色值(必须十六进制) + * @example + * ```javascript + * editor.execCommand( 'backcolor', '#000' ); + * ``` + */ + /** + * 返回选区字体颜色 + * @command backcolor + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体背景颜色 + * @example + * ```javascript + * editor.queryCommandValue( 'backcolor' ); + * ``` + */ -/** - * 字体大小 - * @command fontsize - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } value 字体大小 - * @example - * ```javascript - * editor.execCommand( 'fontsize', '14px' ); - * ``` - */ -/** - * 返回选区字体大小 - * @command fontsize - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回字体大小 - * @example - * ```javascript - * editor.queryCommandValue( 'fontsize' ); - * ``` - */ + /** + * 字体大小 + * @command fontsize + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 字体大小 + * @example + * ```javascript + * editor.execCommand( 'fontsize', '14px' ); + * ``` + */ + /** + * 返回选区字体大小 + * @command fontsize + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体大小 + * @example + * ```javascript + * editor.queryCommandValue( 'fontsize' ); + * ``` + */ -/** - * 字体样式 - * @command fontfamily - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } value 字体样式 - * @example - * ```javascript - * editor.execCommand( 'fontfamily', '微软雅黑' ); - * ``` - */ -/** - * 返回选区字体样式 - * @command fontfamily - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回字体样式 - * @example - * ```javascript - * editor.queryCommandValue( 'fontfamily' ); - * ``` - */ + /** + * 字体样式 + * @command fontfamily + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 字体样式 + * @example + * ```javascript + * editor.execCommand( 'fontfamily', '微软雅黑' ); + * ``` + */ + /** + * 返回选区字体样式 + * @command fontfamily + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回字体样式 + * @example + * ```javascript + * editor.queryCommandValue( 'fontfamily' ); + * ``` + */ -/** - * 字体下划线,与删除线互斥 - * @command underline - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'underline' ); - * ``` - */ + /** + * 字体下划线,与删除线互斥 + * @command underline + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'underline' ); + * ``` + */ -/** - * 字体删除线,与下划线互斥 - * @command strikethrough - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'strikethrough' ); - * ``` - */ + /** + * 字体删除线,与下划线互斥 + * @command strikethrough + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'strikethrough' ); + * ``` + */ -/** - * 字体边框 - * @command fontborder - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'fontborder' ); - * ``` - */ + /** + * 字体边框 + * @command fontborder + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'fontborder' ); + * ``` + */ -UE.plugins["font"] = function() { - var me = this, - fonts = { - forecolor: "color", - backcolor: "background-color", - fontsize: "font-size", - fontfamily: "font-family", - underline: "text-decoration", - strikethrough: "text-decoration", - fontborder: "border" - }, - lang = me.getLang(), - needCmd = { underline: 1, strikethrough: 1, fontborder: 1 }, - needSetChild = { - forecolor: "color", - backcolor: "background-color", - fontsize: "font-size", - fontfamily: "font-family" - }; - me.setOpt({ - fontfamily: [ - { name: "default", val: "default" }, - { name: "songti", val: "宋体,SimSun" }, - { name: "yahei", val: "微软雅黑,Microsoft YaHei" }, - { name: "kaiti", val: "楷体,楷体_GB2312,SimKai" }, - { name: "heiti", val: "黑体,SimHei" }, - { name: "lishu", val: "隶书,SimLi" }, - // { name: "andaleMono", val: "andale mono" }, - { name: "arial", val: "arial,helvetica,sans-serif" }, - // { name: "arialBlack", val: "arial black,avant garde" }, - // { name: "comicSansMs", val: "comic sans ms" }, - // { name: "impact", val: "impact,chicago" }, - { name: "timesNewRoman", val: "times new roman" } - ], - fontsize: [10, 11, 12, 14, 16, 18, 20, 24, 36] - }); - - function mergeWithParent(node) { - var parent; - while ((parent = node.parentNode)) { - if ( - parent.tagName == "SPAN" && - domUtils.getChildCount(parent, function(child) { - return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child); - }) == 1 - ) { - parent.style.cssText += node.style.cssText; - domUtils.remove(node, true); - node = parent; - } else { - break; - } - } - } - function mergeChild(rng, cmdName, value) { - if (needSetChild[cmdName]) { - rng.adjustmentBoundary(); - if (!rng.collapsed && rng.startContainer.nodeType == 1) { - var start = rng.startContainer.childNodes[rng.startOffset]; - if (start && domUtils.isTagNode(start, "span")) { - var bk = rng.createBookmark(); - utils.each(domUtils.getElementsByTagName(start, "span"), function( - span - ) { - if (!span.parentNode || domUtils.isBookmarkNode(span)) return; - if ( - cmdName == "backcolor" && - domUtils - .getComputedStyle(span, "background-color") - .toLowerCase() === value - ) { - return; - } - domUtils.removeStyle(span, needSetChild[cmdName]); - if (span.style.cssText.replace(/^\s+$/, "").length == 0) { - domUtils.remove(span, true); - } - }); - rng.moveToBookmark(bk); - } - } - } - } - function mergesibling(rng, cmdName, value) { - var collapsed = rng.collapsed, - bk = rng.createBookmark(), - common; - if (collapsed) { - common = bk.start.parentNode; - while (dtd.$inline[common.tagName]) { - common = common.parentNode; - } - } else { - common = domUtils.getCommonAncestor(bk.start, bk.end); - } - utils.each(domUtils.getElementsByTagName(common, "span"), function(span) { - if (!span.parentNode || domUtils.isBookmarkNode(span)) return; - if (/\s*border\s*:\s*none;?\s*/i.test(span.style.cssText)) { - if (/^\s*border\s*:\s*none;?\s*$/.test(span.style.cssText)) { - domUtils.remove(span, true); - } else { - domUtils.removeStyle(span, "border"); - } - return; - } - if ( - /border/i.test(span.style.cssText) && - span.parentNode.tagName == "SPAN" && - /border/i.test(span.parentNode.style.cssText) - ) { - span.style.cssText = span.style.cssText.replace( - /border[^:]*:[^;]+;?/gi, - "" - ); - } - if (!(cmdName == "fontborder" && value == "none")) { - var next = span.nextSibling; - while (next && next.nodeType == 1 && next.tagName == "SPAN") { - if (domUtils.isBookmarkNode(next) && cmdName == "fontborder") { - span.appendChild(next); - next = span.nextSibling; - continue; - } - if (next.style.cssText == span.style.cssText) { - domUtils.moveChild(next, span); - domUtils.remove(next); - } - if (span.nextSibling === next) break; - next = span.nextSibling; - } - } - - mergeWithParent(span); - if (browser.ie && browser.version > 8) { - //拷贝父亲们的特别的属性,这里只做背景颜色的处理 - var parent = domUtils.findParent(span, function(n) { - return ( - n.tagName == "SPAN" && /background-color/.test(n.style.cssText) - ); + UE.plugins["font"] = function () { + var me = this, + fonts = { + forecolor: "color", + backcolor: "background-color", + fontsize: "font-size", + fontfamily: "font-family", + underline: "text-decoration", + strikethrough: "text-decoration", + fontborder: "border" + }, + lang = me.getLang(), + needCmd = {underline: 1, strikethrough: 1, fontborder: 1}, + needSetChild = { + forecolor: "color", + backcolor: "background-color", + fontsize: "font-size", + fontfamily: "font-family" + }; + me.setOpt({ + fontfamily: [ + {name: "default", val: "default"}, + {name: "songti", val: "宋体,SimSun"}, + {name: "yahei", val: "微软雅黑,Microsoft YaHei"}, + {name: "kaiti", val: "楷体,楷体_GB2312,SimKai"}, + {name: "heiti", val: "黑体,SimHei"}, + {name: "lishu", val: "隶书,SimLi"}, + // { name: "andaleMono", val: "andale mono" }, + {name: "arial", val: "arial,helvetica,sans-serif"}, + // { name: "arialBlack", val: "arial black,avant garde" }, + // { name: "comicSansMs", val: "comic sans ms" }, + // { name: "impact", val: "impact,chicago" }, + {name: "timesNewRoman", val: "times new roman"} + ], + fontsize: [10, 11, 12, 14, 16, 18, 20, 24, 36] }); - if (parent && !/background-color/.test(span.style.cssText)) { - span.style.backgroundColor = parent.style.backgroundColor; - } - } - }); - rng.moveToBookmark(bk); - mergeChild(rng, cmdName, value); - } - me.addInputRule(function(root) { - utils.each(root.getNodesByTagName("u s del font strike"), function(node) { - if (node.tagName == "font") { - var cssStyle = []; - for (var p in node.attrs) { - switch (p) { - case "size": - cssStyle.push( - "font-size:" + - ({ - "1": "10", - "2": "12", - "3": "16", - "4": "18", - "5": "24", - "6": "32", - "7": "48" - }[node.attrs[p]] || node.attrs[p]) + - "px" - ); - break; - case "color": - cssStyle.push("color:" + node.attrs[p]); - break; - case "face": - cssStyle.push("font-family:" + node.attrs[p]); - break; - case "style": - cssStyle.push(node.attrs[p]); - } - } - node.attrs = { - style: cssStyle.join(";") - }; - } else { - var val = node.tagName == "u" ? "underline" : "line-through"; - node.attrs = { - style: (node.getAttr("style") || "") + "text-decoration:" + val + ";" - }; - } - node.tagName = "span"; - }); - // utils.each(root.getNodesByTagName('span'), function (node) { - // var val; - // if(val = node.getAttr('class')){ - // if(/fontstrikethrough/.test(val)){ - // node.setStyle('text-decoration','line-through'); - // if(node.attrs['class']){ - // node.attrs['class'] = node.attrs['class'].replace(/fontstrikethrough/,''); - // }else{ - // node.setAttr('class') - // } - // } - // if(/fontborder/.test(val)){ - // node.setStyle('border','1px solid #000'); - // if(node.attrs['class']){ - // node.attrs['class'] = node.attrs['class'].replace(/fontborder/,''); - // }else{ - // node.setAttr('class') - // } - // } - // } - // }); - }); - // me.addOutputRule(function(root){ - // utils.each(root.getNodesByTagName('span'), function (node) { - // var val; - // if(val = node.getStyle('text-decoration')){ - // if(/line-through/.test(val)){ - // if(node.attrs['class']){ - // node.attrs['class'] += ' fontstrikethrough'; - // }else{ - // node.setAttr('class','fontstrikethrough') - // } - // } - // - // node.setStyle('text-decoration') - // } - // if(val = node.getStyle('border')){ - // if(/1px/.test(val) && /solid/.test(val)){ - // if(node.attrs['class']){ - // node.attrs['class'] += ' fontborder'; - // - // }else{ - // node.setAttr('class','fontborder') - // } - // } - // node.setStyle('border') - // - // } - // }); - // }); - for (var p in fonts) { - (function(cmd, style) { - UE.commands[cmd] = { - execCommand: function(cmdName, value) { - value = - value || - (this.queryCommandState(cmdName) - ? "none" - : cmdName === "underline" - ? "underline" - : cmdName === "fontborder" ? "1px solid #000" : "line-through"); - var me = this, - range = this.selection.getRange(), - text; - - if (value === "default") { - if (range.collapsed) { - text = me.document.createTextNode("font"); - range.insertNode(text).select(); - } - me.execCommand("removeFormat", "span,a", style); - if (text) { - range.setStartBefore(text).collapse(true); - domUtils.remove(text); - } - mergesibling(range, cmdName, value); - range.select(); - } else { - if (!range.collapsed) { - if (needCmd[cmd] && me.queryCommandValue(cmd)) { - me.execCommand("removeFormat", "span,a", style); - } - range = me.selection.getRange(); - - range.applyInlineStyle("span", { style: style + ":" + value }); - mergesibling(range, cmdName, value); - range.select(); - } else { - var span = domUtils.findParentByTagName( - range.startContainer, - "span", - true - ); - text = me.document.createTextNode("font"); - if ( - span && - !span.children.length && - !span[browser.ie ? "innerText" : "textContent"].replace( - fillCharReg, - "" - ).length - ) { - //for ie hack when enter - range.insertNode(text); - if (needCmd[cmd]) { - range.selectNode(text).select(); - me.execCommand("removeFormat", "span,a", style, null); - - span = domUtils.findParentByTagName(text, "span", true); - range.setStartBefore(text); - } - span && (span.style.cssText += ";" + style + ":" + value); - range.collapse(true).select(); - } else { - range.insertNode(text); - range.selectNode(text).select(); - span = range.document.createElement("span"); - - if (needCmd[cmd]) { - //a标签内的不处理跳过 - if (domUtils.findParentByTagName(text, "a", true)) { - range.setStartBefore(text).setCursor(); - domUtils.remove(text); - return; - } - me.execCommand("removeFormat", "span,a", style); - } - - span.style.cssText = style + ":" + value; - - text.parentNode.insertBefore(span, text); - //修复,span套span 但样式不继承的问题 - if (!browser.ie || (browser.ie && browser.version == 9)) { - var spanParent = span.parentNode; - while (!domUtils.isBlockElm(spanParent)) { - if (spanParent.tagName == "SPAN") { - //opera合并style不会加入";" - span.style.cssText = - spanParent.style.cssText + ";" + span.style.cssText; - } - spanParent = spanParent.parentNode; - } - } - - if (opera) { - setTimeout(function() { - range.setStart(span, 0).collapse(true); - mergesibling(range, cmdName, value); - range.select(); - }); + function mergeWithParent(node) { + var parent; + while ((parent = node.parentNode)) { + if ( + parent.tagName == "SPAN" && + domUtils.getChildCount(parent, function (child) { + return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child); + }) == 1 + ) { + parent.style.cssText += node.style.cssText; + domUtils.remove(node, true); + node = parent; } else { - range.setStart(span, 0).collapse(true); - mergesibling(range, cmdName, value); - range.select(); + break; } - - //trace:981 - //domUtils.mergeToParent(span) - } - domUtils.remove(text); } - } - return true; - }, - queryCommandValue: function(cmdName) { - var startNode = this.selection.getStart(); - var styleVal; - - //trace:946 - if (cmdName === "underline" || cmdName === "strikethrough") { - var tmpNode = startNode, - value; - while ( - tmpNode && - !domUtils.isBlockElm(tmpNode) && - !domUtils.isBody(tmpNode) - ) { - if (tmpNode.nodeType == 1) { - value = domUtils.getComputedStyle(tmpNode, style); - if (value != "none") { - return value; - } - } - - tmpNode = tmpNode.parentNode; - } - return "none"; - } - - else if (cmdName === "fontborder") { - var tmp = startNode, - val; - while (tmp && dtd.$inline[tmp.tagName]) { - if ((val = domUtils.getComputedStyle(tmp, "border"))) { - if (/1px/.test(val) && /solid/.test(val)) { - return val; - } - } - tmp = tmp.parentNode; - } - return ""; - } - - else if (cmdName === "FontSize") { - styleVal = domUtils.getComputedStyle(startNode, style); - tmp = /^([\d\.]+)(\w+)$/.exec(styleVal); - - if (tmp) { - return Math.floor(tmp[1]) + tmp[2]; - } - - return styleVal; - } - - else if(cmdName === 'FontFamily'){ - styleVal = domUtils.getComputedStyle(startNode, style) - // 移除左右引号 - styleVal = styleVal.replace(/['"]/g, ''); - var fontFamily = lang.fontfamily.default; - var fontList = me.options["fontfamily"] || []; - for(var i=0;i 8) { + //拷贝父亲们的特别的属性,这里只做背景颜色的处理 + var parent = domUtils.findParent(span, function (n) { + return ( + n.tagName == "SPAN" && /background-color/.test(n.style.cssText) + ); + }); + if (parent && !/background-color/.test(span.style.cssText)) { + span.style.backgroundColor = parent.style.backgroundColor; + } + } + }); + rng.moveToBookmark(bk); + mergeChild(rng, cmdName, value); + } + + me.addInputRule(function (root) { + utils.each(root.getNodesByTagName("u s del font strike"), function (node) { + if (node.tagName == "font") { + var cssStyle = []; + for (var p in node.attrs) { + switch (p) { + case "size": + cssStyle.push( + "font-size:" + + ({ + "1": "10", + "2": "12", + "3": "16", + "4": "18", + "5": "24", + "6": "32", + "7": "48" + }[node.attrs[p]] || node.attrs[p]) + + "px" + ); + break; + case "color": + cssStyle.push("color:" + node.attrs[p]); + break; + case "face": + cssStyle.push("font-family:" + node.attrs[p]); + break; + case "style": + cssStyle.push(node.attrs[p]); + } + } + node.attrs = { + style: cssStyle.join(";") + }; + } else { + var val = node.tagName == "u" ? "underline" : "line-through"; + node.attrs = { + style: (node.getAttr("style") || "") + "text-decoration:" + val + ";" + }; + } + node.tagName = "span"; + }); + // utils.each(root.getNodesByTagName('span'), function (node) { + // var val; + // if(val = node.getAttr('class')){ + // if(/fontstrikethrough/.test(val)){ + // node.setStyle('text-decoration','line-through'); + // if(node.attrs['class']){ + // node.attrs['class'] = node.attrs['class'].replace(/fontstrikethrough/,''); + // }else{ + // node.setAttr('class') + // } + // } + // if(/fontborder/.test(val)){ + // node.setStyle('border','1px solid #000'); + // if(node.attrs['class']){ + // node.attrs['class'] = node.attrs['class'].replace(/fontborder/,''); + // }else{ + // node.setAttr('class') + // } + // } + // } + // }); + }); + // me.addOutputRule(function(root){ + // utils.each(root.getNodesByTagName('span'), function (node) { + // var val; + // if(val = node.getStyle('text-decoration')){ + // if(/line-through/.test(val)){ + // if(node.attrs['class']){ + // node.attrs['class'] += ' fontstrikethrough'; + // }else{ + // node.setAttr('class','fontstrikethrough') + // } + // } + // + // node.setStyle('text-decoration') + // } + // if(val = node.getStyle('border')){ + // if(/1px/.test(val) && /solid/.test(val)){ + // if(node.attrs['class']){ + // node.attrs['class'] += ' fontborder'; + // + // }else{ + // node.setAttr('class','fontborder') + // } + // } + // node.setStyle('border') + // + // } + // }); + // }); + for (var p in fonts) { + (function (cmd, style) { + UE.commands[cmd] = { + execCommand: function (cmdName, value) { + // console.log("execCommand", cmdName, value); + value = + value || + (this.queryCommandState(cmdName) + ? "none" + : cmdName === "underline" + ? "underline" + : cmdName === "fontborder" ? "1px solid #000" : "line-through"); + var me = this, + range = this.selection.getRange(), + text; + + if (value === "default") { + if (range.collapsed) { + text = me.document.createTextNode("font"); + range.insertNode(text).select(); + } + me.execCommand("removeFormat", "span,a", style); + if (text) { + range.setStartBefore(text).collapse(true); + domUtils.remove(text); + } + mergesibling(range, cmdName, value); + range.select(); + } else { + if (!range.collapsed) { + if (needCmd[cmd] && me.queryCommandValue(cmd)) { + me.execCommand("removeFormat", "span,a", style); + } + range = me.selection.getRange(); + + range.applyInlineStyle("span", {style: style + ":" + value}); + mergesibling(range, cmdName, value); + range.select(); + } else { + var span = domUtils.findParentByTagName( + range.startContainer, + "span", + true + ); + text = me.document.createTextNode("font"); + if ( + span && + !span.children.length && + !span[browser.ie ? "innerText" : "textContent"].replace( + fillCharReg, + "" + ).length + ) { + //for ie hack when enter + range.insertNode(text); + if (needCmd[cmd]) { + range.selectNode(text).select(); + me.execCommand("removeFormat", "span,a", style, null); + + span = domUtils.findParentByTagName(text, "span", true); + range.setStartBefore(text); + } + span && (span.style.cssText += ";" + style + ":" + value); + range.collapse(true).select(); + } else { + range.insertNode(text); + range.selectNode(text).select(); + span = range.document.createElement("span"); + + if (needCmd[cmd]) { + //a标签内的不处理跳过 + if (domUtils.findParentByTagName(text, "a", true)) { + range.setStartBefore(text).setCursor(); + domUtils.remove(text); + return; + } + me.execCommand("removeFormat", "span,a", style); + } + + span.style.cssText = style + ":" + value; + + text.parentNode.insertBefore(span, text); + //修复,span套span 但样式不继承的问题 + if (!browser.ie || (browser.ie && browser.version === 9)) { + var spanParent = span.parentNode; + while (!domUtils.isBlockElm(spanParent)) { + if (spanParent.tagName === "SPAN") { + //opera合并style不会加入";" + span.style.cssText = + spanParent.style.cssText + ";" + span.style.cssText; + } + spanParent = spanParent.parentNode; + } + } + + if (opera) { + setTimeout(function () { + range.setStart(span, 0).collapse(true); + mergesibling(range, cmdName, value); + range.select(); + }); + } else { + range.setStart(span, 0).collapse(true); + mergesibling(range, cmdName, value); + range.select(); + } + + //trace:981 + //domUtils.mergeToParent(span) + } + domUtils.remove(text); + } + } + return true; + }, + queryCommandValue: function (cmdName) { + var startNode = this.selection.getStart(); + var styleVal; + + //trace:946 + if (cmdName === "underline" || cmdName === "strikethrough") { + var tmpNode = startNode, + value; + while ( + tmpNode && + !domUtils.isBlockElm(tmpNode) && + !domUtils.isBody(tmpNode) + ) { + if (tmpNode.nodeType === 1) { + value = domUtils.getComputedStyle(tmpNode, style); + if (value !== "none") { + return value; + } + } + + tmpNode = tmpNode.parentNode; + } + return "none"; + } else if (cmdName === "fontborder") { + var tmp = startNode, + val; + while (tmp && dtd.$inline[tmp.tagName]) { + if ((val = domUtils.getComputedStyle(tmp, "border"))) { + if (/1px/.test(val) && /solid/.test(val)) { + return val; + } + } + tmp = tmp.parentNode; + } + return ""; + } else if (cmdName === "FontSize") { + styleVal = domUtils.getComputedStyle(startNode, style); + tmp = /^([\d\.]+)(\w+)$/.exec(styleVal); + + if (tmp) { + return Math.floor(tmp[1]) + tmp[2]; + } + + return styleVal; + } else if (cmdName === 'FontFamily') { + styleVal = domUtils.getComputedStyle(startNode, style) + // 移除左右引号 + styleVal = styleVal.replace(/['"]/g, ''); + // 移除字体 宋体, SimSun 转为 宋体,SimSun,否则以下的判断会出错 + styleVal = styleVal.replace(/\s*,\s*/g, ','); + var fontFamily = lang.fontfamily.default; + var fontList = me.options["fontfamily"] || []; + for (var i = 0; i < fontList.length; i++) { + var v = fontList[i]; + // console.log('FontFamily', styleVal, v.val); + if (v.val === styleVal) { + fontFamily = styleVal; + break; + } + } + // console.log('fontList', fontList); + // console.log('FontFamily', styleVal, fontFamily); + return fontFamily; + } + + value = domUtils.getComputedStyle(startNode, style); + return value; + }, + queryCommandState: function (cmdName) { + if (!needCmd[cmdName]) return 0; + var val = this.queryCommandValue(cmdName); + if (cmdName === "fontborder") { + return /1px/.test(val) && /solid/.test(val); + } else { + return cmdName === "underline" + ? /underline/.test(val) + : /line\-through/.test(val); + } + } + }; + })(p, fonts[p]); + } + }; // plugins/link.js -/** - * 超链接 - * @file - * @since 1.2.6.1 - */ + /** + * 超链接 + * @file + * @since 1.2.6.1 + */ -/** - * 插入超链接 - * @command link - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { Object } options 设置自定义属性,例如:url、title、target - * @example - * ```javascript - * editor.execCommand( 'link', '{ - * url:'ueditor.baidu.com', - * title:'ueditor', - * target:'_blank' - * }' ); - * ``` - */ -/** - * 返回当前选中的第一个超链接节点 - * @command link - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { Element } 超链接节点 - * @example - * ```javascript - * editor.queryCommandValue( 'link' ); - * ``` - */ + /** + * 插入超链接 + * @command link + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } options 设置自定义属性,例如:url、title、target + * @example + * ```javascript + * editor.execCommand( 'link', '{ + * url:'ueditor.baidu.com', + * title:'ueditor', + * target:'_blank' + * }' ); + * ``` + */ + /** + * 返回当前选中的第一个超链接节点 + * @command link + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { Element } 超链接节点 + * @example + * ```javascript + * editor.queryCommandValue( 'link' ); + * ``` + */ -/** - * 取消超链接 - * @command unlink - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'unlink'); - * ``` - */ + /** + * 取消超链接 + * @command unlink + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'unlink'); + * ``` + */ -UE.plugins["link"] = function() { - function optimize(range) { - var start = range.startContainer, - end = range.endContainer; + UE.plugins["link"] = function () { + function optimize(range) { + var start = range.startContainer, + end = range.endContainer; - if ((start = domUtils.findParentByTagName(start, "a", true))) { - range.setStartBefore(start); - } - if ((end = domUtils.findParentByTagName(end, "a", true))) { - range.setEndAfter(end); - } - } - - UE.commands["unlink"] = { - execCommand: function() { - var range = this.selection.getRange(), - bookmark; - if ( - range.collapsed && - !domUtils.findParentByTagName(range.startContainer, "a", true) - ) { - return; - } - bookmark = range.createBookmark(); - optimize(range); - range.removeInlineStyle("a").moveToBookmark(bookmark).select(); - }, - queryCommandState: function() { - return !this.highlight && this.queryCommandValue("link") ? 0 : -1; - } - }; - function doLink(range, opt, me) { - var rngClone = range.cloneRange(), - link = me.queryCommandValue("link"); - optimize((range = range.adjustmentBoundary())); - var start = range.startContainer; - if (start.nodeType == 1 && link) { - start = start.childNodes[range.startOffset]; - if ( - start && - start.nodeType == 1 && - start.tagName == "A" && - /^(?:https?|ftp|file)\s*:\s*\/\//.test( - start[browser.ie ? "innerText" : "textContent"] - ) - ) { - start[browser.ie ? "innerText" : "textContent"] = utils.html( - opt.textValue || opt.href - ); - } - } - if (!rngClone.collapsed || link) { - range.removeInlineStyle("a"); - rngClone = range.cloneRange(); - } - - if (rngClone.collapsed) { - var a = range.document.createElement("a"), - text = ""; - if (opt.textValue) { - text = utils.html(opt.textValue); - delete opt.textValue; - } else { - text = utils.html(opt.href); - } - domUtils.setAttributes(a, opt); - start = domUtils.findParentByTagName(rngClone.startContainer, "a", true); - if (start && domUtils.isInNodeEndBoundary(rngClone, start)) { - range.setStartAfter(start).collapse(true); - } - a[browser.ie ? "innerText" : "textContent"] = text; - range.insertNode(a).selectNode(a); - } else { - range.applyInlineStyle("a", opt); - } - } - UE.commands["link"] = { - execCommand: function(cmdName, opt) { - var range; - opt._href && (opt._href = utils.unhtml(opt._href, /[<">]/g)); - opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g)); - opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g)); - doLink((range = this.selection.getRange()), opt, this); - //闭合都不加占位符,如果加了会在a后边多个占位符节点,导致a是图片背景组成的列表,出现空白问题 - range.collapse().select(true); - }, - queryCommandValue: function() { - var range = this.selection.getRange(), - node; - if (range.collapsed) { - // node = this.selection.getStart(); - //在ie下getstart()取值偏上了 - node = range.startContainer; - node = node.nodeType == 1 ? node : node.parentNode; - - if ( - node && - (node = domUtils.findParentByTagName(node, "a", true)) && - !domUtils.isInNodeEndBoundary(range, node) - ) { - return node; - } - } else { - //trace:1111 如果是

    xx

    startContainer是p就会找不到a - range.shrinkBoundary(); - var start = range.startContainer.nodeType == 3 || - !range.startContainer.childNodes[range.startOffset] - ? range.startContainer - : range.startContainer.childNodes[range.startOffset], - end = range.endContainer.nodeType == 3 || range.endOffset == 0 - ? range.endContainer - : range.endContainer.childNodes[range.endOffset - 1], - common = range.getCommonAncestor(); - node = domUtils.findParentByTagName(common, "a", true); - if (!node && common.nodeType == 1) { - var as = common.getElementsByTagName("a"), - ps, - pe; - - for (var i = 0, ci; (ci = as[i++]); ) { - (ps = domUtils.getPosition(ci, start)), (pe = domUtils.getPosition( - ci, - end - )); - if ( - (ps & domUtils.POSITION_FOLLOWING || - ps & domUtils.POSITION_CONTAINS) && - (pe & domUtils.POSITION_PRECEDING || - pe & domUtils.POSITION_CONTAINS) - ) { - node = ci; - break; + if ((start = domUtils.findParentByTagName(start, "a", true))) { + range.setStartBefore(start); + } + if ((end = domUtils.findParentByTagName(end, "a", true))) { + range.setEndAfter(end); } - } } - return node; - } - }, - queryCommandState: function() { - //判断如果是视频的话连接不可用 - //fix 853 - var img = this.selection.getRange().getClosedNode(), - flag = - img && - (img.className == "edui-faked-video" || - img.className.indexOf("edui-upload-video") != -1); - return flag ? -1 : 0; - } - }; -}; + + UE.commands["unlink"] = { + execCommand: function () { + var range = this.selection.getRange(), + bookmark; + if ( + range.collapsed && + !domUtils.findParentByTagName(range.startContainer, "a", true) + ) { + return; + } + bookmark = range.createBookmark(); + optimize(range); + range.removeInlineStyle("a").moveToBookmark(bookmark).select(); + }, + queryCommandState: function () { + return !this.highlight && this.queryCommandValue("link") ? 0 : -1; + } + }; + + function doLink(range, opt, me) { + var rngClone = range.cloneRange(), + link = me.queryCommandValue("link"); + optimize((range = range.adjustmentBoundary())); + var start = range.startContainer; + if (start.nodeType == 1 && link) { + start = start.childNodes[range.startOffset]; + if ( + start && + start.nodeType == 1 && + start.tagName == "A" && + /^(?:https?|ftp|file)\s*:\s*\/\//.test( + start[browser.ie ? "innerText" : "textContent"] + ) + ) { + start[browser.ie ? "innerText" : "textContent"] = utils.html( + opt.textValue || opt.href + ); + } + } + if (!rngClone.collapsed || link) { + range.removeInlineStyle("a"); + rngClone = range.cloneRange(); + } + + if (rngClone.collapsed) { + var a = range.document.createElement("a"), + text = ""; + if (opt.textValue) { + text = utils.html(opt.textValue); + delete opt.textValue; + } else { + text = utils.html(opt.href); + } + domUtils.setAttributes(a, opt); + start = domUtils.findParentByTagName(rngClone.startContainer, "a", true); + if (start && domUtils.isInNodeEndBoundary(rngClone, start)) { + range.setStartAfter(start).collapse(true); + } + a[browser.ie ? "innerText" : "textContent"] = text; + range.insertNode(a).selectNode(a); + } else { + range.applyInlineStyle("a", opt); + } + } + + UE.commands["link"] = { + execCommand: function (cmdName, opt) { + var range; + opt._href && (opt._href = utils.unhtml(opt._href, /[<">]/g)); + opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g)); + opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g)); + doLink((range = this.selection.getRange()), opt, this); + //闭合都不加占位符,如果加了会在a后边多个占位符节点,导致a是图片背景组成的列表,出现空白问题 + range.collapse().select(true); + }, + queryCommandValue: function () { + var range = this.selection.getRange(), + node; + if (range.collapsed) { + // node = this.selection.getStart(); + //在ie下getstart()取值偏上了 + node = range.startContainer; + node = node.nodeType == 1 ? node : node.parentNode; + + if ( + node && + (node = domUtils.findParentByTagName(node, "a", true)) && + !domUtils.isInNodeEndBoundary(range, node) + ) { + return node; + } + } else { + //trace:1111 如果是

    xx

    startContainer是p就会找不到a + range.shrinkBoundary(); + var start = range.startContainer.nodeType == 3 || + !range.startContainer.childNodes[range.startOffset] + ? range.startContainer + : range.startContainer.childNodes[range.startOffset], + end = range.endContainer.nodeType == 3 || range.endOffset == 0 + ? range.endContainer + : range.endContainer.childNodes[range.endOffset - 1], + common = range.getCommonAncestor(); + node = domUtils.findParentByTagName(common, "a", true); + if (!node && common.nodeType == 1) { + var as = common.getElementsByTagName("a"), + ps, + pe; + + for (var i = 0, ci; (ci = as[i++]);) { + (ps = domUtils.getPosition(ci, start)), (pe = domUtils.getPosition( + ci, + end + )); + if ( + (ps & domUtils.POSITION_FOLLOWING || + ps & domUtils.POSITION_CONTAINS) && + (pe & domUtils.POSITION_PRECEDING || + pe & domUtils.POSITION_CONTAINS) + ) { + node = ci; + break; + } + } + } + return node; + } + }, + queryCommandState: function () { + //判断如果是视频的话连接不可用 + //fix 853 + var img = this.selection.getRange().getClosedNode(), + flag = + img && + (img.className == "edui-faked-video" || + img.className.indexOf("edui-upload-video") != -1); + return flag ? -1 : 0; + } + }; + }; // plugins/iframe.js @@ -13289,16 +16559,17 @@ UE.plugins["link"] = function() { ///commandsTitle 插入Iframe ///commandsDialog dialogs\insertframe -UE.plugins["insertframe"] = function() { - var me = this; - function deleteIframe() { - me._iframe && delete me._iframe; - } + UE.plugins["insertframe"] = function () { + var me = this; - me.addListener("selectionchange", function() { - deleteIframe(); - }); -}; + function deleteIframe() { + me._iframe && delete me._iframe; + } + + me.addListener("selectionchange", function () { + deleteIframe(); + }); + }; // plugins/scrawl.js @@ -13307,1995 +16578,1999 @@ UE.plugins["insertframe"] = function() { ///commandsName Scrawl ///commandsTitle 涂鸦 ///commandsDialog dialogs\scrawl -UE.commands["scrawl"] = { - queryCommandState: function() { - return browser.ie && browser.version <= 8 ? -1 : 0; - } -}; + UE.commands["scrawl"] = { + queryCommandState: function () { + return browser.ie && browser.version <= 8 ? -1 : 0; + } + }; // plugins/removeformat.js -/** - * 清除格式 - * @file - * @since 1.2.6.1 - */ + /** + * 清除格式 + * @file + * @since 1.2.6.1 + */ -/** - * 清除文字样式 - * @command removeformat - * @method execCommand - * @param { String } cmd 命令字符串 - * @param {String} tags 以逗号隔开的标签。如:strong - * @param {String} style 样式如:color - * @param {String} attrs 属性如:width - * @example - * ```javascript - * editor.execCommand( 'removeformat', 'strong','color','width' ); - * ``` - */ + /** + * 清除文字样式 + * @command removeformat + * @method execCommand + * @param { String } cmd 命令字符串 + * @param {String} tags 以逗号隔开的标签。如:strong + * @param {String} style 样式如:color + * @param {String} attrs 属性如:width + * @example + * ```javascript + * editor.execCommand( 'removeformat', 'strong','color','width' ); + * ``` + */ -UE.plugins["removeformat"] = function() { - var me = this; - me.setOpt({ - removeFormatTags: - "b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var", - removeFormatAttributes: "class,style,lang,width,height,align,hspace,valign" - }); - me.commands["removeformat"] = { - execCommand: function(cmdName, tags, style, attrs, notIncludeA) { - var tagReg = new RegExp( - "^(?:" + - (tags || this.options.removeFormatTags).replace(/,/g, "|") + - ")$", - "i" - ), - removeFormatAttributes = style - ? [] - : (attrs || this.options.removeFormatAttributes).split(","), - range = new dom.Range(this.document), - bookmark, - node, - parent, - filter = function(node) { - return node.nodeType == 1; + UE.plugins["removeformat"] = function () { + var me = this; + me.setOpt({ + removeFormatTags: + "b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var", + removeFormatAttributes: "class,style,lang,width,height,align,hspace,valign" + }); + me.commands["removeformat"] = { + execCommand: function (cmdName, tags, style, attrs, notIncludeA) { + var tagReg = new RegExp( + "^(?:" + + (tags || this.options.removeFormatTags).replace(/,/g, "|") + + ")$", + "i" + ), + removeFormatAttributes = style + ? [] + : (attrs || this.options.removeFormatAttributes).split(","), + range = new dom.Range(this.document), + bookmark, + node, + parent, + filter = function (node) { + return node.nodeType == 1; + }; + + function isRedundantSpan(node) { + if (node.nodeType == 3 || node.tagName.toLowerCase() != "span") { + return 0; + } + if (browser.ie) { + //ie 下判断实效,所以只能简单用style来判断 + //return node.style.cssText == '' ? 1 : 0; + var attrs = node.attributes; + if (attrs.length) { + for (var i = 0, l = attrs.length; i < l; i++) { + if (attrs[i].specified) { + return 0; + } + } + return 1; + } + } + return !node.attributes.length; + } + + function doRemove(range) { + var bookmark1 = range.createBookmark(); + if (range.collapsed) { + range.enlarge(true); + } + + //不能把a标签切了 + if (!notIncludeA) { + var aNode = domUtils.findParentByTagName( + range.startContainer, + "a", + true + ); + if (aNode) { + range.setStartBefore(aNode); + } + + aNode = domUtils.findParentByTagName(range.endContainer, "a", true); + if (aNode) { + range.setEndAfter(aNode); + } + } + + bookmark = range.createBookmark(); + + node = bookmark.start; + + //切开始 + while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) { + domUtils.breakParent(node, parent); + + domUtils.clearEmptySibling(node); + } + if (bookmark.end) { + //切结束 + node = bookmark.end; + while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) { + domUtils.breakParent(node, parent); + domUtils.clearEmptySibling(node); + } + + //开始去除样式 + var current = domUtils.getNextDomNode(bookmark.start, false, filter), + next; + while (current) { + if (current == bookmark.end) { + break; + } + + next = domUtils.getNextDomNode(current, true, filter); + + if ( + !dtd.$empty[current.tagName.toLowerCase()] && + !domUtils.isBookmarkNode(current) + ) { + if (tagReg.test(current.tagName)) { + if (style) { + domUtils.removeStyle(current, style); + if (isRedundantSpan(current) && style != "text-decoration") { + domUtils.remove(current, true); + } + } else { + domUtils.remove(current, true); + } + } else { + //trace:939 不能把list上的样式去掉 + // 清除格式时,默认移除Table、List上的样式 + if ( + true + // !dtd.$tableContent[current.tagName] && !dtd.$list[current.tagName] + ) { + domUtils.removeAttributes(current, removeFormatAttributes); + if (isRedundantSpan(current)) { + domUtils.remove(current, true); + } + } else { + // console.log('current.ignore',current); + } + } + } + current = next; + } + } + //trace:1035 + //trace:1096 不能把td上的样式去掉,比如边框 + var pN = bookmark.start.parentNode; + if ( + domUtils.isBlockElm(pN) && + !dtd.$tableContent[pN.tagName] && + !dtd.$list[pN.tagName] + ) { + domUtils.removeAttributes(pN, removeFormatAttributes); + } + pN = bookmark.end.parentNode; + if ( + bookmark.end && + domUtils.isBlockElm(pN) && + !dtd.$tableContent[pN.tagName] && + !dtd.$list[pN.tagName] + ) { + domUtils.removeAttributes(pN, removeFormatAttributes); + } + range.moveToBookmark(bookmark).moveToBookmark(bookmark1); + //清除冗余的代码 + var node = range.startContainer, + tmp, + collapsed = range.collapsed; + while ( + node.nodeType == 1 && + domUtils.isEmptyNode(node) && + dtd.$removeEmpty[node.tagName] + ) { + tmp = node.parentNode; + range.setStartBefore(node); + //trace:937 + //更新结束边界 + if (range.startContainer === range.endContainer) { + range.endOffset--; + } + domUtils.remove(node); + node = tmp; + } + + if (!collapsed) { + node = range.endContainer; + while ( + node.nodeType == 1 && + domUtils.isEmptyNode(node) && + dtd.$removeEmpty[node.tagName] + ) { + tmp = node.parentNode; + range.setEndBefore(node); + domUtils.remove(node); + + node = tmp; + } + } + } + + range = this.selection.getRange(); + doRemove(range); + range.select(); + } }; - - function isRedundantSpan(node) { - if (node.nodeType == 3 || node.tagName.toLowerCase() != "span") { - return 0; - } - if (browser.ie) { - //ie 下判断实效,所以只能简单用style来判断 - //return node.style.cssText == '' ? 1 : 0; - var attrs = node.attributes; - if (attrs.length) { - for (var i = 0, l = attrs.length; i < l; i++) { - if (attrs[i].specified) { - return 0; - } - } - return 1; - } - } - return !node.attributes.length; - } - function doRemove(range) { - var bookmark1 = range.createBookmark(); - if (range.collapsed) { - range.enlarge(true); - } - - //不能把a标签切了 - if (!notIncludeA) { - var aNode = domUtils.findParentByTagName( - range.startContainer, - "a", - true - ); - if (aNode) { - range.setStartBefore(aNode); - } - - aNode = domUtils.findParentByTagName(range.endContainer, "a", true); - if (aNode) { - range.setEndAfter(aNode); - } - } - - bookmark = range.createBookmark(); - - node = bookmark.start; - - //切开始 - while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) { - domUtils.breakParent(node, parent); - - domUtils.clearEmptySibling(node); - } - if (bookmark.end) { - //切结束 - node = bookmark.end; - while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) { - domUtils.breakParent(node, parent); - domUtils.clearEmptySibling(node); - } - - //开始去除样式 - var current = domUtils.getNextDomNode(bookmark.start, false, filter), - next; - while (current) { - if (current == bookmark.end) { - break; - } - - next = domUtils.getNextDomNode(current, true, filter); - - if ( - !dtd.$empty[current.tagName.toLowerCase()] && - !domUtils.isBookmarkNode(current) - ) { - if (tagReg.test(current.tagName)) { - if (style) { - domUtils.removeStyle(current, style); - if (isRedundantSpan(current) && style != "text-decoration") { - domUtils.remove(current, true); - } - } else { - domUtils.remove(current, true); - } - } else { - //trace:939 不能把list上的样式去掉 - // 清除格式时,默认移除Table、List上的样式 - if ( - true - // !dtd.$tableContent[current.tagName] && !dtd.$list[current.tagName] - ) { - domUtils.removeAttributes(current, removeFormatAttributes); - if (isRedundantSpan(current)) { - domUtils.remove(current, true); - } - }else{ - // console.log('current.ignore',current); - } - } - } - current = next; - } - } - //trace:1035 - //trace:1096 不能把td上的样式去掉,比如边框 - var pN = bookmark.start.parentNode; - if ( - domUtils.isBlockElm(pN) && - !dtd.$tableContent[pN.tagName] && - !dtd.$list[pN.tagName] - ) { - domUtils.removeAttributes(pN, removeFormatAttributes); - } - pN = bookmark.end.parentNode; - if ( - bookmark.end && - domUtils.isBlockElm(pN) && - !dtd.$tableContent[pN.tagName] && - !dtd.$list[pN.tagName] - ) { - domUtils.removeAttributes(pN, removeFormatAttributes); - } - range.moveToBookmark(bookmark).moveToBookmark(bookmark1); - //清除冗余的代码 - var node = range.startContainer, - tmp, - collapsed = range.collapsed; - while ( - node.nodeType == 1 && - domUtils.isEmptyNode(node) && - dtd.$removeEmpty[node.tagName] - ) { - tmp = node.parentNode; - range.setStartBefore(node); - //trace:937 - //更新结束边界 - if (range.startContainer === range.endContainer) { - range.endOffset--; - } - domUtils.remove(node); - node = tmp; - } - - if (!collapsed) { - node = range.endContainer; - while ( - node.nodeType == 1 && - domUtils.isEmptyNode(node) && - dtd.$removeEmpty[node.tagName] - ) { - tmp = node.parentNode; - range.setEndBefore(node); - domUtils.remove(node); - - node = tmp; - } - } - } - - range = this.selection.getRange(); - doRemove(range); - range.select(); - } - }; -}; + }; // plugins/blockquote.js -/** - * 添加引用 - * @file - * @since 1.2.6.1 - */ + /** + * 添加引用 + * @file + * @since 1.2.6.1 + */ -/** - * 添加引用 - * @command blockquote - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'blockquote' ); - * ``` - */ + /** + * 添加引用 + * @command blockquote + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'blockquote' ); + * ``` + */ -/** - * 添加引用 - * @command blockquote - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { Object } attrs 节点属性 - * @example - * ```javascript - * editor.execCommand( 'blockquote',{ - * style: "color: red;" - * } ); - * ``` - */ + /** + * 添加引用 + * @command blockquote + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { Object } attrs 节点属性 + * @example + * ```javascript + * editor.execCommand( 'blockquote',{ + * style: "color: red;" + * } ); + * ``` + */ -UE.plugins["blockquote"] = function() { - var me = this; - function getObj(editor) { - return domUtils.filterNodeList( - editor.selection.getStartElementPath(), - "blockquote" - ); - } - me.commands["blockquote"] = { - execCommand: function(cmdName, attrs) { - var range = this.selection.getRange(), - obj = getObj(this), - blockquote = dtd.blockquote, - bookmark = range.createBookmark(); + UE.plugins["blockquote"] = function () { + var me = this; - if (obj) { - var start = range.startContainer, - startBlock = domUtils.isBlockElm(start) - ? start - : domUtils.findParent(start, function(node) { - return domUtils.isBlockElm(node); - }), - end = range.endContainer, - endBlock = domUtils.isBlockElm(end) - ? end - : domUtils.findParent(end, function(node) { - return domUtils.isBlockElm(node); - }); - - //处理一下li - startBlock = - domUtils.findParentByTagName(startBlock, "li", true) || startBlock; - endBlock = - domUtils.findParentByTagName(endBlock, "li", true) || endBlock; - - if ( - startBlock.tagName == "LI" || - startBlock.tagName == "TD" || - startBlock === obj || - domUtils.isBody(startBlock) - ) { - domUtils.remove(obj, true); - } else { - domUtils.breakParent(startBlock, obj); + function getObj(editor) { + return domUtils.filterNodeList( + editor.selection.getStartElementPath(), + "blockquote" + ); } - if (startBlock !== endBlock) { - obj = domUtils.findParentByTagName(endBlock, "blockquote"); - if (obj) { - if ( - endBlock.tagName == "LI" || - endBlock.tagName == "TD" || - domUtils.isBody(endBlock) - ) { - obj.parentNode && domUtils.remove(obj, true); - } else { - domUtils.breakParent(endBlock, obj); + me.commands["blockquote"] = { + execCommand: function (cmdName, attrs) { + var range = this.selection.getRange(), + obj = getObj(this), + blockquote = dtd.blockquote, + bookmark = range.createBookmark(); + + if (obj) { + var start = range.startContainer, + startBlock = domUtils.isBlockElm(start) + ? start + : domUtils.findParent(start, function (node) { + return domUtils.isBlockElm(node); + }), + end = range.endContainer, + endBlock = domUtils.isBlockElm(end) + ? end + : domUtils.findParent(end, function (node) { + return domUtils.isBlockElm(node); + }); + + //处理一下li + startBlock = + domUtils.findParentByTagName(startBlock, "li", true) || startBlock; + endBlock = + domUtils.findParentByTagName(endBlock, "li", true) || endBlock; + + if ( + startBlock.tagName == "LI" || + startBlock.tagName == "TD" || + startBlock === obj || + domUtils.isBody(startBlock) + ) { + domUtils.remove(obj, true); + } else { + domUtils.breakParent(startBlock, obj); + } + + if (startBlock !== endBlock) { + obj = domUtils.findParentByTagName(endBlock, "blockquote"); + if (obj) { + if ( + endBlock.tagName == "LI" || + endBlock.tagName == "TD" || + domUtils.isBody(endBlock) + ) { + obj.parentNode && domUtils.remove(obj, true); + } else { + domUtils.breakParent(endBlock, obj); + } + } + } + + var blockquotes = domUtils.getElementsByTagName( + this.document, + "blockquote" + ); + for (var i = 0, bi; (bi = blockquotes[i++]);) { + if (!bi.childNodes.length) { + domUtils.remove(bi); + } else if ( + domUtils.getPosition(bi, startBlock) & + domUtils.POSITION_FOLLOWING && + domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING + ) { + domUtils.remove(bi, true); + } + } + } else { + var tmpRange = range.cloneRange(), + node = tmpRange.startContainer.nodeType == 1 + ? tmpRange.startContainer + : tmpRange.startContainer.parentNode, + preNode = node, + doEnd = 1; + + //调整开始 + while (1) { + if (domUtils.isBody(node)) { + if (preNode !== node) { + if (range.collapsed) { + tmpRange.selectNode(preNode); + doEnd = 0; + } else { + tmpRange.setStartBefore(preNode); + } + } else { + tmpRange.setStart(node, 0); + } + + break; + } + if (!blockquote[node.tagName]) { + if (range.collapsed) { + tmpRange.selectNode(preNode); + } else { + tmpRange.setStartBefore(preNode); + } + break; + } + + preNode = node; + node = node.parentNode; + } + + //调整结束 + if (doEnd) { + preNode = node = node = tmpRange.endContainer.nodeType == 1 + ? tmpRange.endContainer + : tmpRange.endContainer.parentNode; + while (1) { + if (domUtils.isBody(node)) { + if (preNode !== node) { + tmpRange.setEndAfter(preNode); + } else { + tmpRange.setEnd(node, node.childNodes.length); + } + + break; + } + if (!blockquote[node.tagName]) { + tmpRange.setEndAfter(preNode); + break; + } + + preNode = node; + node = node.parentNode; + } + } + + node = range.document.createElement("blockquote"); + domUtils.setAttributes(node, attrs); + node.appendChild(tmpRange.extractContents()); + tmpRange.insertNode(node); + //去除重复的 + var childs = domUtils.getElementsByTagName(node, "blockquote"); + for (var i = 0, ci; (ci = childs[i++]);) { + if (ci.parentNode) { + domUtils.remove(ci, true); + } + } + } + range.moveToBookmark(bookmark).select(); + }, + queryCommandState: function () { + return getObj(this) ? 1 : 0; } - } - } - - var blockquotes = domUtils.getElementsByTagName( - this.document, - "blockquote" - ); - for (var i = 0, bi; (bi = blockquotes[i++]); ) { - if (!bi.childNodes.length) { - domUtils.remove(bi); - } else if ( - domUtils.getPosition(bi, startBlock) & - domUtils.POSITION_FOLLOWING && - domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING - ) { - domUtils.remove(bi, true); - } - } - } else { - var tmpRange = range.cloneRange(), - node = tmpRange.startContainer.nodeType == 1 - ? tmpRange.startContainer - : tmpRange.startContainer.parentNode, - preNode = node, - doEnd = 1; - - //调整开始 - while (1) { - if (domUtils.isBody(node)) { - if (preNode !== node) { - if (range.collapsed) { - tmpRange.selectNode(preNode); - doEnd = 0; - } else { - tmpRange.setStartBefore(preNode); - } - } else { - tmpRange.setStart(node, 0); - } - - break; - } - if (!blockquote[node.tagName]) { - if (range.collapsed) { - tmpRange.selectNode(preNode); - } else { - tmpRange.setStartBefore(preNode); - } - break; - } - - preNode = node; - node = node.parentNode; - } - - //调整结束 - if (doEnd) { - preNode = node = node = tmpRange.endContainer.nodeType == 1 - ? tmpRange.endContainer - : tmpRange.endContainer.parentNode; - while (1) { - if (domUtils.isBody(node)) { - if (preNode !== node) { - tmpRange.setEndAfter(preNode); - } else { - tmpRange.setEnd(node, node.childNodes.length); - } - - break; - } - if (!blockquote[node.tagName]) { - tmpRange.setEndAfter(preNode); - break; - } - - preNode = node; - node = node.parentNode; - } - } - - node = range.document.createElement("blockquote"); - domUtils.setAttributes(node, attrs); - node.appendChild(tmpRange.extractContents()); - tmpRange.insertNode(node); - //去除重复的 - var childs = domUtils.getElementsByTagName(node, "blockquote"); - for (var i = 0, ci; (ci = childs[i++]); ) { - if (ci.parentNode) { - domUtils.remove(ci, true); - } - } - } - range.moveToBookmark(bookmark).select(); - }, - queryCommandState: function() { - return getObj(this) ? 1 : 0; - } - }; -}; + }; + }; // plugins/convertcase.js -/** - * 大小写转换 - * @file - * @since 1.2.6.1 - */ + /** + * 大小写转换 + * @file + * @since 1.2.6.1 + */ -/** - * 把选区内文本变大写,与“tolowercase”命令互斥 - * @command touppercase - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'touppercase' ); - * ``` - */ + /** + * 把选区内文本变大写,与“tolowercase”命令互斥 + * @command touppercase + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'touppercase' ); + * ``` + */ -/** - * 把选区内文本变小写,与“touppercase”命令互斥 - * @command tolowercase - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'tolowercase' ); - * ``` - */ -UE.commands["touppercase"] = UE.commands["tolowercase"] = { - execCommand: function(cmd) { - var me = this; - var rng = me.selection.getRange(); - if (rng.collapsed) { - return rng; - } - var bk = rng.createBookmark(), - bkEnd = bk.end, - filterFn = function(node) { - return !domUtils.isBr(node) && !domUtils.isWhitespace(node); - }, - curNode = domUtils.getNextDomNode(bk.start, false, filterFn); - while ( - curNode && - domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING - ) { - if (curNode.nodeType == 3) { - curNode.nodeValue = curNode.nodeValue[ - cmd == "touppercase" ? "toUpperCase" : "toLowerCase" - ](); - } - curNode = domUtils.getNextDomNode(curNode, true, filterFn); - if (curNode === bkEnd) { - break; - } - } - rng.moveToBookmark(bk).select(); - } -}; + /** + * 把选区内文本变小写,与“touppercase”命令互斥 + * @command tolowercase + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'tolowercase' ); + * ``` + */ + UE.commands["touppercase"] = UE.commands["tolowercase"] = { + execCommand: function (cmd) { + var me = this; + var rng = me.selection.getRange(); + if (rng.collapsed) { + return rng; + } + var bk = rng.createBookmark(), + bkEnd = bk.end, + filterFn = function (node) { + return !domUtils.isBr(node) && !domUtils.isWhitespace(node); + }, + curNode = domUtils.getNextDomNode(bk.start, false, filterFn); + while ( + curNode && + domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING + ) { + if (curNode.nodeType == 3) { + curNode.nodeValue = curNode.nodeValue[ + cmd == "touppercase" ? "toUpperCase" : "toLowerCase" + ](); + } + curNode = domUtils.getNextDomNode(curNode, true, filterFn); + if (curNode === bkEnd) { + break; + } + } + rng.moveToBookmark(bk).select(); + } + }; // plugins/indent.js -/** - * 首行缩进 - * @file - * @since 1.2.6.1 - */ + /** + * 首行缩进 + * @file + * @since 1.2.6.1 + */ -/** - * 缩进 - * @command indent - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'indent' ); - * ``` - */ -UE.commands["indent"] = { - execCommand: function() { - var me = this, - value = me.queryCommandState("indent") - ? "0em" - : me.options.indentValue || "2em"; - me.execCommand("Paragraph", "p", { style: "text-indent:" + value }); - }, - queryCommandState: function() { - var pN = domUtils.filterNodeList( - this.selection.getStartElementPath(), - "p h1 h2 h3 h4 h5 h6" - ); - return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0; - } -}; + /** + * 缩进 + * @command indent + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'indent' ); + * ``` + */ + UE.commands["indent"] = { + execCommand: function () { + var me = this, + value = me.queryCommandState("indent") + ? "0em" + : me.options.indentValue || "2em"; + me.execCommand("Paragraph", "p", {style: "text-indent:" + value}); + }, + queryCommandState: function () { + var pN = domUtils.filterNodeList( + this.selection.getStartElementPath(), + "p h1 h2 h3 h4 h5 h6" + ); + return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0; + } + }; // plugins/print.js -/** - * 打印 - * @file - * @since 1.2.6.1 - */ + /** + * 打印 + * @file + * @since 1.2.6.1 + */ -/** - * 打印 - * @command print - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'print' ); - * ``` - */ -UE.commands["print"] = { - execCommand: function() { - this.window.print(); - }, - notNeedUndo: 1 -}; + /** + * 打印 + * @command print + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'print' ); + * ``` + */ + UE.commands["print"] = { + execCommand: function () { + this.window.print(); + }, + notNeedUndo: 1 + }; // plugins/preview.js -/** - * 预览 - * @file - * @since 1.2.6.1 - */ + /** + * 预览 + * @file + * @since 1.2.6.1 + */ -/** - * 预览 - * @command preview - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'preview' ); - * ``` - */ -UE.commands["preview"] = { - execCommand: function() { - var w = window.open("", "_blank", ""), - d = w.document; - d.open(); - d.write( - '
    " + - this.getContent(null, null, true) + - "
    " - ); - d.close(); - }, - notNeedUndo: 1 -}; + /** + * 预览 + * @command preview + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'preview' ); + * ``` + */ + UE.commands["preview"] = { + execCommand: function () { + var w = window.open("", "_blank", ""), + d = w.document; + d.open(); + d.write( + '
    " + + this.getContent(null, null, true) + + "
    " + ); + d.close(); + }, + notNeedUndo: 1 + }; // plugins/selectall.js -/** - * 全选 - * @file - * @since 1.2.6.1 - */ + /** + * 全选 + * @file + * @since 1.2.6.1 + */ -/** - * 选中所有内容 - * @command selectall - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'selectall' ); - * ``` - */ -UE.plugins["selectall"] = function() { - var me = this; - me.commands["selectall"] = { - execCommand: function() { - //去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标 - var me = this, - body = me.body, - range = me.selection.getRange(); - range.selectNodeContents(body); - if (domUtils.isEmptyBlock(body)) { - //opera不能自动合并到元素的里边,要手动处理一下 - if (browser.opera && body.firstChild && body.firstChild.nodeType == 1) { - range.setStartAtFirst(body.firstChild); - } - range.collapse(true); - } - range.select(true); - }, - notNeedUndo: 1 - }; + /** + * 选中所有内容 + * @command selectall + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'selectall' ); + * ``` + */ + UE.plugins["selectall"] = function () { + var me = this; + me.commands["selectall"] = { + execCommand: function () { + //去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标 + var me = this, + body = me.body, + range = me.selection.getRange(); + range.selectNodeContents(body); + if (domUtils.isEmptyBlock(body)) { + //opera不能自动合并到元素的里边,要手动处理一下 + if (browser.opera && body.firstChild && body.firstChild.nodeType == 1) { + range.setStartAtFirst(body.firstChild); + } + range.collapse(true); + } + range.select(true); + }, + notNeedUndo: 1 + }; - //快捷键 - me.addshortcutkey({ - selectAll: "ctrl+65" - }); -}; + //快捷键 + me.addshortcutkey({ + selectAll: "ctrl+65" + }); + }; // plugins/paragraph.js -/** - * 段落样式 - * @file - * @since 1.2.6.1 - */ + /** + * 段落样式 + * @file + * @since 1.2.6.1 + */ -/** - * 段落格式 - * @command paragraph - * @method execCommand - * @param { String } cmd 命令字符串 - * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' - * @param {Object} attrs 标签的属性 - * @example - * ```javascript - * editor.execCommand( 'Paragraph','h1','{ - * class:'test' - * }' ); - * ``` - */ + /** + * 段落格式 + * @command paragraph + * @method execCommand + * @param { String } cmd 命令字符串 + * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' + * @param {Object} attrs 标签的属性 + * @example + * ```javascript + * editor.execCommand( 'Paragraph','h1','{ + * class:'test' + * }' ); + * ``` + */ -/** - * 返回选区内节点标签名 - * @command paragraph - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 节点标签名 - * @example - * ```javascript - * editor.queryCommandValue( 'Paragraph' ); - * ``` - */ + /** + * 返回选区内节点标签名 + * @command paragraph + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 节点标签名 + * @example + * ```javascript + * editor.queryCommandValue( 'Paragraph' ); + * ``` + */ -UE.plugins["paragraph"] = function() { - var me = this, - block = domUtils.isBlockElm, - notExchange = ["TD", "LI", "PRE"], - doParagraph = function(range, style, attrs, sourceCmdName) { - var bookmark = range.createBookmark(), - filterFn = function(node) { - return node.nodeType == 1 - ? node.tagName.toLowerCase() != "br" && - !domUtils.isBookmarkNode(node) - : !domUtils.isWhitespace(node); - }, - para; + UE.plugins["paragraph"] = function () { + var me = this, + block = domUtils.isBlockElm, + notExchange = ["TD", "LI", "PRE"], + doParagraph = function (range, style, attrs, sourceCmdName) { + var bookmark = range.createBookmark(), + filterFn = function (node) { + return node.nodeType == 1 + ? node.tagName.toLowerCase() != "br" && + !domUtils.isBookmarkNode(node) + : !domUtils.isWhitespace(node); + }, + para; - range.enlarge(true); - var bookmark2 = range.createBookmark(), - current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), - tmpRange = range.cloneRange(), - tmpNode; - while ( - current && - !( - domUtils.getPosition(current, bookmark2.end) & - domUtils.POSITION_FOLLOWING - ) - ) { - if (current.nodeType === 3 || !block(current)) { - tmpRange.setStartBefore(current); - while (current && current !== bookmark2.end && !block(current)) { - tmpNode = current; - current = domUtils.getNextDomNode(current, false, null, function( - node - ) { - return !block(node); - }); - } - tmpRange.setEndAfter(tmpNode); + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode; + while ( + current && + !( + domUtils.getPosition(current, bookmark2.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + if (current.nodeType === 3 || !block(current)) { + tmpRange.setStartBefore(current); + while (current && current !== bookmark2.end && !block(current)) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function ( + node + ) { + return !block(node); + }); + } + tmpRange.setEndAfter(tmpNode); - para = range.document.createElement(style); - if (attrs) { - domUtils.setAttributes(para, attrs); - if ( - sourceCmdName && - sourceCmdName === "customstyle" && - attrs.style - ) { - para.style.cssText = attrs.style; + para = range.document.createElement(style); + if (attrs) { + domUtils.setAttributes(para, attrs); + if ( + sourceCmdName && + sourceCmdName === "customstyle" && + attrs.style + ) { + para.style.cssText = attrs.style; + } + } + para.appendChild(tmpRange.extractContents()); + //需要内容占位 + if (domUtils.isEmptyNode(para)) { + domUtils.fillChar(range.document, para); + } + + tmpRange.insertNode(para); + + var parent = para.parentNode; + //如果para上一级是一个block元素且不是body,td就删除它 + if ( + block(parent) && + !domUtils.isBody(para.parentNode) && + utils.indexOf(notExchange, parent.tagName) === -1 + ) { + //存储dir,style + if (!(sourceCmdName && sourceCmdName === "customstyle")) { + parent.getAttribute("dir") && + para.setAttribute("dir", parent.getAttribute("dir")); + //trace:1070 + parent.style.cssText && + (para.style.cssText = + parent.style.cssText + ";" + para.style.cssText); + //trace:1030 + parent.style.textAlign && + !para.style.textAlign && + (para.style.textAlign = parent.style.textAlign); + parent.style.textIndent && + !para.style.textIndent && + (para.style.textIndent = parent.style.textIndent); + parent.style.padding && + !para.style.padding && + (para.style.padding = parent.style.padding); + } + + //trace:1706 选择的就是h1-6要删除 + if ( + attrs && + /h\d/i.test(parent.tagName) && + !/h\d/i.test(para.tagName) + ) { + domUtils.setAttributes(parent, attrs); + if ( + sourceCmdName && + sourceCmdName === "customstyle" && + attrs.style + ) { + parent.style.cssText = attrs.style; + } + domUtils.remove(para.parentNode, true); + para = parent; + } else { + domUtils.remove(para.parentNode, true); + } + } + if (utils.indexOf(notExchange, parent.tagName) !== -1) { + current = parent; + } else { + current = para; + } + + current = domUtils.getNextDomNode(current, false, filterFn); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); + }; + me.setOpt("paragraph", { + p: "", + h1: "", + h2: "", + h3: "", + h4: "", + h5: "", + h6: "" + }); + me.commands["paragraph"] = { + execCommand: function (cmdName, style, attrs, sourceCmdName) { + var range = this.selection.getRange(); + //闭合时单独处理 + if (range.collapsed) { + var txt = this.document.createTextNode("p"); + range.insertNode(txt); + //去掉冗余的fillchar + if (browser.ie) { + var node = txt.previousSibling; + if (node && domUtils.isWhitespace(node)) { + domUtils.remove(node); + } + node = txt.nextSibling; + if (node && domUtils.isWhitespace(node)) { + domUtils.remove(node); + } + } + } + range = doParagraph(range, style, attrs, sourceCmdName); + if (txt) { + range.setStartBefore(txt).collapse(true); + pN = txt.parentNode; + + domUtils.remove(txt); + + if (domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN)) { + domUtils.fillNode(this.document, pN); + } + } + + if ( + browser.gecko && + range.collapsed && + range.startContainer.nodeType === 1 + ) { + var child = range.startContainer.childNodes[range.startOffset]; + if ( + child && + child.nodeType === 1 && + child.tagName.toLowerCase() === style + ) { + range.setStart(child, 0).collapse(true); + } + } + //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了 + range.select(); + + return true; + }, + queryCommandValue: function () { + var node = domUtils.filterNodeList( + this.selection.getStartElementPath(), + "p h1 h2 h3 h4 h5 h6" + ); + return node ? node.tagName.toLowerCase() : ""; } - } - para.appendChild(tmpRange.extractContents()); - //需要内容占位 - if (domUtils.isEmptyNode(para)) { - domUtils.fillChar(range.document, para); - } - - tmpRange.insertNode(para); - - var parent = para.parentNode; - //如果para上一级是一个block元素且不是body,td就删除它 - if ( - block(parent) && - !domUtils.isBody(para.parentNode) && - utils.indexOf(notExchange, parent.tagName) === -1 - ) { - //存储dir,style - if (!(sourceCmdName && sourceCmdName === "customstyle")) { - parent.getAttribute("dir") && - para.setAttribute("dir", parent.getAttribute("dir")); - //trace:1070 - parent.style.cssText && - (para.style.cssText = - parent.style.cssText + ";" + para.style.cssText); - //trace:1030 - parent.style.textAlign && - !para.style.textAlign && - (para.style.textAlign = parent.style.textAlign); - parent.style.textIndent && - !para.style.textIndent && - (para.style.textIndent = parent.style.textIndent); - parent.style.padding && - !para.style.padding && - (para.style.padding = parent.style.padding); - } - - //trace:1706 选择的就是h1-6要删除 - if ( - attrs && - /h\d/i.test(parent.tagName) && - !/h\d/i.test(para.tagName) - ) { - domUtils.setAttributes(parent, attrs); - if ( - sourceCmdName && - sourceCmdName === "customstyle" && - attrs.style - ) { - parent.style.cssText = attrs.style; - } - domUtils.remove(para.parentNode, true); - para = parent; - } else { - domUtils.remove(para.parentNode, true); - } - } - if (utils.indexOf(notExchange, parent.tagName) !== -1) { - current = parent; - } else { - current = para; - } - - current = domUtils.getNextDomNode(current, false, filterFn); - } else { - current = domUtils.getNextDomNode(current, true, filterFn); - } - } - return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); + }; }; - me.setOpt("paragraph", { - p: "", - h1: "", - h2: "", - h3: "", - h4: "", - h5: "", - h6: "" - }); - me.commands["paragraph"] = { - execCommand: function(cmdName, style, attrs, sourceCmdName) { - var range = this.selection.getRange(); - //闭合时单独处理 - if (range.collapsed) { - var txt = this.document.createTextNode("p"); - range.insertNode(txt); - //去掉冗余的fillchar - if (browser.ie) { - var node = txt.previousSibling; - if (node && domUtils.isWhitespace(node)) { - domUtils.remove(node); - } - node = txt.nextSibling; - if (node && domUtils.isWhitespace(node)) { - domUtils.remove(node); - } - } - } - range = doParagraph(range, style, attrs, sourceCmdName); - if (txt) { - range.setStartBefore(txt).collapse(true); - pN = txt.parentNode; - - domUtils.remove(txt); - - if (domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN)) { - domUtils.fillNode(this.document, pN); - } - } - - if ( - browser.gecko && - range.collapsed && - range.startContainer.nodeType === 1 - ) { - var child = range.startContainer.childNodes[range.startOffset]; - if ( - child && - child.nodeType === 1 && - child.tagName.toLowerCase() === style - ) { - range.setStart(child, 0).collapse(true); - } - } - //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了 - range.select(); - - return true; - }, - queryCommandValue: function() { - var node = domUtils.filterNodeList( - this.selection.getStartElementPath(), - "p h1 h2 h3 h4 h5 h6" - ); - return node ? node.tagName.toLowerCase() : ""; - } - }; -}; // plugins/directionality.js -/** - * 设置文字输入的方向的插件 - * @file - * @since 1.2.6.1 - */ -(function() { - var block = domUtils.isBlockElm, - getObj = function(editor) { - // var startNode = editor.selection.getStart(), - // parents; - // if ( startNode ) { - // //查找所有的是block的父亲节点 - // parents = domUtils.findParents( startNode, true, block, true ); - // for ( var i = 0,ci; ci = parents[i++]; ) { - // if ( ci.getAttribute( 'dir' ) ) { - // return ci; - // } - // } - // } - return domUtils.filterNodeList( - editor.selection.getStartElementPath(), - function(n) { - return n && n.nodeType == 1 && n.getAttribute("dir"); - } - ); - }, - doDirectionality = function(range, editor, forward) { - var bookmark, - filterFn = function(node) { - return node.nodeType == 1 - ? !domUtils.isBookmarkNode(node) - : !domUtils.isWhitespace(node); - }, - obj = getObj(editor); - - if (obj && range.collapsed) { - obj.setAttribute("dir", forward); - return range; - } - bookmark = range.createBookmark(); - range.enlarge(true); - var bookmark2 = range.createBookmark(), - current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), - tmpRange = range.cloneRange(), - tmpNode; - while ( - current && - !( - domUtils.getPosition(current, bookmark2.end) & - domUtils.POSITION_FOLLOWING - ) - ) { - if (current.nodeType == 3 || !block(current)) { - tmpRange.setStartBefore(current); - while (current && current !== bookmark2.end && !block(current)) { - tmpNode = current; - current = domUtils.getNextDomNode(current, false, null, function( - node - ) { - return !block(node); - }); - } - tmpRange.setEndAfter(tmpNode); - var common = tmpRange.getCommonAncestor(); - if (!domUtils.isBody(common) && block(common)) { - //遍历到了block节点 - common.setAttribute("dir", forward); - current = common; - } else { - //没有遍历到,添加一个block节点 - var p = range.document.createElement("p"); - p.setAttribute("dir", forward); - var frag = tmpRange.extractContents(); - p.appendChild(frag); - tmpRange.insertNode(p); - current = p; - } - - current = domUtils.getNextDomNode(current, false, filterFn); - } else { - current = domUtils.getNextDomNode(current, true, filterFn); - } - } - return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); - }; - - /** - * 文字输入方向 - * @command directionality - * @method execCommand - * @param { String } cmdName 命令字符串 - * @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入 - * @example - * ```javascript - * editor.execCommand( 'directionality', 'ltr'); - * ``` + /** + * 设置文字输入的方向的插件 + * @file + * @since 1.2.6.1 */ + (function () { + var block = domUtils.isBlockElm, + getObj = function (editor) { + // var startNode = editor.selection.getStart(), + // parents; + // if ( startNode ) { + // //查找所有的是block的父亲节点 + // parents = domUtils.findParents( startNode, true, block, true ); + // for ( var i = 0,ci; ci = parents[i++]; ) { + // if ( ci.getAttribute( 'dir' ) ) { + // return ci; + // } + // } + // } + return domUtils.filterNodeList( + editor.selection.getStartElementPath(), + function (n) { + return n && n.nodeType == 1 && n.getAttribute("dir"); + } + ); + }, + doDirectionality = function (range, editor, forward) { + var bookmark, + filterFn = function (node) { + return node.nodeType == 1 + ? !domUtils.isBookmarkNode(node) + : !domUtils.isWhitespace(node); + }, + obj = getObj(editor); - /** - * 查询当前选区的文字输入方向 - * @command directionality - * @method queryCommandValue - * @param { String } cmdName 命令字符串 - * @return { String } 返回'ltr'表示从左向右输入,返回'rtl'表示从右向左输入 - * @example - * ```javascript - * editor.queryCommandValue( 'directionality'); - * ``` - */ - UE.commands["directionality"] = { - execCommand: function(cmdName, forward) { - var range = this.selection.getRange(); - //闭合时单独处理 - if (range.collapsed) { - var txt = this.document.createTextNode("d"); - range.insertNode(txt); - } - doDirectionality(range, this, forward); - if (txt) { - range.setStartBefore(txt).collapse(true); - domUtils.remove(txt); - } + if (obj && range.collapsed) { + obj.setAttribute("dir", forward); + return range; + } + bookmark = range.createBookmark(); + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode; + while ( + current && + !( + domUtils.getPosition(current, bookmark2.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + if (current.nodeType == 3 || !block(current)) { + tmpRange.setStartBefore(current); + while (current && current !== bookmark2.end && !block(current)) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function ( + node + ) { + return !block(node); + }); + } + tmpRange.setEndAfter(tmpNode); + var common = tmpRange.getCommonAncestor(); + if (!domUtils.isBody(common) && block(common)) { + //遍历到了block节点 + common.setAttribute("dir", forward); + current = common; + } else { + //没有遍历到,添加一个block节点 + var p = range.document.createElement("p"); + p.setAttribute("dir", forward); + var frag = tmpRange.extractContents(); + p.appendChild(frag); + tmpRange.insertNode(p); + current = p; + } - range.select(); - return true; - }, - queryCommandValue: function() { - var node = getObj(this); - return node ? node.getAttribute("dir") : "ltr"; - } - }; -})(); + current = domUtils.getNextDomNode(current, false, filterFn); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); + }; + + /** + * 文字输入方向 + * @command directionality + * @method execCommand + * @param { String } cmdName 命令字符串 + * @param { String } forward 传入'ltr'表示从左向右输入,传入'rtl'表示从右向左输入 + * @example + * ```javascript + * editor.execCommand( 'directionality', 'ltr'); + * ``` + */ + + /** + * 查询当前选区的文字输入方向 + * @command directionality + * @method queryCommandValue + * @param { String } cmdName 命令字符串 + * @return { String } 返回'ltr'表示从左向右输入,返回'rtl'表示从右向左输入 + * @example + * ```javascript + * editor.queryCommandValue( 'directionality'); + * ``` + */ + UE.commands["directionality"] = { + execCommand: function (cmdName, forward) { + var range = this.selection.getRange(); + //闭合时单独处理 + if (range.collapsed) { + var txt = this.document.createTextNode("d"); + range.insertNode(txt); + } + doDirectionality(range, this, forward); + if (txt) { + range.setStartBefore(txt).collapse(true); + domUtils.remove(txt); + } + + range.select(); + return true; + }, + queryCommandValue: function () { + var node = getObj(this); + return node ? node.getAttribute("dir") : "ltr"; + } + }; + })(); // plugins/horizontal.js -/** - * 插入分割线插件 - * @file - * @since 1.2.6.1 - */ + /** + * 插入分割线插件 + * @file + * @since 1.2.6.1 + */ -/** - * 插入分割线 - * @command horizontal - * @method execCommand - * @param { String } cmdName 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'horizontal' ); - * ``` - */ -UE.plugins["horizontal"] = function() { - var me = this; - me.commands["horizontal"] = { - execCommand: function(cmdName) { - var me = this; - if (me.queryCommandState(cmdName) !== -1) { - me.execCommand("insertHtml", "
    "); - var range = me.selection.getRange(), - start = range.startContainer; - if (start.nodeType == 1 && !start.childNodes[range.startOffset]) { - var tmp; - if ((tmp = start.childNodes[range.startOffset - 1])) { - if (tmp.nodeType == 1 && tmp.tagName == "HR") { - if (me.options.enterTag == "p") { - tmp = me.document.createElement("p"); - range.insertNode(tmp); - range.setStart(tmp, 0).setCursor(); - } else { - tmp = me.document.createElement("br"); - range.insertNode(tmp); - range.setStartBefore(tmp).setCursor(); - } + /** + * 插入分割线 + * @command horizontal + * @method execCommand + * @param { String } cmdName 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'horizontal' ); + * ``` + */ + UE.plugins["horizontal"] = function () { + var me = this; + me.commands["horizontal"] = { + execCommand: function (cmdName) { + var me = this; + if (me.queryCommandState(cmdName) !== -1) { + me.execCommand("insertHtml", "
    "); + var range = me.selection.getRange(), + start = range.startContainer; + if (start.nodeType == 1 && !start.childNodes[range.startOffset]) { + var tmp; + if ((tmp = start.childNodes[range.startOffset - 1])) { + if (tmp.nodeType == 1 && tmp.tagName == "HR") { + if (me.options.enterTag == "p") { + tmp = me.document.createElement("p"); + range.insertNode(tmp); + range.setStart(tmp, 0).setCursor(); + } else { + tmp = me.document.createElement("br"); + range.insertNode(tmp); + range.setStartBefore(tmp).setCursor(); + } + } + } + } + return true; + } + }, + //边界在table里不能加分隔线 + queryCommandState: function () { + return domUtils.filterNodeList( + this.selection.getStartElementPath(), + "table" + ) + ? -1 + : 0; } - } - } - return true; - } - }, - //边界在table里不能加分隔线 - queryCommandState: function() { - return domUtils.filterNodeList( - this.selection.getStartElementPath(), - "table" - ) - ? -1 - : 0; - } - }; - // me.addListener('delkeyup',function(){ - // var rng = this.selection.getRange(); - // if(browser.ie && browser.version > 8){ - // rng.txtToElmBoundary(true); - // if(domUtils.isStartInblock(rng)){ - // var tmpNode = rng.startContainer; - // var pre = tmpNode.previousSibling; - // if(pre && domUtils.isTagNode(pre,'hr')){ - // domUtils.remove(pre); - // rng.select(); - // return; - // } - // } - // } - // if(domUtils.isBody(rng.startContainer)){ - // var hr = rng.startContainer.childNodes[rng.startOffset -1]; - // if(hr && hr.nodeName == 'HR'){ - // var next = hr.nextSibling; - // if(next){ - // rng.setStart(next,0) - // }else if(hr.previousSibling){ - // rng.setStartAtLast(hr.previousSibling) - // }else{ - // var p = this.document.createElement('p'); - // hr.parentNode.insertBefore(p,hr); - // domUtils.fillNode(this.document,p); - // rng.setStart(p,0); - // } - // domUtils.remove(hr); - // rng.setCursor(false,true); - // } - // } - // }) - me.addListener("delkeydown", function(name, evt) { - var rng = this.selection.getRange(); - rng.txtToElmBoundary(true); - if (domUtils.isStartInblock(rng)) { - var tmpNode = rng.startContainer; - var pre = tmpNode.previousSibling; - if (pre && domUtils.isTagNode(pre, "hr")) { - domUtils.remove(pre); - rng.select(); - domUtils.preventDefault(evt); - return true; - } - } - }); -}; + }; + // me.addListener('delkeyup',function(){ + // var rng = this.selection.getRange(); + // if(browser.ie && browser.version > 8){ + // rng.txtToElmBoundary(true); + // if(domUtils.isStartInblock(rng)){ + // var tmpNode = rng.startContainer; + // var pre = tmpNode.previousSibling; + // if(pre && domUtils.isTagNode(pre,'hr')){ + // domUtils.remove(pre); + // rng.select(); + // return; + // } + // } + // } + // if(domUtils.isBody(rng.startContainer)){ + // var hr = rng.startContainer.childNodes[rng.startOffset -1]; + // if(hr && hr.nodeName == 'HR'){ + // var next = hr.nextSibling; + // if(next){ + // rng.setStart(next,0) + // }else if(hr.previousSibling){ + // rng.setStartAtLast(hr.previousSibling) + // }else{ + // var p = this.document.createElement('p'); + // hr.parentNode.insertBefore(p,hr); + // domUtils.fillNode(this.document,p); + // rng.setStart(p,0); + // } + // domUtils.remove(hr); + // rng.setCursor(false,true); + // } + // } + // }) + me.addListener("delkeydown", function (name, evt) { + var rng = this.selection.getRange(); + rng.txtToElmBoundary(true); + if (domUtils.isStartInblock(rng)) { + var tmpNode = rng.startContainer; + var pre = tmpNode.previousSibling; + if (pre && domUtils.isTagNode(pre, "hr")) { + domUtils.remove(pre); + rng.select(); + domUtils.preventDefault(evt); + return true; + } + } + }); + }; // plugins/time.js -/** - * 插入时间和日期 - * @file - * @since 1.2.6.1 - */ + /** + * 插入时间和日期 + * @file + * @since 1.2.6.1 + */ -/** - * 插入时间,默认格式:12:59:59 - * @command time - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'time'); - * ``` - */ + /** + * 插入时间,默认格式:12:59:59 + * @command time + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'time'); + * ``` + */ -/** - * 插入日期,默认格式:2013-08-30 - * @command date - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'date'); - * ``` - */ -UE.commands["time"] = UE.commands["date"] = { - execCommand: function(cmd, format) { - var date = new Date(); + /** + * 插入日期,默认格式:2013-08-30 + * @command date + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'date'); + * ``` + */ + UE.commands["time"] = UE.commands["date"] = { + execCommand: function (cmd, format) { + var date = new Date(); - function formatTime(date, format) { - var hh = ("0" + date.getHours()).slice(-2), - ii = ("0" + date.getMinutes()).slice(-2), - ss = ("0" + date.getSeconds()).slice(-2); - format = format || "hh:ii:ss"; - return format.replace(/hh/gi, hh).replace(/ii/gi, ii).replace(/ss/gi, ss); - } - function formatDate(date, format) { - var yyyy = ("000" + date.getFullYear()).slice(-4), - yy = yyyy.slice(-2), - mm = ("0" + (date.getMonth() + 1)).slice(-2), - dd = ("0" + date.getDate()).slice(-2); - format = format || "yyyy-mm-dd"; - return format - .replace(/yyyy/gi, yyyy) - .replace(/yy/gi, yy) - .replace(/mm/gi, mm) - .replace(/dd/gi, dd); - } + function formatTime(date, format) { + var hh = ("0" + date.getHours()).slice(-2), + ii = ("0" + date.getMinutes()).slice(-2), + ss = ("0" + date.getSeconds()).slice(-2); + format = format || "hh:ii:ss"; + return format.replace(/hh/gi, hh).replace(/ii/gi, ii).replace(/ss/gi, ss); + } - this.execCommand( - "insertHtml", - cmd == "time" ? formatTime(date, format) : formatDate(date, format) - ); - } -}; + function formatDate(date, format) { + var yyyy = ("000" + date.getFullYear()).slice(-4), + yy = yyyy.slice(-2), + mm = ("0" + (date.getMonth() + 1)).slice(-2), + dd = ("0" + date.getDate()).slice(-2); + format = format || "yyyy-mm-dd"; + return format + .replace(/yyyy/gi, yyyy) + .replace(/yy/gi, yy) + .replace(/mm/gi, mm) + .replace(/dd/gi, dd); + } + + this.execCommand( + "insertHtml", + cmd == "time" ? formatTime(date, format) : formatDate(date, format) + ); + } + }; // plugins/rowspacing.js -/** - * 段前段后间距插件 - * @file - * @since 1.2.6.1 - */ + /** + * 段前段后间距插件 + * @file + * @since 1.2.6.1 + */ -/** - * 设置段间距 - * @command rowspacing - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } value 段间距的值,以px为单位 - * @param { String } dir 间距位置,top或bottom,分别表示段前和段后 - * @example - * ```javascript - * editor.execCommand( 'rowspacing', '10', 'top' ); - * ``` - */ + /** + * 设置段间距 + * @command rowspacing + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } value 段间距的值,以px为单位 + * @param { String } dir 间距位置,top或bottom,分别表示段前和段后 + * @example + * ```javascript + * editor.execCommand( 'rowspacing', '10', 'top' ); + * ``` + */ -UE.plugins["rowspacing"] = function() { - var me = this; - me.setOpt({ - rowspacingtop: ["5", "10", "15", "20", "25"], - rowspacingbottom: ["5", "10", "15", "20", "25"] - }); - me.commands["rowspacing"] = { - execCommand: function(cmdName, value, dir) { - this.execCommand("paragraph", "p", { - style: "margin-" + dir + ":" + value + "px" - }); - return true; - }, - queryCommandValue: function(cmdName, dir) { - var pN = domUtils.filterNodeList( - this.selection.getStartElementPath(), - function(node) { - return domUtils.isBlockElm(node); - } - ), - value; - //trace:1026 - if (pN) { - value = domUtils - .getComputedStyle(pN, "margin-" + dir) - .replace(/[^\d]/g, ""); - return !value ? 0 : value; - } - return 0; - } - }; -}; + UE.plugins["rowspacing"] = function () { + var me = this; + me.setOpt({ + rowspacingtop: ["5", "10", "15", "20", "25"], + rowspacingbottom: ["5", "10", "15", "20", "25"] + }); + me.commands["rowspacing"] = { + execCommand: function (cmdName, value, dir) { + this.execCommand("paragraph", "p", { + style: "margin-" + dir + ":" + value + "px" + }); + return true; + }, + queryCommandValue: function (cmdName, dir) { + var pN = domUtils.filterNodeList( + this.selection.getStartElementPath(), + function (node) { + return domUtils.isBlockElm(node); + } + ), + value; + //trace:1026 + if (pN) { + value = domUtils + .getComputedStyle(pN, "margin-" + dir) + .replace(/[^\d]/g, ""); + return !value ? 0 : value; + } + return 0; + } + }; + }; // plugins/lineheight.js -/** - * 设置行内间距 - * @file - * @since 1.2.6.1 - */ -UE.plugins["lineheight"] = function() { - var me = this; - me.setOpt({ lineheight: ["1", "1.5", "1.75", "2", "3", "4", "5"] }); - - /** - * 行距 - * @command lineheight - * @method execCommand - * @param { String } cmdName 命令字符串 - * @param { String } value 传入的行高值, 该值是当前字体的倍数, 例如: 1.5, 1.75 - * @example - * ```javascript - * editor.execCommand( 'lineheight', 1.5); - * ``` - */ - /** - * 查询当前选区内容的行高大小 - * @command lineheight - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回当前行高大小 - * @example - * ```javascript - * editor.queryCommandValue( 'lineheight' ); - * ``` + /** + * 设置行内间距 + * @file + * @since 1.2.6.1 */ + UE.plugins["lineheight"] = function () { + var me = this; + me.setOpt({lineheight: ["1", "1.5", "1.75", "2", "3", "4", "5"]}); - me.commands["lineheight"] = { - execCommand: function(cmdName, value) { - this.execCommand("paragraph", "p", { - style: "line-height:" + (value == "1" ? "normal" : value + "em") - }); - return true; - }, - queryCommandValue: function() { - var pN = domUtils.filterNodeList( - this.selection.getStartElementPath(), - function(node) { - return domUtils.isBlockElm(node); - } - ); - if (pN) { - var value = domUtils.getComputedStyle(pN, "line-height"); - return value == "normal" ? 1 : value.replace(/[^\d.]*/gi, ""); - } - } - }; -}; + /** + * 行距 + * @command lineheight + * @method execCommand + * @param { String } cmdName 命令字符串 + * @param { String } value 传入的行高值, 该值是当前字体的倍数, 例如: 1.5, 1.75 + * @example + * ```javascript + * editor.execCommand( 'lineheight', 1.5); + * ``` + */ + /** + * 查询当前选区内容的行高大小 + * @command lineheight + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回当前行高大小 + * @example + * ```javascript + * editor.queryCommandValue( 'lineheight' ); + * ``` + */ + + me.commands["lineheight"] = { + execCommand: function (cmdName, value) { + this.execCommand("paragraph", "p", { + style: "line-height:" + (value == "1" ? "normal" : value + "em") + }); + return true; + }, + queryCommandValue: function () { + var pN = domUtils.filterNodeList( + this.selection.getStartElementPath(), + function (node) { + return domUtils.isBlockElm(node); + } + ); + if (pN) { + var value = domUtils.getComputedStyle(pN, "line-height"); + return value == "normal" ? 1 : value.replace(/[^\d.]*/gi, ""); + } + } + }; + }; // plugins/insertcode.js -/** - * 插入代码插件 - * @file - * @since 1.2.6.1 - */ - -UE.plugins["insertcode"] = function() { - var me = this; - me.setOpt("insertcode", { - as3: "ActionScript3", - bash: "Bash/Shell", - cpp: "C/C++", - css: "Css", - // cf: "CodeFunction", - "c#": "C#", - delphi: "Delphi", - // diff: "Diff", - erlang: "Erlang", - groovy: "Groovy", - html: "Html", - java: "Java", - // jfx: "JavaFx", - js: "Javascript", - pl: "Perl", - php: "PHP", - plain: "Text", - ps: "PowerShell", - python: "Python", - ruby: "Ruby", - scala: "Scala", - sql: "SQL", - vb: "VB", - xml: "XML", - mind: "Mind", - }); - - /** - * 插入代码 - * @command insertcode - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } lang 插入代码的语言 - * @example - * ```javascript - * editor.execCommand( 'insertcode', 'javascript' ); - * ``` + /** + * 插入代码插件 + * @file + * @since 1.2.6.1 */ - /** - * 如果选区所在位置是插入插入代码区域,返回代码的语言 - * @command insertcode - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回代码的语言 - * @example - * ```javascript - * editor.queryCommandValue( 'insertcode' ); - * ``` - */ + UE.plugins["insertcode"] = function () { + var me = this; + me.setOpt("insertcode", { + as3: "ActionScript3", + bash: "Bash/Shell", + cpp: "C/C++", + css: "Css", + // cf: "CodeFunction", + "c#": "C#", + delphi: "Delphi", + // diff: "Diff", + erlang: "Erlang", + groovy: "Groovy", + html: "Html", + java: "Java", + // jfx: "JavaFx", + js: "Javascript", + pl: "Perl", + php: "PHP", + plain: "Text", + ps: "PowerShell", + python: "Python", + ruby: "Ruby", + scala: "Scala", + sql: "SQL", + vb: "VB", + xml: "XML", + mind: "Mind", + }); - me.commands["insertcode"] = { - execCommand: function(cmd, lang) { - var me = this, - rng = me.selection.getRange(), - pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); - if (pre) { - pre.className = "brush:" + lang + ";toolbar:false;"; - } else { - var code = ""; - if (rng.collapsed) { - code = browser.ie && browser.ie11below - ? browser.version <= 8 ? " " : "" - : "
    "; - } else { - var frag = rng.extractContents(); - var div = me.document.createElement("div"); - div.appendChild(frag); + /** + * 插入代码 + * @command insertcode + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } lang 插入代码的语言 + * @example + * ```javascript + * editor.execCommand( 'insertcode', 'javascript' ); + * ``` + */ - utils.each( - UE.filterNode( - UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, "")), - me.options.filterTxtRules - ).children, - function(node) { - if (browser.ie && browser.ie11below && browser.version > 8) { - if (node.type == "element") { - if (node.tagName == "br") { - code += "\n"; - } else if (!dtd.$empty[node.tagName]) { - utils.each(node.children, function(cn) { - if (cn.type == "element") { - if (cn.tagName == "br") { - code += "\n"; - } else if (!dtd.$empty[node.tagName]) { - code += cn.innerText(); - } - } else { - code += cn.data; - } - }); - if (!/\n$/.test(code)) { - code += "\n"; - } - } + /** + * 如果选区所在位置是插入插入代码区域,返回代码的语言 + * @command insertcode + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回代码的语言 + * @example + * ```javascript + * editor.queryCommandValue( 'insertcode' ); + * ``` + */ + + me.commands["insertcode"] = { + execCommand: function (cmd, lang) { + var me = this, + rng = me.selection.getRange(), + pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + if (pre) { + pre.className = "brush:" + lang + ";toolbar:false;"; } else { - code += node.data + "\n"; - } - if (!node.nextSibling() && /\n$/.test(code)) { - code = code.replace(/\n$/, ""); - } - } else { - if (browser.ie && browser.ie11below) { - if (node.type == "element") { - if (node.tagName == "br") { - code += "
    "; - } else if (!dtd.$empty[node.tagName]) { - utils.each(node.children, function(cn) { - if (cn.type == "element") { - if (cn.tagName == "br") { - code += "
    "; - } else if (!dtd.$empty[node.tagName]) { - code += cn.innerText(); - } - } else { - code += cn.data; - } - }); - if (!/br>$/.test(code)) { - code += "
    "; - } + var code = ""; + if (rng.collapsed) { + code = browser.ie && browser.ie11below + ? browser.version <= 8 ? " " : "" + : "
    "; + } else { + var frag = rng.extractContents(); + var div = me.document.createElement("div"); + div.appendChild(frag); + + utils.each( + UE.filterNode( + UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, "")), + me.options.filterTxtRules + ).children, + function (node) { + if (browser.ie && browser.ie11below && browser.version > 8) { + if (node.type == "element") { + if (node.tagName == "br") { + code += "\n"; + } else if (!dtd.$empty[node.tagName]) { + utils.each(node.children, function (cn) { + if (cn.type == "element") { + if (cn.tagName == "br") { + code += "\n"; + } else if (!dtd.$empty[node.tagName]) { + code += cn.innerText(); + } + } else { + code += cn.data; + } + }); + if (!/\n$/.test(code)) { + code += "\n"; + } + } + } else { + code += node.data + "\n"; + } + if (!node.nextSibling() && /\n$/.test(code)) { + code = code.replace(/\n$/, ""); + } + } else { + if (browser.ie && browser.ie11below) { + if (node.type == "element") { + if (node.tagName == "br") { + code += "
    "; + } else if (!dtd.$empty[node.tagName]) { + utils.each(node.children, function (cn) { + if (cn.type == "element") { + if (cn.tagName == "br") { + code += "
    "; + } else if (!dtd.$empty[node.tagName]) { + code += cn.innerText(); + } + } else { + code += cn.data; + } + }); + if (!/br>$/.test(code)) { + code += "
    "; + } + } + } else { + code += node.data + "
    "; + } + if (!node.nextSibling() && /
    $/.test(code)) { + code = code.replace(/
    $/, ""); + } + } else { + code += node.type == "element" + ? dtd.$empty[node.tagName] ? "" : node.innerText() + : node.data; + if (!/br\/?\s*>$/.test(code)) { + if (!node.nextSibling()) return; + code += "
    "; + } + } + } + } + ); } - } else { - code += node.data + "
    "; - } - if (!node.nextSibling() && /
    $/.test(code)) { - code = code.replace(/
    $/, ""); - } - } else { - code += node.type == "element" - ? dtd.$empty[node.tagName] ? "" : node.innerText() - : node.data; - if (!/br\/?\s*>$/.test(code)) { - if (!node.nextSibling()) return; - code += "
    "; - } - } - } - } - ); - } - me.execCommand( - "inserthtml", - '
    ' +
    -            code +
    -            "
    ", - true - ); - - pre = me.document.getElementById("coder"); - domUtils.removeAttributes(pre, "id"); - var tmpNode = pre.previousSibling; - - if ( - tmpNode && - ((tmpNode.nodeType == 3 && - tmpNode.nodeValue.length == 1 && - browser.ie && - browser.version == 6) || - domUtils.isEmptyBlock(tmpNode)) - ) { - domUtils.remove(tmpNode); - } - var rng = me.selection.getRange(); - if (domUtils.isEmptyBlock(pre)) { - rng.setStart(pre, 0).setCursor(false, true); - } else { - rng.selectNodeContents(pre).select(); - } - } - }, - queryCommandValue: function() { - var path = this.selection.getStartElementPath(); - var lang = ""; - utils.each(path, function(node) { - if (node.nodeName == "PRE") { - var match = node.className.match(/brush:([^;]+)/); - lang = match && match[1] ? match[1] : ""; - return false; - } - }); - return lang; - } - }; - - me.addInputRule(function(root) { - utils.each(root.getNodesByTagName("pre"), function(pre) { - var brs = pre.getNodesByTagName("br"); - if (brs.length) { - browser.ie && - browser.ie11below && - browser.version > 8 && - utils.each(brs, function(br) { - var txt = UE.uNode.createText("\n"); - br.parentNode.insertBefore(txt, br); - br.parentNode.removeChild(br); - }); - return; - } - if (browser.ie && browser.ie11below && browser.version > 8) return; - var code = pre.innerText().split(/\n/); - pre.innerHTML(""); - utils.each(code, function(c) { - if (c.length) { - pre.appendChild(UE.uNode.createText(c)); - } - pre.appendChild(UE.uNode.createElement("br")); - }); - }); - }); - me.addOutputRule(function(root) { - utils.each(root.getNodesByTagName("pre"), function(pre) { - var code = ""; - utils.each(pre.children, function(n) { - if (n.type == "text") { - //在ie下文本内容有可能末尾带有\n要去掉 - //trace:3396 - code += n.data.replace(/[ ]/g, " ").replace(/\n$/, ""); - } else { - if (n.tagName == "br") { - code += "\n"; - } else { - code += !dtd.$empty[n.tagName] ? "" : n.innerText(); - } - } - }); - - pre.innerText(code.replace(/( |\n)+$/, "")); - }); - }); - //不需要判断highlight的command列表 - me.notNeedCodeQuery = { - help: 1, - undo: 1, - redo: 1, - source: 1, - print: 1, - searchreplace: 1, - fullscreen: 1, - preview: 1, - insertparagraph: 1, - elementpath: 1, - insertcode: 1, - inserthtml: 1, - selectall: 1 - }; - //将queyCommamndState重置 - var orgQuery = me.queryCommandState; - me.queryCommandState = function(cmd) { - var me = this; - - if ( - !me.notNeedCodeQuery[cmd.toLowerCase()] && - me.selection && - me.queryCommandValue("insertcode") - ) { - return -1; - } - return UE.Editor.prototype.queryCommandState.apply(this, arguments); - }; - me.addListener("beforeenterkeydown", function() { - var rng = me.selection.getRange(); - var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); - if (pre) { - me.fireEvent("saveScene"); - if (!rng.collapsed) { - rng.deleteContents(); - } - if (!browser.ie || browser.ie9above) { - var tmpNode = me.document.createElement("br"), - pre; - rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true); - var next = tmpNode.nextSibling; - if (!next && (!browser.ie || browser.version > 10)) { - rng.insertNode(tmpNode.cloneNode(false)); - } else { - rng.setStartAfter(tmpNode); - } - pre = tmpNode.previousSibling; - var tmp; - while (pre) { - tmp = pre; - pre = pre.previousSibling; - if (!pre || pre.nodeName == "BR") { - pre = tmp; - break; - } - } - if (pre) { - var str = ""; - while ( - pre && - pre.nodeName != "BR" && - new RegExp("^[\\s" + domUtils.fillChar + "]*$").test(pre.nodeValue) - ) { - str += pre.nodeValue; - pre = pre.nextSibling; - } - if (pre.nodeName != "BR") { - var match = pre.nodeValue.match( - new RegExp("^([\\s" + domUtils.fillChar + "]+)") - ); - if (match && match[1]) { - str += match[1]; - } - } - if (str) { - str = me.document.createTextNode(str); - rng.insertNode(str).setStartAfter(str); - } - } - rng.collapse(true).select(true); - } else { - if (browser.version > 8) { - var txt = me.document.createTextNode("\n"); - var start = rng.startContainer; - if (rng.startOffset == 0) { - var preNode = start.previousSibling; - if (preNode) { - rng.insertNode(txt); - var fillchar = me.document.createTextNode(" "); - rng - .setStartAfter(txt) - .insertNode(fillchar) - .setStart(fillchar, 0) - .collapse(true) - .select(true); - } - } else { - rng.insertNode(txt).setStartAfter(txt); - var fillchar = me.document.createTextNode(" "); - start = rng.startContainer.childNodes[rng.startOffset]; - if (start && !/^\n/.test(start.nodeValue)) { - rng.setStartBefore(txt); - } - rng - .insertNode(fillchar) - .setStart(fillchar, 0) - .collapse(true) - .select(true); - } - } else { - var tmpNode = me.document.createElement("br"); - rng.insertNode(tmpNode); - rng.insertNode(me.document.createTextNode(domUtils.fillChar)); - rng.setStartAfter(tmpNode); - pre = tmpNode.previousSibling; - var tmp; - while (pre) { - tmp = pre; - pre = pre.previousSibling; - if (!pre || pre.nodeName == "BR") { - pre = tmp; - break; - } - } - if (pre) { - var str = ""; - while ( - pre && - pre.nodeName != "BR" && - new RegExp("^[ " + domUtils.fillChar + "]*$").test(pre.nodeValue) - ) { - str += pre.nodeValue; - pre = pre.nextSibling; - } - if (pre.nodeName != "BR") { - var match = pre.nodeValue.match( - new RegExp("^([ " + domUtils.fillChar + "]+)") - ); - if (match && match[1]) { - str += match[1]; - } - } - - str = me.document.createTextNode(str); - rng.insertNode(str).setStartAfter(str); - } - rng.collapse(true).select(); - } - } - me.fireEvent("saveScene"); - return true; - } - }); - - me.addListener("tabkeydown", function(cmd, evt) { - var rng = me.selection.getRange(); - var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); - if (pre) { - me.fireEvent("saveScene"); - if (evt.shiftKey) { - } else { - if (!rng.collapsed) { - var bk = rng.createBookmark(); - var start = bk.start.previousSibling; - - while (start) { - if (pre.firstChild === start && !domUtils.isBr(start)) { - pre.insertBefore(me.document.createTextNode(" "), start); - - break; - } - if (domUtils.isBr(start)) { - pre.insertBefore( - me.document.createTextNode(" "), - start.nextSibling - ); - - break; - } - start = start.previousSibling; - } - var end = bk.end; - start = bk.start.nextSibling; - if (pre.firstChild === bk.start) { - pre.insertBefore( - me.document.createTextNode(" "), - start.nextSibling - ); - } - while (start && start !== end) { - if (domUtils.isBr(start) && start.nextSibling) { - if (start.nextSibling === end) { - break; - } - pre.insertBefore( - me.document.createTextNode(" "), - start.nextSibling - ); - } - - start = start.nextSibling; - } - rng.moveToBookmark(bk).select(); - } else { - var tmpNode = me.document.createTextNode(" "); - rng - .insertNode(tmpNode) - .setStartAfter(tmpNode) - .collapse(true) - .select(true); - } - } - - me.fireEvent("saveScene"); - return true; - } - }); - - me.addListener("beforeinserthtml", function(evtName, html) { - var me = this, - rng = me.selection.getRange(), - pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); - if (pre) { - if (!rng.collapsed) { - rng.deleteContents(); - } - var htmlstr = ""; - if (browser.ie && browser.version > 8) { - utils.each( - UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules) - .children, - function(node) { - if (node.type == "element") { - if (node.tagName == "br") { - htmlstr += "\n"; - } else if (!dtd.$empty[node.tagName]) { - utils.each(node.children, function(cn) { - if (cn.type == "element") { - if (cn.tagName == "br") { - htmlstr += "\n"; - } else if (!dtd.$empty[node.tagName]) { - htmlstr += cn.innerText(); - } - } else { - htmlstr += cn.data; - } - }); - if (!/\n$/.test(htmlstr)) { - htmlstr += "\n"; - } - } - } else { - htmlstr += node.data + "\n"; - } - if (!node.nextSibling() && /\n$/.test(htmlstr)) { - htmlstr = htmlstr.replace(/\n$/, ""); - } - } - ); - var tmpNode = me.document.createTextNode( - utils.html(htmlstr.replace(/ /g, " ")) - ); - rng.insertNode(tmpNode).selectNode(tmpNode).select(); - } else { - var frag = me.document.createDocumentFragment(); - - utils.each( - UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules) - .children, - function(node) { - if (node.type == "element") { - if (node.tagName == "br") { - frag.appendChild(me.document.createElement("br")); - } else if (!dtd.$empty[node.tagName]) { - utils.each(node.children, function(cn) { - if (cn.type == "element") { - if (cn.tagName == "br") { - frag.appendChild(me.document.createElement("br")); - } else if (!dtd.$empty[node.tagName]) { - frag.appendChild( - me.document.createTextNode( - utils.html(cn.innerText().replace(/ /g, " ")) - ) - ); - } - } else { - frag.appendChild( - me.document.createTextNode( - utils.html(cn.data.replace(/ /g, " ")) - ) + me.execCommand( + "inserthtml", + '
    ' +
    +                        code +
    +                        "
    ", + true ); - } - }); - if (frag.lastChild.nodeName != "BR") { - frag.appendChild(me.document.createElement("br")); - } - } - } else { - frag.appendChild( - me.document.createTextNode( - utils.html(node.data.replace(/ /g, " ")) - ) - ); - } - if (!node.nextSibling() && frag.lastChild.nodeName == "BR") { - frag.removeChild(frag.lastChild); - } - } - ); - rng.insertNode(frag).select(); - } - return true; - } - }); - //方向键的处理 - me.addListener("keydown", function(cmd, evt) { - var me = this, - keyCode = evt.keyCode || evt.which; - if (keyCode == 40) { - var rng = me.selection.getRange(), - pre, - start = rng.startContainer; - if ( - rng.collapsed && - (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) && - !pre.nextSibling - ) { - var last = pre.lastChild; - while (last && last.nodeName == "BR") { - last = last.previousSibling; - } - if ( - last === start || - (rng.startContainer === pre && - rng.startOffset == pre.childNodes.length) - ) { - me.execCommand("insertparagraph"); - domUtils.preventDefault(evt); - } - } - } - }); - //trace:3395 - me.addListener("delkeydown", function(type, evt) { - var rng = this.selection.getRange(); - rng.txtToElmBoundary(true); - var start = rng.startContainer; - if ( - domUtils.isTagNode(start, "pre") && - rng.collapsed && - domUtils.isStartInblock(rng) - ) { - var p = me.document.createElement("p"); - domUtils.fillNode(me.document, p); - start.parentNode.insertBefore(p, start); - domUtils.remove(start); - rng.setStart(p, 0).setCursor(false, true); - domUtils.preventDefault(evt); - return true; - } - }); -}; + pre = me.document.getElementById("coder"); + domUtils.removeAttributes(pre, "id"); + var tmpNode = pre.previousSibling; + + if ( + tmpNode && + ((tmpNode.nodeType == 3 && + tmpNode.nodeValue.length == 1 && + browser.ie && + browser.version == 6) || + domUtils.isEmptyBlock(tmpNode)) + ) { + domUtils.remove(tmpNode); + } + var rng = me.selection.getRange(); + if (domUtils.isEmptyBlock(pre)) { + rng.setStart(pre, 0).setCursor(false, true); + } else { + rng.selectNodeContents(pre).select(); + } + } + }, + queryCommandValue: function () { + var path = this.selection.getStartElementPath(); + var lang = ""; + utils.each(path, function (node) { + if (node.nodeName == "PRE") { + var match = node.className.match(/brush:([^;]+)/); + lang = match && match[1] ? match[1] : ""; + return false; + } + }); + return lang; + } + }; + + me.addInputRule(function (root) { + utils.each(root.getNodesByTagName("pre"), function (pre) { + var brs = pre.getNodesByTagName("br"); + if (brs.length) { + browser.ie && + browser.ie11below && + browser.version > 8 && + utils.each(brs, function (br) { + var txt = UE.uNode.createText("\n"); + br.parentNode.insertBefore(txt, br); + br.parentNode.removeChild(br); + }); + return; + } + if (browser.ie && browser.ie11below && browser.version > 8) return; + var code = pre.innerText().split(/\n/); + pre.innerHTML(""); + utils.each(code, function (c) { + if (c.length) { + pre.appendChild(UE.uNode.createText(c)); + } + pre.appendChild(UE.uNode.createElement("br")); + }); + }); + }); + me.addOutputRule(function (root) { + utils.each(root.getNodesByTagName("pre"), function (pre) { + var code = ""; + utils.each(pre.children, function (n) { + if (n.type == "text") { + //在ie下文本内容有可能末尾带有\n要去掉 + //trace:3396 + code += n.data.replace(/[ ]/g, " ").replace(/\n$/, ""); + } else { + if (n.tagName == "br") { + code += "\n"; + } else { + code += !dtd.$empty[n.tagName] ? "" : n.innerText(); + } + } + }); + + pre.innerText(code.replace(/( |\n)+$/, "")); + }); + }); + //不需要判断highlight的command列表 + me.notNeedCodeQuery = { + help: 1, + undo: 1, + redo: 1, + source: 1, + print: 1, + searchreplace: 1, + fullscreen: 1, + preview: 1, + insertparagraph: 1, + elementpath: 1, + insertcode: 1, + inserthtml: 1, + selectall: 1 + }; + //将queyCommamndState重置 + var orgQuery = me.queryCommandState; + me.queryCommandState = function (cmd) { + var me = this; + + if ( + !me.notNeedCodeQuery[cmd.toLowerCase()] && + me.selection && + me.queryCommandValue("insertcode") + ) { + return -1; + } + return UE.Editor.prototype.queryCommandState.apply(this, arguments); + }; + me.addListener("beforeenterkeydown", function () { + var rng = me.selection.getRange(); + var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + if (pre) { + me.fireEvent("saveScene"); + if (!rng.collapsed) { + rng.deleteContents(); + } + if (!browser.ie || browser.ie9above) { + var tmpNode = me.document.createElement("br"), + pre; + rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true); + var next = tmpNode.nextSibling; + if (!next && (!browser.ie || browser.version > 10)) { + rng.insertNode(tmpNode.cloneNode(false)); + } else { + rng.setStartAfter(tmpNode); + } + pre = tmpNode.previousSibling; + var tmp; + while (pre) { + tmp = pre; + pre = pre.previousSibling; + if (!pre || pre.nodeName == "BR") { + pre = tmp; + break; + } + } + if (pre) { + var str = ""; + while ( + pre && + pre.nodeName != "BR" && + new RegExp("^[\\s" + domUtils.fillChar + "]*$").test(pre.nodeValue) + ) { + str += pre.nodeValue; + pre = pre.nextSibling; + } + if (pre.nodeName != "BR") { + var match = pre.nodeValue.match( + new RegExp("^([\\s" + domUtils.fillChar + "]+)") + ); + if (match && match[1]) { + str += match[1]; + } + } + if (str) { + str = me.document.createTextNode(str); + rng.insertNode(str).setStartAfter(str); + } + } + rng.collapse(true).select(true); + } else { + if (browser.version > 8) { + var txt = me.document.createTextNode("\n"); + var start = rng.startContainer; + if (rng.startOffset == 0) { + var preNode = start.previousSibling; + if (preNode) { + rng.insertNode(txt); + var fillchar = me.document.createTextNode(" "); + rng + .setStartAfter(txt) + .insertNode(fillchar) + .setStart(fillchar, 0) + .collapse(true) + .select(true); + } + } else { + rng.insertNode(txt).setStartAfter(txt); + var fillchar = me.document.createTextNode(" "); + start = rng.startContainer.childNodes[rng.startOffset]; + if (start && !/^\n/.test(start.nodeValue)) { + rng.setStartBefore(txt); + } + rng + .insertNode(fillchar) + .setStart(fillchar, 0) + .collapse(true) + .select(true); + } + } else { + var tmpNode = me.document.createElement("br"); + rng.insertNode(tmpNode); + rng.insertNode(me.document.createTextNode(domUtils.fillChar)); + rng.setStartAfter(tmpNode); + pre = tmpNode.previousSibling; + var tmp; + while (pre) { + tmp = pre; + pre = pre.previousSibling; + if (!pre || pre.nodeName == "BR") { + pre = tmp; + break; + } + } + if (pre) { + var str = ""; + while ( + pre && + pre.nodeName != "BR" && + new RegExp("^[ " + domUtils.fillChar + "]*$").test(pre.nodeValue) + ) { + str += pre.nodeValue; + pre = pre.nextSibling; + } + if (pre.nodeName != "BR") { + var match = pre.nodeValue.match( + new RegExp("^([ " + domUtils.fillChar + "]+)") + ); + if (match && match[1]) { + str += match[1]; + } + } + + str = me.document.createTextNode(str); + rng.insertNode(str).setStartAfter(str); + } + rng.collapse(true).select(); + } + } + me.fireEvent("saveScene"); + return true; + } + }); + + me.addListener("tabkeydown", function (cmd, evt) { + var rng = me.selection.getRange(); + var pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + if (pre) { + me.fireEvent("saveScene"); + if (evt.shiftKey) { + } else { + if (!rng.collapsed) { + var bk = rng.createBookmark(); + var start = bk.start.previousSibling; + + while (start) { + if (pre.firstChild === start && !domUtils.isBr(start)) { + pre.insertBefore(me.document.createTextNode(" "), start); + + break; + } + if (domUtils.isBr(start)) { + pre.insertBefore( + me.document.createTextNode(" "), + start.nextSibling + ); + + break; + } + start = start.previousSibling; + } + var end = bk.end; + start = bk.start.nextSibling; + if (pre.firstChild === bk.start) { + pre.insertBefore( + me.document.createTextNode(" "), + start.nextSibling + ); + } + while (start && start !== end) { + if (domUtils.isBr(start) && start.nextSibling) { + if (start.nextSibling === end) { + break; + } + pre.insertBefore( + me.document.createTextNode(" "), + start.nextSibling + ); + } + + start = start.nextSibling; + } + rng.moveToBookmark(bk).select(); + } else { + var tmpNode = me.document.createTextNode(" "); + rng + .insertNode(tmpNode) + .setStartAfter(tmpNode) + .collapse(true) + .select(true); + } + } + + me.fireEvent("saveScene"); + return true; + } + }); + + me.addListener("beforeinserthtml", function (evtName, html) { + var me = this, + rng = me.selection.getRange(), + pre = domUtils.findParentByTagName(rng.startContainer, "pre", true); + if (pre) { + if (!rng.collapsed) { + rng.deleteContents(); + } + var htmlstr = ""; + if (browser.ie && browser.version > 8) { + utils.each( + UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules) + .children, + function (node) { + if (node.type == "element") { + if (node.tagName == "br") { + htmlstr += "\n"; + } else if (!dtd.$empty[node.tagName]) { + utils.each(node.children, function (cn) { + if (cn.type == "element") { + if (cn.tagName == "br") { + htmlstr += "\n"; + } else if (!dtd.$empty[node.tagName]) { + htmlstr += cn.innerText(); + } + } else { + htmlstr += cn.data; + } + }); + if (!/\n$/.test(htmlstr)) { + htmlstr += "\n"; + } + } + } else { + htmlstr += node.data + "\n"; + } + if (!node.nextSibling() && /\n$/.test(htmlstr)) { + htmlstr = htmlstr.replace(/\n$/, ""); + } + } + ); + var tmpNode = me.document.createTextNode( + utils.html(htmlstr.replace(/ /g, " ")) + ); + rng.insertNode(tmpNode).selectNode(tmpNode).select(); + } else { + var frag = me.document.createDocumentFragment(); + + utils.each( + UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules) + .children, + function (node) { + if (node.type == "element") { + if (node.tagName == "br") { + frag.appendChild(me.document.createElement("br")); + } else if (!dtd.$empty[node.tagName]) { + utils.each(node.children, function (cn) { + if (cn.type == "element") { + if (cn.tagName == "br") { + frag.appendChild(me.document.createElement("br")); + } else if (!dtd.$empty[node.tagName]) { + frag.appendChild( + me.document.createTextNode( + utils.html(cn.innerText().replace(/ /g, " ")) + ) + ); + } + } else { + frag.appendChild( + me.document.createTextNode( + utils.html(cn.data.replace(/ /g, " ")) + ) + ); + } + }); + if (frag.lastChild.nodeName != "BR") { + frag.appendChild(me.document.createElement("br")); + } + } + } else { + frag.appendChild( + me.document.createTextNode( + utils.html(node.data.replace(/ /g, " ")) + ) + ); + } + if (!node.nextSibling() && frag.lastChild.nodeName == "BR") { + frag.removeChild(frag.lastChild); + } + } + ); + rng.insertNode(frag).select(); + } + + return true; + } + }); + //方向键的处理 + me.addListener("keydown", function (cmd, evt) { + var me = this, + keyCode = evt.keyCode || evt.which; + if (keyCode == 40) { + var rng = me.selection.getRange(), + pre, + start = rng.startContainer; + if ( + rng.collapsed && + (pre = domUtils.findParentByTagName(rng.startContainer, "pre", true)) && + !pre.nextSibling + ) { + var last = pre.lastChild; + while (last && last.nodeName == "BR") { + last = last.previousSibling; + } + if ( + last === start || + (rng.startContainer === pre && + rng.startOffset == pre.childNodes.length) + ) { + me.execCommand("insertparagraph"); + domUtils.preventDefault(evt); + } + } + } + }); + //trace:3395 + me.addListener("delkeydown", function (type, evt) { + var rng = this.selection.getRange(); + rng.txtToElmBoundary(true); + var start = rng.startContainer; + if ( + domUtils.isTagNode(start, "pre") && + rng.collapsed && + domUtils.isStartInblock(rng) + ) { + var p = me.document.createElement("p"); + domUtils.fillNode(me.document, p); + start.parentNode.insertBefore(p, start); + domUtils.remove(start); + rng.setStart(p, 0).setCursor(false, true); + domUtils.preventDefault(evt); + return true; + } + }); + }; // plugins/cleardoc.js -/** - * 清空文档插件 - * @file - * @since 1.2.6.1 - */ + /** + * 清空文档插件 + * @file + * @since 1.2.6.1 + */ -/** - * 清空文档 - * @command cleardoc - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * //editor 是编辑器实例 - * editor.execCommand('cleardoc'); - * ``` - */ + /** + * 清空文档 + * @command cleardoc + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * //editor 是编辑器实例 + * editor.execCommand('cleardoc'); + * ``` + */ -UE.commands["cleardoc"] = { - execCommand: function(cmdName) { - var me = this, - enterTag = me.options.enterTag, - range = me.selection.getRange(); - if (enterTag == "br") { - me.body.innerHTML = "
    "; - range.setStart(me.body, 0).setCursor(); - } else { - me.body.innerHTML = "

    " + (ie ? "" : "
    ") + "

    "; - range.setStart(me.body.firstChild, 0).setCursor(false, true); - } - setTimeout(function() { - me.fireEvent("clearDoc"); - }, 0); - } -}; + UE.commands["cleardoc"] = { + execCommand: function (cmdName) { + var me = this, + enterTag = me.options.enterTag, + range = me.selection.getRange(); + if (enterTag == "br") { + me.body.innerHTML = "
    "; + range.setStart(me.body, 0).setCursor(); + } else { + me.body.innerHTML = "

    " + (ie ? "" : "
    ") + "

    "; + range.setStart(me.body.firstChild, 0).setCursor(false, true); + } + setTimeout(function () { + me.fireEvent("clearDoc"); + }, 0); + } + }; // plugins/anchor.js -/** - * 锚点插件,为UEditor提供插入锚点支持 - * @file - * @since 1.2.6.1 - */ -UE.plugin.register("anchor", function() { - return { - bindEvents: { - ready: function() { - utils.cssRule( - "anchor", - ".anchorclass{background: url('" + - this.options.themePath + - this.options.theme + - "/images/anchor.gif') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}", - this.document - ); - } - }, - outputRule: function(root) { - utils.each(root.getNodesByTagName("img"), function(a) { - var val; - if ((val = a.getAttr("anchorname"))) { - a.tagName = "a"; - a.setAttr({ - anchorname: "", - name: val, - class: "" - }); - } - }); - }, - inputRule: function(root) { - utils.each(root.getNodesByTagName("a"), function(a) { - var val; - if ((val = a.getAttr("name")) && !a.getAttr("href")) { - //过滤掉word冗余标签 - //_Toc\d+有可能勿命中 - if (/^\_Toc\d+$/.test(val)) { - a.parentNode.removeChild(a); - return; - } - a.tagName = "img"; - a.setAttr({ - anchorname: a.getAttr("name"), - class: "anchorclass" - }); - a.setAttr("name"); - } - }); - }, - commands: { - /** - * 插入锚点 - * @command anchor - * @method execCommand - * @param { String } cmd 命令字符串 - * @param { String } name 锚点名称字符串 - * @example - * ```javascript - * //editor 是编辑器实例 - * editor.execCommand('anchor', 'anchor1'); - * ``` - */ - anchor: { - execCommand: function(cmd, name) { - var range = this.selection.getRange(), - img = range.getClosedNode(); - if (img && img.getAttribute("anchorname")) { - if (name) { - img.setAttribute("anchorname", name); - } else { - range.setStartBefore(img).setCursor(); - domUtils.remove(img); + /** + * 锚点插件,为UEditor提供插入锚点支持 + * @file + * @since 1.2.6.1 + */ + UE.plugin.register("anchor", function () { + return { + bindEvents: { + ready: function () { + utils.cssRule( + "anchor", + ".anchorclass{background: url('" + + this.options.themePath + + this.options.theme + + "/images/anchor.gif') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}", + this.document + ); + } + }, + outputRule: function (root) { + utils.each(root.getNodesByTagName("img"), function (a) { + var val; + if ((val = a.getAttr("anchorname"))) { + a.tagName = "a"; + a.setAttr({ + anchorname: "", + name: val, + class: "" + }); + } + }); + }, + inputRule: function (root) { + utils.each(root.getNodesByTagName("a"), function (a) { + var val; + if ((val = a.getAttr("name")) && !a.getAttr("href")) { + //过滤掉word冗余标签 + //_Toc\d+有可能勿命中 + if (/^\_Toc\d+$/.test(val)) { + a.parentNode.removeChild(a); + return; + } + a.tagName = "img"; + a.setAttr({ + anchorname: a.getAttr("name"), + class: "anchorclass" + }); + a.setAttr("name"); + } + }); + }, + commands: { + /** + * 插入锚点 + * @command anchor + * @method execCommand + * @param { String } cmd 命令字符串 + * @param { String } name 锚点名称字符串 + * @example + * ```javascript + * //editor 是编辑器实例 + * editor.execCommand('anchor', 'anchor1'); + * ``` + */ + anchor: { + execCommand: function (cmd, name) { + var range = this.selection.getRange(), + img = range.getClosedNode(); + if (img && img.getAttribute("anchorname")) { + if (name) { + img.setAttribute("anchorname", name); + } else { + range.setStartBefore(img).setCursor(); + domUtils.remove(img); + } + } else { + if (name) { + //只在选区的开始插入 + var anchor = this.document.createElement("img"); + range.collapse(true); + domUtils.setAttributes(anchor, { + anchorname: name, + class: "anchorclass" + }); + range + .insertNode(anchor) + .setStartAfter(anchor) + .setCursor(false, true); + } + } + } + } } - } else { - if (name) { - //只在选区的开始插入 - var anchor = this.document.createElement("img"); - range.collapse(true); - domUtils.setAttributes(anchor, { - anchorname: name, - class: "anchorclass" - }); - range - .insertNode(anchor) - .setStartAfter(anchor) - .setCursor(false, true); - } - } - } - } - } - }; -}); + }; + }); // plugins/wordcount.js @@ -15303,7 +18578,7 @@ UE.plugin.register("anchor", function() { ///commands 字数统计 ///commandsName WordCount,wordCount ///commandsTitle 字数统计 -/* + /* * Created by JetBrains WebStorm. * User: taoqili * Date: 11-9-7 @@ -15311,215 +18586,218 @@ UE.plugin.register("anchor", function() { * To change this template use File | Settings | File Templates. */ -UE.plugins["wordcount"] = function() { - var me = this; - me.setOpt("wordCount", true); - me.addListener("contentchange", function() { - me.fireEvent("wordcount"); - }); - var timer; - me.addListener("ready", function() { - var me = this; - domUtils.on(me.body, "keyup", function(evt) { - var code = evt.keyCode || evt.which, - //忽略的按键,ctr,alt,shift,方向键 - ignores = { - "16": 1, - "18": 1, - "20": 1, - "37": 1, - "38": 1, - "39": 1, - "40": 1 - }; - if (code in ignores) return; - clearTimeout(timer); - timer = setTimeout(function() { - me.fireEvent("wordcount"); - }, 200); - }); - }); -}; + UE.plugins["wordcount"] = function () { + var me = this; + me.setOpt("wordCount", true); + me.addListener("contentchange", function () { + me.fireEvent("wordcount"); + }); + var timer; + me.addListener("ready", function () { + var me = this; + domUtils.on(me.body, "keyup", function (evt) { + var code = evt.keyCode || evt.which, + //忽略的按键,ctr,alt,shift,方向键 + ignores = { + "16": 1, + "18": 1, + "20": 1, + "37": 1, + "38": 1, + "39": 1, + "40": 1 + }; + if (code in ignores) return; + clearTimeout(timer); + timer = setTimeout(function () { + me.fireEvent("wordcount"); + }, 200); + }); + }); + }; // plugins/pagebreak.js -/** - * 分页功能插件 - * @file - * @since 1.2.6.1 - */ -UE.plugins["pagebreak"] = function() { - var me = this, - notBreakTags = ["td"]; - me.setOpt("pageBreakTag", "_ueditor_page_break_tag_"); - - function fillNode(node) { - if (domUtils.isEmptyBlock(node)) { - var firstChild = node.firstChild, - tmpNode; - - while ( - firstChild && - firstChild.nodeType == 1 && - domUtils.isEmptyBlock(firstChild) - ) { - tmpNode = firstChild; - firstChild = firstChild.firstChild; - } - !tmpNode && (tmpNode = node); - domUtils.fillNode(me.document, tmpNode); - } - } - //分页符样式添加 - - me.ready(function() { - utils.cssRule( - "pagebreak", - ".pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}", - me.document - ); - }); - function isHr(node) { - return ( - node && - node.nodeType == 1 && - node.tagName == "HR" && - node.className == "pagebreak" - ); - } - me.addInputRule(function(root) { - root.traversal(function(node) { - if (node.type == "text" && node.data == me.options.pageBreakTag) { - var hr = UE.uNode.createElement( - '
    ' - ); - node.parentNode.insertBefore(hr, node); - node.parentNode.removeChild(node); - } - }); - }); - me.addOutputRule(function(node) { - utils.each(node.getNodesByTagName("hr"), function(n) { - if (n.getAttr("class") == "pagebreak") { - var txt = UE.uNode.createText(me.options.pageBreakTag); - n.parentNode.insertBefore(txt, n); - n.parentNode.removeChild(n); - } - }); - }); - - /** - * 插入分页符 - * @command pagebreak - * @method execCommand - * @param { String } cmd 命令字符串 - * @remind 在表格中插入分页符会把表格切分成两部分 - * @remind 获取编辑器内的数据时, 编辑器会把分页符转换成“_ueditor_page_break_tag_”字符串, - * 以便于提交数据到服务器端后处理分页。 - * @example - * ```javascript - * editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak - * ``` + /** + * 分页功能插件 + * @file + * @since 1.2.6.1 */ + UE.plugins["pagebreak"] = function () { + var me = this, + notBreakTags = ["td"]; + me.setOpt("pageBreakTag", "_ueditor_page_break_tag_"); - me.commands["pagebreak"] = { - execCommand: function() { - var range = me.selection.getRange(), - hr = me.document.createElement("hr"); - domUtils.setAttributes(hr, { - class: "pagebreak", - noshade: "noshade", - size: "5" - }); - domUtils.unSelectable(hr); - //table单独处理 - var node = domUtils.findParentByTagName( - range.startContainer, - notBreakTags, - true - ), - parents = [], - pN; - if (node) { - switch (node.tagName) { - case "TD": - pN = node.parentNode; - if (!pN.previousSibling) { - var table = domUtils.findParentByTagName(pN, "table"); - // var tableWrapDiv = table.parentNode; - // if(tableWrapDiv && tableWrapDiv.nodeType == 1 - // && tableWrapDiv.tagName == 'DIV' - // && tableWrapDiv.getAttribute('dropdrag') - // ){ - // domUtils.remove(tableWrapDiv,true); - // } - table.parentNode.insertBefore(hr, table); - parents = domUtils.findParents(hr, true); - } else { - pN.parentNode.insertBefore(hr, pN); - parents = domUtils.findParents(hr); + function fillNode(node) { + if (domUtils.isEmptyBlock(node)) { + var firstChild = node.firstChild, + tmpNode; + + while ( + firstChild && + firstChild.nodeType == 1 && + domUtils.isEmptyBlock(firstChild) + ) { + tmpNode = firstChild; + firstChild = firstChild.firstChild; + } + !tmpNode && (tmpNode = node); + domUtils.fillNode(me.document, tmpNode); } - pN = parents[1]; - if (hr !== pN) { - domUtils.breakParent(hr, pN); + } + + //分页符样式添加 + + me.ready(function () { + utils.cssRule( + "pagebreak", + ".pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}", + me.document + ); + }); + + function isHr(node) { + return ( + node && + node.nodeType == 1 && + node.tagName == "HR" && + node.className == "pagebreak" + ); + } + + me.addInputRule(function (root) { + root.traversal(function (node) { + if (node.type == "text" && node.data == me.options.pageBreakTag) { + var hr = UE.uNode.createElement( + '
    ' + ); + node.parentNode.insertBefore(hr, node); + node.parentNode.removeChild(node); + } + }); + }); + me.addOutputRule(function (node) { + utils.each(node.getNodesByTagName("hr"), function (n) { + if (n.getAttr("class") == "pagebreak") { + var txt = UE.uNode.createText(me.options.pageBreakTag); + n.parentNode.insertBefore(txt, n); + n.parentNode.removeChild(n); + } + }); + }); + + /** + * 插入分页符 + * @command pagebreak + * @method execCommand + * @param { String } cmd 命令字符串 + * @remind 在表格中插入分页符会把表格切分成两部分 + * @remind 获取编辑器内的数据时, 编辑器会把分页符转换成“_ueditor_page_break_tag_”字符串, + * 以便于提交数据到服务器端后处理分页。 + * @example + * ```javascript + * editor.execCommand( 'pagebreak'); //插入一个hr标签,带有样式类名pagebreak + * ``` + */ + + me.commands["pagebreak"] = { + execCommand: function () { + var range = me.selection.getRange(), + hr = me.document.createElement("hr"); + domUtils.setAttributes(hr, { + class: "pagebreak", + noshade: "noshade", + size: "5" + }); + domUtils.unSelectable(hr); + //table单独处理 + var node = domUtils.findParentByTagName( + range.startContainer, + notBreakTags, + true + ), + parents = [], + pN; + if (node) { + switch (node.tagName) { + case "TD": + pN = node.parentNode; + if (!pN.previousSibling) { + var table = domUtils.findParentByTagName(pN, "table"); + // var tableWrapDiv = table.parentNode; + // if(tableWrapDiv && tableWrapDiv.nodeType == 1 + // && tableWrapDiv.tagName == 'DIV' + // && tableWrapDiv.getAttribute('dropdrag') + // ){ + // domUtils.remove(tableWrapDiv,true); + // } + table.parentNode.insertBefore(hr, table); + parents = domUtils.findParents(hr, true); + } else { + pN.parentNode.insertBefore(hr, pN); + parents = domUtils.findParents(hr); + } + pN = parents[1]; + if (hr !== pN) { + domUtils.breakParent(hr, pN); + } + //table要重写绑定一下拖拽 + me.fireEvent("afteradjusttable", me.document); + } + } else { + if (!range.collapsed) { + range.deleteContents(); + var start = range.startContainer; + while ( + !domUtils.isBody(start) && + domUtils.isBlockElm(start) && + domUtils.isEmptyNode(start) + ) { + range.setStartBefore(start).collapse(true); + domUtils.remove(start); + start = range.startContainer; + } + } + range.insertNode(hr); + + var pN = hr.parentNode, + nextNode; + while (!domUtils.isBody(pN)) { + domUtils.breakParent(hr, pN); + nextNode = hr.nextSibling; + if (nextNode && domUtils.isEmptyBlock(nextNode)) { + domUtils.remove(nextNode); + } + pN = hr.parentNode; + } + nextNode = hr.nextSibling; + var pre = hr.previousSibling; + if (isHr(pre)) { + domUtils.remove(pre); + } else { + pre && fillNode(pre); + } + + if (!nextNode) { + var p = me.document.createElement("p"); + + hr.parentNode.appendChild(p); + domUtils.fillNode(me.document, p); + range.setStart(p, 0).collapse(true); + } else { + if (isHr(nextNode)) { + domUtils.remove(nextNode); + } else { + fillNode(nextNode); + } + range.setEndAfter(hr).collapse(false); + } + + range.select(true); + } } - //table要重写绑定一下拖拽 - me.fireEvent("afteradjusttable", me.document); - } - } else { - if (!range.collapsed) { - range.deleteContents(); - var start = range.startContainer; - while ( - !domUtils.isBody(start) && - domUtils.isBlockElm(start) && - domUtils.isEmptyNode(start) - ) { - range.setStartBefore(start).collapse(true); - domUtils.remove(start); - start = range.startContainer; - } - } - range.insertNode(hr); - - var pN = hr.parentNode, - nextNode; - while (!domUtils.isBody(pN)) { - domUtils.breakParent(hr, pN); - nextNode = hr.nextSibling; - if (nextNode && domUtils.isEmptyBlock(nextNode)) { - domUtils.remove(nextNode); - } - pN = hr.parentNode; - } - nextNode = hr.nextSibling; - var pre = hr.previousSibling; - if (isHr(pre)) { - domUtils.remove(pre); - } else { - pre && fillNode(pre); - } - - if (!nextNode) { - var p = me.document.createElement("p"); - - hr.parentNode.appendChild(p); - domUtils.fillNode(me.document, p); - range.setStart(p, 0).collapse(true); - } else { - if (isHr(nextNode)) { - domUtils.remove(nextNode); - } else { - fillNode(nextNode); - } - range.setEndAfter(hr).collapse(false); - } - - range.select(true); - } - } - }; -}; + }; + }; // plugins/wordimage.js @@ -15529,719 +18807,725 @@ UE.plugins["pagebreak"] = function() { ///commandsTitle 本地图片引导上传 ///commandsDialog dialogs\wordimage -UE.plugin.register("wordimage", function() { - var me = this, - images = []; + UE.plugin.register("wordimage", function () { + var me = this, + images = []; - this.addListener("click", function (type, evt) { - var el = evt.target || evt.srcElement; - if ('IMG' == el.tagName && el.getAttribute('data-word-image')) { - me.ui._dialogs.wordimageDialog && me.ui._dialogs.wordimageDialog.open(); - } - }); - - return { - commands: { - wordimage: { - execCommand: function() { - var images = domUtils.getElementsByTagName(me.body, "img"); - var urlList = []; - for (var i = 0, ci; (ci = images[i++]); ) { - var url = ci.getAttribute("data-word-image"); - url && urlList.push(url); - } - return urlList; - }, - queryCommandState: function() { - images = domUtils.getElementsByTagName(me.body, "img"); - for (var i = 0, ci; (ci = images[i++]); ) { - if (ci.getAttribute("data-word-image")) { - return 1; + this.addListener("click", function (type, evt) { + var el = evt.target || evt.srcElement; + if ('IMG' == el.tagName && el.getAttribute('data-word-image')) { + me.ui._dialogs.wordimageDialog && me.ui._dialogs.wordimageDialog.open(); } - } - return -1; - }, - notNeedUndo: true - } - }, - inputRule: function(root) { - utils.each(root.getNodesByTagName("img"), function(img) { - var attrs = img.attrs, - flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43, - opt = me.options, - src = opt.UEDITOR_HOME_URL + "themes/default/images/spacer.gif"; - if (attrs["src"] && /^(?:(file:\/+))/.test(attrs["src"])) { - img.setAttr({ - width: attrs.width, - height: attrs.height, - alt: attrs.alt, - 'data-word-image': attrs.src, - src: src, - style: - "background:url(" + - (flag - ? opt.themePath + opt.theme + "/images/word.gif" - : opt.langPath + opt.lang + "/images/localimage.png") + - ") no-repeat center center;border:1px solid #ddd" - }); - } - }); - } - }; -}); + }); + + return { + commands: { + wordimage: { + execCommand: function () { + var images = domUtils.getElementsByTagName(me.body, "img"); + var urlList = []; + for (var i = 0, ci; (ci = images[i++]);) { + var url = ci.getAttribute("data-word-image"); + url && urlList.push(url); + } + return urlList; + }, + queryCommandState: function () { + images = domUtils.getElementsByTagName(me.body, "img"); + for (var i = 0, ci; (ci = images[i++]);) { + if (ci.getAttribute("data-word-image")) { + return 1; + } + } + return -1; + }, + notNeedUndo: true + } + }, + inputRule: function (root) { + utils.each(root.getNodesByTagName("img"), function (img) { + var attrs = img.attrs, + flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43, + opt = me.options, + src = opt.UEDITOR_HOME_URL + "themes/default/images/spacer.gif"; + if (attrs["src"] && /^(?:(file:\/+))/.test(attrs["src"])) { + img.setAttr({ + width: attrs.width, + height: attrs.height, + alt: attrs.alt, + 'data-word-image': attrs.src, + src: src, + style: + "background:url(" + + (flag + ? opt.themePath + opt.theme + "/images/word.gif" + : opt.langPath + opt.lang + "/images/localimage.png") + + ") no-repeat center center;border:1px solid #ddd" + }); + } + }); + } + }; + }); // plugins/autosave.js -UE.plugin.register("autosave", function () { - var me = this, saveKey = null; + UE.plugin.register("autosave", function () { + var me = this, saveKey = null; - function save(editor) { - var saveData; + function save(editor) { + var saveData; - if (!editor.hasContents()) { - //这里不能调用命令来删除, 会造成事件死循环 - saveKey && me.removePreferences(saveKey); - return; - } + if (!editor.hasContents()) { + //这里不能调用命令来删除, 会造成事件死循环 + saveKey && me.removePreferences(saveKey); + return; + } - editor._autoSaveTimer = null; + editor._autoSaveTimer = null; - saveData = me.body.innerHTML; + saveData = me.body.innerHTML; - if ( - editor.fireEvent("beforeautosave", { + if ( + editor.fireEvent("beforeautosave", { + content: saveData + }) === false + ) { + return; + } + + // console.log('autosave', saveKey, saveData); + me.setPreferences(saveKey, saveData); + + editor.fireEvent("afterautosave", { content: saveData - }) === false - ) { - return; + }); } - // console.log('autosave', saveKey, saveData); - me.setPreferences(saveKey, saveData); - - editor.fireEvent("afterautosave", { - content: saveData - }); - } - - return { - defaultOptions: { - autoSaveEnable: true, - autoSaveRestore: false, - autoSaveKey: null, - }, - bindEvents: { - ready: function () { - saveKey = me.getOpt('autoSaveKey'); - if (!saveKey) { - var _suffix = "_DraftsData", key = null; - - if (me.key) { - key = me.key + _suffix; - } else { - key = (me.container.parentNode.id || "ue-common") + _suffix; - } - saveKey = (location.protocol + location.host + location.pathname).replace( - /[.:\/]/g, - "_" - ) + key; - } - if (me.getOpt('autoSaveRestore')) { - var data = me.getPreferences(saveKey); - // console.log('saveKey', saveKey, data); - if (data) { - me.body.innerHTML = data; - me.fireEvent('showmessage',{ - type:'info', - content:me.getLang('autosave').autoRestoreTip - }) - } - } - // console.log('saveKey', saveKey); + return { + defaultOptions: { + autoSaveEnable: true, + autoSaveRestore: false, + autoSaveKey: null, }, - beforesubmit: function(){ - if (!me.getOpt("autoSaveEnable") || !saveKey) { - return; + bindEvents: { + ready: function () { + saveKey = me.getOpt('autoSaveKey'); + if (!saveKey) { + var _suffix = "_DraftsData", key = null; + + if (me.key) { + key = me.key + _suffix; + } else { + key = (me.container.parentNode.id || "ue-common") + _suffix; + } + saveKey = (location.protocol + location.host + location.pathname).replace( + /[.:\/]/g, + "_" + ) + key; + } + if (me.getOpt('autoSaveRestore')) { + var data = me.getPreferences(saveKey); + // console.log('saveKey', saveKey, data); + if (data) { + me.body.innerHTML = data; + me.fireEvent('showmessage', { + type: 'info', + content: me.getLang('autosave').autoRestoreTip + }) + } + } + // console.log('saveKey', saveKey); + }, + beforesubmit: function () { + if (!me.getOpt("autoSaveEnable") || !saveKey) { + return; + } + me.execCommand('clear_auto_save_content'); + }, + contentchange: function () { + if (!me.isReady) { + return; + } + if (!me.getOpt("autoSaveEnable") || !saveKey) { + return; + } + + if (me._autoSaveTimer) { + window.clearTimeout(me._autoSaveTimer); + } + + me._autoSaveTimer = window.setTimeout(function () { + save(me); + }, 1000); } - me.execCommand('clear_auto_save_content'); }, - contentchange: function () { - if(!me.isReady){ - return; - } - if (!me.getOpt("autoSaveEnable") || !saveKey) { - return; - } + commands: { + clear_auto_save_content: { + execCommand: function (cmd, name) { + if (saveKey && me.getPreferences(saveKey)) { + me.removePreferences(saveKey); + } + }, + notNeedUndo: true, + ignoreContentChange: true + }, - if (me._autoSaveTimer) { - window.clearTimeout(me._autoSaveTimer); - } + set_auto_save_content: { + execCommand: function (cmd, name) { + save(me); + }, + notNeedUndo: true, + ignoreContentChange: true + }, - me._autoSaveTimer = window.setTimeout(function () { - save(me); - }, 1000); + get_auto_save_content: { + execCommand: function (cmd, name) { + return me.getPreferences(saveKey) || ""; + }, + notNeedUndo: true, + ignoreContentChange: true + }, + + auto_save_restore: { + execCommand: function (cmd, name) { + if (saveKey) { + me.body.innerHTML = + me.getPreferences(saveKey) || "

    " + domUtils.fillHtml + "

    "; + me.focus(true); + } + }, + queryCommandState: function () { + return saveKey ? (me.getPreferences(saveKey) === null ? -1 : 0) : -1; + }, + notNeedUndo: true, + ignoreContentChange: true + } } - }, - commands: { - clear_auto_save_content: { - execCommand: function (cmd, name) { - if (saveKey && me.getPreferences(saveKey)) { - me.removePreferences(saveKey); - } - }, - notNeedUndo: true, - ignoreContentChange: true - }, - - set_auto_save_content: { - execCommand: function (cmd, name) { - save(me); - }, - notNeedUndo: true, - ignoreContentChange: true - }, - - get_auto_save_content: { - execCommand: function (cmd, name) { - return me.getPreferences(saveKey) || ""; - }, - notNeedUndo: true, - ignoreContentChange: true - }, - - auto_save_restore: { - execCommand: function (cmd, name) { - if (saveKey) { - me.body.innerHTML = - me.getPreferences(saveKey) || "

    " + domUtils.fillHtml + "

    "; - me.focus(true); - } - }, - queryCommandState: function () { - return saveKey ? (me.getPreferences(saveKey) === null ? -1 : 0) : -1; - }, - notNeedUndo: true, - ignoreContentChange: true - } - } - }; -}); + }; + }); // plugins/formula.js -UE.plugin.register("formula", function () { - var me = this, images = []; + UE.plugin.register("formula", function () { + var me = this, images = []; - return { - commands: { - formula: { - execCommand: function (cmdName, value) { - var range = me.selection.getRange(), - img = range.getClosedNode(); + return { + commands: { + formula: { + execCommand: function (cmdName, value) { + var range = me.selection.getRange(), + img = range.getClosedNode(); - value = encodeURIComponent(value); - var formulaConfig = me.getOpt('formulaConfig'); - var src = formulaConfig.imageUrlTemplate.replace(/\{\}/, value); + value = encodeURIComponent(value); + var formulaConfig = me.getOpt('formulaConfig'); + var src = formulaConfig.imageUrlTemplate.replace(/\{\}/, value); - if (img) { - img.setAttribute("src", src); - } else { - me.execCommand("insertHtml", ''); - } - }, - } - }, - }; -}); + if (img) { + img.setAttribute("src", src); + } else { + me.execCommand("insertHtml", ''); + } + }, + } + }, + }; + }); // plugins/dragdrop.js -UE.plugins["dragdrop"] = function() { - var me = this; - me.ready(function() { - domUtils.on(this.body, "dragend", function() { - var rng = me.selection.getRange(); - var node = rng.getClosedNode() || me.selection.getStart(); + UE.plugins["dragdrop"] = function () { + var me = this; + me.ready(function () { + domUtils.on(this.body, "dragend", function () { + var rng = me.selection.getRange(); + var node = rng.getClosedNode() || me.selection.getStart(); - if (node && node.tagName == "IMG") { - var pre = node.previousSibling, - next; - while ((next = node.nextSibling)) { - if ( - next.nodeType == 1 && - next.tagName == "SPAN" && - !next.firstChild - ) { - domUtils.remove(next); - } else { - break; - } - } + if (node && node.tagName == "IMG") { + var pre = node.previousSibling, + next; + while ((next = node.nextSibling)) { + if ( + next.nodeType == 1 && + next.tagName == "SPAN" && + !next.firstChild + ) { + domUtils.remove(next); + } else { + break; + } + } - if ( - ((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre)) || !pre) && - (!next || (next && !domUtils.isEmptyBlock(next))) - ) { - if (pre && pre.tagName == "P" && !domUtils.isEmptyBlock(pre)) { - pre.appendChild(node); - domUtils.moveChild(next, pre); - domUtils.remove(next); - } else if ( - next && - next.tagName == "P" && - !domUtils.isEmptyBlock(next) - ) { - next.insertBefore(node, next.firstChild); - } + if ( + ((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre)) || !pre) && + (!next || (next && !domUtils.isEmptyBlock(next))) + ) { + if (pre && pre.tagName == "P" && !domUtils.isEmptyBlock(pre)) { + pre.appendChild(node); + domUtils.moveChild(next, pre); + domUtils.remove(next); + } else if ( + next && + next.tagName == "P" && + !domUtils.isEmptyBlock(next) + ) { + next.insertBefore(node, next.firstChild); + } - if (pre && pre.tagName == "P" && domUtils.isEmptyBlock(pre)) { - domUtils.remove(pre); - } - if (next && next.tagName == "P" && domUtils.isEmptyBlock(next)) { - domUtils.remove(next); - } - rng.selectNode(node).select(); - me.fireEvent("saveScene"); - } - } - }); - }); - me.addListener("keyup", function(type, evt) { - var keyCode = evt.keyCode || evt.which; - if (keyCode == 13) { - var rng = me.selection.getRange(), - node; - if ( - (node = domUtils.findParentByTagName(rng.startContainer, "p", true)) - ) { - if (domUtils.getComputedStyle(node, "text-align") == "center") { - domUtils.removeStyle(node, "text-align"); - } - } - } - }); -}; + if (pre && pre.tagName == "P" && domUtils.isEmptyBlock(pre)) { + domUtils.remove(pre); + } + if (next && next.tagName == "P" && domUtils.isEmptyBlock(next)) { + domUtils.remove(next); + } + rng.selectNode(node).select(); + me.fireEvent("saveScene"); + } + } + }); + }); + me.addListener("keyup", function (type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) { + var rng = me.selection.getRange(), + node; + if ( + (node = domUtils.findParentByTagName(rng.startContainer, "p", true)) + ) { + if (domUtils.getComputedStyle(node, "text-align") == "center") { + domUtils.removeStyle(node, "text-align"); + } + } + } + }); + }; // plugins/undo.js -/** - * undo redo - * @file - * @since 1.2.6.1 - */ + /** + * undo redo + * @file + * @since 1.2.6.1 + */ -/** - * 撤销上一次执行的命令 - * @command undo - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'undo' ); - * ``` - */ + /** + * 撤销上一次执行的命令 + * @command undo + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'undo' ); + * ``` + */ -/** - * 重做上一次执行的命令 - * @command redo - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.execCommand( 'redo' ); - * ``` - */ + /** + * 重做上一次执行的命令 + * @command redo + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'redo' ); + * ``` + */ -UE.plugins["undo"] = function() { - var saveSceneTimer; - var me = this, - maxUndoCount = me.options.maxUndoCount || 20, - maxInputCount = me.options.maxInputCount || 20, - fillchar = new RegExp(domUtils.fillChar + "|", "gi"); // ie会产生多余的 - var noNeedFillCharTags = { - ol: 1, - ul: 1, - table: 1, - tbody: 1, - tr: 1, - body: 1 - }; - var orgState = me.options.autoClearEmptyNode; - function compareAddr(indexA, indexB) { - if (indexA.length != indexB.length) return 0; - for (var i = 0, l = indexA.length; i < l; i++) { - if (indexA[i] != indexB[i]) return 0; - } - return 1; - } + UE.plugins["undo"] = function () { + var saveSceneTimer; + var me = this, + maxUndoCount = me.options.maxUndoCount || 20, + maxInputCount = me.options.maxInputCount || 20, + fillchar = new RegExp(domUtils.fillChar + "|", "gi"); // ie会产生多余的 + var noNeedFillCharTags = { + ol: 1, + ul: 1, + table: 1, + tbody: 1, + tr: 1, + body: 1 + }; + var orgState = me.options.autoClearEmptyNode; - function compareRangeAddress(rngAddrA, rngAddrB) { - if (rngAddrA.collapsed != rngAddrB.collapsed) { - return 0; - } - if ( - !compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || - !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress) - ) { - return 0; - } - return 1; - } - - function UndoManager() { - this.list = []; - this.index = 0; - this.hasUndo = false; - this.hasRedo = false; - this.undo = function() { - if (this.hasUndo) { - if (!this.list[this.index - 1] && this.list.length == 1) { - this.reset(); - return; - } - while ( - this.list[this.index].content == this.list[this.index - 1].content - ) { - this.index--; - if (this.index == 0) { - return this.restore(0); - } - } - this.restore(--this.index); - } - }; - this.redo = function() { - if (this.hasRedo) { - while ( - this.list[this.index].content == this.list[this.index + 1].content - ) { - this.index++; - if (this.index == this.list.length - 1) { - return this.restore(this.index); - } - } - this.restore(++this.index); - } - }; - - this.restore = function() { - var me = this.editor; - var scene = this.list[this.index]; - var root = UE.htmlparser(scene.content.replace(fillchar, "")); - me.options.autoClearEmptyNode = false; - me.filterInputRule(root); - me.options.autoClearEmptyNode = orgState; - //trace:873 - //去掉展位符 - me.document.body.innerHTML = root.toHtml(); - me.fireEvent("afterscencerestore"); - //处理undo后空格不展位的问题 - if (browser.ie) { - utils.each( - domUtils.getElementsByTagName(me.document, "td th caption p"), - function(node) { - if (domUtils.isEmptyNode(node)) { - domUtils.fillNode(me.document, node); + function compareAddr(indexA, indexB) { + if (indexA.length != indexB.length) return 0; + for (var i = 0, l = indexA.length; i < l; i++) { + if (indexA[i] != indexB[i]) return 0; } - } - ); - } - - try { - var rng = new dom.Range(me.document).moveToAddress(scene.address); - rng.select( - noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()] - ); - } catch (e) {} - - this.update(); - this.clearKey(); - //不能把自己reset了 - me.fireEvent("reset", true); - }; - - this.getScene = function() { - var me = this.editor; - var rng = me.selection.getRange(), - rngAddress = rng.createAddress(false, true); - me.fireEvent("beforegetscene"); - var root = UE.htmlparser(me.body.innerHTML); - me.options.autoClearEmptyNode = false; - me.filterOutputRule(root); - me.options.autoClearEmptyNode = orgState; - var cont = root.toHtml(); - //trace:3461 - //这个会引起回退时导致空格丢失的情况 - // browser.ie && (cont = cont.replace(/> <').replace(/\s*\s*/g, '>')); - me.fireEvent("aftergetscene"); - - return { - address: rngAddress, - content: cont - }; - }; - this.save = function(notCompareRange, notSetCursor) { - - clearTimeout(saveSceneTimer); - var currentScene = this.getScene(notSetCursor), - lastScene = this.list[this.index]; - if (!lastScene || ( lastScene && lastScene.content != currentScene.content )) { - // 使用异步避免直接在事件中取值滞后一个字符 - setTimeout(function(){ - me.trigger("contentchange"); - },0); - } - //内容相同位置相同不存 - if ( - lastScene && - lastScene.content == currentScene.content && - (notCompareRange - ? 1 - : compareRangeAddress(lastScene.address, currentScene.address)) - ) { - return; - } - this.list = this.list.slice(0, this.index + 1); - this.list.push(currentScene); - //如果大于最大数量了,就把最前的剔除 - if (this.list.length > maxUndoCount) { - this.list.shift(); - } - this.index = this.list.length - 1; - this.clearKey(); - //跟新undo/redo状态 - this.update(); - }; - this.update = function() { - this.hasRedo = !!this.list[this.index + 1]; - this.hasUndo = !!this.list[this.index - 1]; - }; - this.reset = function() { - this.list = []; - this.index = 0; - this.hasUndo = false; - this.hasRedo = false; - this.clearKey(); - }; - this.clearKey = function() { - keycont = 0; - lastKeyCode = null; - }; - } - - me.undoManger = new UndoManager(); - me.undoManger.editor = me; - function saveScene() { - this.undoManger.save(); - } - - me.addListener("saveScene", function() { - var args = Array.prototype.splice.call(arguments, 1); - this.undoManger.save.apply(this.undoManger, args); - }); - - // me.addListener('beforeexeccommand', saveScene); - // me.addListener('afterexeccommand', saveScene); - - me.addListener("reset", function(type, exclude) { - if (!exclude) { - this.undoManger.reset(); - } - }); - me.commands["redo"] = me.commands["undo"] = { - execCommand: function(cmdName) { - this.undoManger[cmdName](); - }, - queryCommandState: function(cmdName) { - return this.undoManger[ - "has" + (cmdName.toLowerCase() == "undo" ? "Undo" : "Redo") - ] - ? 0 - : -1; - }, - notNeedUndo: 1 - }; - - var keys = { - // /*Backspace*/ 8:1, /*Delete*/ 46:1, - /*Shift*/ 16: 1, - /*Ctrl*/ 17: 1, - /*Alt*/ 18: 1, - 37: 1, - 38: 1, - 39: 1, - 40: 1 - }, - keycont = 0, - lastKeyCode; - //输入法状态下不计算字符数 - var inputType = false; - me.addListener("ready", function() { - domUtils.on(this.body, "compositionstart", function() { - inputType = true; - }); - domUtils.on(this.body, "compositionend", function() { - inputType = false; - }); - }); - //快捷键 - me.addshortcutkey({ - Undo: "ctrl+90", //undo - Redo: "ctrl+89" //redo - }); - var isCollapsed = true; - me.addListener("keydown", function(type, evt) { - var me = this; - var keyCode = evt.keyCode || evt.which; - if ( - !keys[keyCode] && - !evt.ctrlKey && - !evt.metaKey && - !evt.shiftKey && - !evt.altKey - ) { - if (inputType) return; - - if (!me.selection.getRange().collapsed) { - me.undoManger.save(false, true); - isCollapsed = false; - return; - } - if (me.undoManger.list.length === 0) { - me.undoManger.save(true); - } - clearTimeout(saveSceneTimer); - function save(cont) { - cont.undoManger.save(false, true); - cont.fireEvent("selectionchange"); - } - saveSceneTimer = setTimeout(function() { - if (inputType) { - var interalTimer = setInterval(function() { - if (!inputType) { - save(me); - clearInterval(interalTimer); - } - }, 300); - return; + return 1; } - save(me); - }, 200); - lastKeyCode = keyCode; - keycont++; - if (keycont >= maxInputCount) { - save(me); - } - } - }); - me.addListener("keyup", function(type, evt) { - var keyCode = evt.keyCode || evt.which; - if ( - !keys[keyCode] && - !evt.ctrlKey && - !evt.metaKey && - !evt.shiftKey && - !evt.altKey - ) { - if (inputType) return; - if (!isCollapsed) { - this.undoManger.save(false, true); - isCollapsed = true; - } - } - }); - //扩展实例,添加关闭和开启命令undo - me.stopCmdUndo = function() { - me.__hasEnterExecCommand = true; - }; - me.startCmdUndo = function() { - me.__hasEnterExecCommand = false; - }; -}; + function compareRangeAddress(rngAddrA, rngAddrB) { + if (rngAddrA.collapsed != rngAddrB.collapsed) { + return 0; + } + if ( + !compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || + !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress) + ) { + return 0; + } + return 1; + } + + function UndoManager() { + this.list = []; + this.index = 0; + this.hasUndo = false; + this.hasRedo = false; + this.undo = function () { + if (this.hasUndo) { + if (!this.list[this.index - 1] && this.list.length == 1) { + this.reset(); + return; + } + while ( + this.list[this.index].content == this.list[this.index - 1].content + ) { + this.index--; + if (this.index == 0) { + return this.restore(0); + } + } + this.restore(--this.index); + } + }; + this.redo = function () { + if (this.hasRedo) { + while ( + this.list[this.index].content == this.list[this.index + 1].content + ) { + this.index++; + if (this.index == this.list.length - 1) { + return this.restore(this.index); + } + } + this.restore(++this.index); + } + }; + + this.restore = function () { + var me = this.editor; + var scene = this.list[this.index]; + var root = UE.htmlparser(scene.content.replace(fillchar, "")); + me.options.autoClearEmptyNode = false; + me.filterInputRule(root); + me.options.autoClearEmptyNode = orgState; + //trace:873 + //去掉展位符 + me.document.body.innerHTML = root.toHtml(); + me.fireEvent("afterscencerestore"); + //处理undo后空格不展位的问题 + if (browser.ie) { + utils.each( + domUtils.getElementsByTagName(me.document, "td th caption p"), + function (node) { + if (domUtils.isEmptyNode(node)) { + domUtils.fillNode(me.document, node); + } + } + ); + } + + try { + var rng = new dom.Range(me.document).moveToAddress(scene.address); + rng.select( + noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()] + ); + } catch (e) { + } + + this.update(); + this.clearKey(); + //不能把自己reset了 + me.fireEvent("reset", true); + }; + + this.getScene = function () { + var me = this.editor; + var rng = me.selection.getRange(), + rngAddress = rng.createAddress(false, true); + me.fireEvent("beforegetscene"); + var root = UE.htmlparser(me.body.innerHTML); + me.options.autoClearEmptyNode = false; + me.filterOutputRule(root); + me.options.autoClearEmptyNode = orgState; + var cont = root.toHtml(); + //trace:3461 + //这个会引起回退时导致空格丢失的情况 + // browser.ie && (cont = cont.replace(/> <').replace(/\s*\s*/g, '>')); + me.fireEvent("aftergetscene"); + + return { + address: rngAddress, + content: cont + }; + }; + this.save = function (notCompareRange, notSetCursor) { + + clearTimeout(saveSceneTimer); + var currentScene = this.getScene(notSetCursor), + lastScene = this.list[this.index]; + if (!lastScene || (lastScene && lastScene.content != currentScene.content)) { + // 使用异步避免直接在事件中取值滞后一个字符 + setTimeout(function () { + me.trigger("contentchange"); + }, 0); + } + //内容相同位置相同不存 + if ( + lastScene && + lastScene.content == currentScene.content && + (notCompareRange + ? 1 + : compareRangeAddress(lastScene.address, currentScene.address)) + ) { + return; + } + this.list = this.list.slice(0, this.index + 1); + this.list.push(currentScene); + //如果大于最大数量了,就把最前的剔除 + if (this.list.length > maxUndoCount) { + this.list.shift(); + } + this.index = this.list.length - 1; + this.clearKey(); + //跟新undo/redo状态 + this.update(); + }; + this.update = function () { + this.hasRedo = !!this.list[this.index + 1]; + this.hasUndo = !!this.list[this.index - 1]; + }; + this.reset = function () { + this.list = []; + this.index = 0; + this.hasUndo = false; + this.hasRedo = false; + this.clearKey(); + }; + this.clearKey = function () { + keycont = 0; + lastKeyCode = null; + }; + } + + me.undoManger = new UndoManager(); + me.undoManger.editor = me; + + function saveScene() { + this.undoManger.save(); + } + + me.addListener("saveScene", function () { + var args = Array.prototype.splice.call(arguments, 1); + this.undoManger.save.apply(this.undoManger, args); + }); + + // me.addListener('beforeexeccommand', saveScene); + // me.addListener('afterexeccommand', saveScene); + + me.addListener("reset", function (type, exclude) { + if (!exclude) { + this.undoManger.reset(); + } + }); + me.commands["redo"] = me.commands["undo"] = { + execCommand: function (cmdName) { + this.undoManger[cmdName](); + }, + queryCommandState: function (cmdName) { + return this.undoManger[ + "has" + (cmdName.toLowerCase() == "undo" ? "Undo" : "Redo") + ] + ? 0 + : -1; + }, + notNeedUndo: 1 + }; + + var keys = { + // /*Backspace*/ 8:1, /*Delete*/ 46:1, + /*Shift*/ 16: 1, + /*Ctrl*/ 17: 1, + /*Alt*/ 18: 1, + 37: 1, + 38: 1, + 39: 1, + 40: 1 + }, + keycont = 0, + lastKeyCode; + //输入法状态下不计算字符数 + var inputType = false; + me.addListener("ready", function () { + domUtils.on(this.body, "compositionstart", function () { + inputType = true; + }); + domUtils.on(this.body, "compositionend", function () { + inputType = false; + }); + }); + //快捷键 + me.addshortcutkey({ + Undo: "ctrl+90", //undo + Redo: "ctrl+89" //redo + }); + var isCollapsed = true; + me.addListener("keyup", function (type, evt) { + + var me = this; + var keyCode = evt.keyCode || evt.which; + if ( + !keys[keyCode] && + !evt.ctrlKey && + !evt.metaKey && + !evt.shiftKey && + !evt.altKey + ) { + if (inputType) return; + + if (!me.selection.getRange().collapsed) { + me.undoManger.save(false, true); + isCollapsed = false; + return; + } + if (me.undoManger.list.length === 0) { + me.undoManger.save(true); + } + clearTimeout(saveSceneTimer); + + function save(cont) { + cont.undoManger.save(false, true); + cont.fireEvent("selectionchange"); + } + + saveSceneTimer = setTimeout(function () { + if (inputType) { + var intervalTimer = setInterval(function () { + if (!inputType) { + save(me); + clearInterval(intervalTimer); + } + }, 300); + return; + } + save(me); + }, 200); + + lastKeyCode = keyCode; + keycont++; + if (keycont >= maxInputCount) { + save(me); + } + } + }); + me.addListener("keyup", function (type, evt) { + var keyCode = evt.keyCode || evt.which; + if ( + !keys[keyCode] && + !evt.ctrlKey && + !evt.metaKey && + !evt.shiftKey && + !evt.altKey + ) { + if (inputType) return; + if (!isCollapsed) { + this.undoManger.save(false, true); + isCollapsed = true; + } + } + }); + //扩展实例,添加关闭和开启命令undo + me.stopCmdUndo = function () { + me.__hasEnterExecCommand = true; + }; + me.startCmdUndo = function () { + me.__hasEnterExecCommand = false; + }; + }; // plugins/copy.js -UE.plugin.register("copy", function() { - var me = this; + UE.plugin.register("copy", function () { + var me = this; - function initZeroClipboard() { - ZeroClipboard.config({ - debug: false, - swfPath: - me.options.UEDITOR_HOME_URL + - "third-party/zeroclipboard/ZeroClipboard.swf" - }); + function initZeroClipboard() { + ZeroClipboard.config({ + debug: false, + swfPath: + me.options.UEDITOR_HOME_URL + + "third-party/zeroclipboard/ZeroClipboard.swf" + }); - var client = (me.zeroclipboard = new ZeroClipboard()); + var client = (me.zeroclipboard = new ZeroClipboard()); - // 复制内容 - client.on("copy", function(e) { - var client = e.client, - rng = me.selection.getRange(), - div = document.createElement("div"); + // 复制内容 + client.on("copy", function (e) { + var client = e.client, + rng = me.selection.getRange(), + div = document.createElement("div"); - div.appendChild(rng.cloneContents()); - client.setText(div.innerText || div.textContent); - client.setHtml(div.innerHTML); - rng.select(); - }); - // hover事件传递到target - client.on("mouseover mouseout", function(e) { - var target = e.target; - if (target) { - if (e.type == "mouseover") { - domUtils.addClass(target, "edui-state-hover"); - } else if (e.type == "mouseout") { - domUtils.removeClasses(target, "edui-state-hover"); + div.appendChild(rng.cloneContents()); + client.setText(div.innerText || div.textContent); + client.setHtml(div.innerHTML); + rng.select(); + }); + // hover事件传递到target + client.on("mouseover mouseout", function (e) { + var target = e.target; + if (target) { + if (e.type == "mouseover") { + domUtils.addClass(target, "edui-state-hover"); + } else if (e.type == "mouseout") { + domUtils.removeClasses(target, "edui-state-hover"); + } + } + }); + // flash加载不成功 + client.on("wrongflash noflash", function () { + ZeroClipboard.destroy(); + }); + + // 触发事件 + me.fireEvent("zeroclipboardready", client); } - } - }); - // flash加载不成功 - client.on("wrongflash noflash", function() { - ZeroClipboard.destroy(); - }); - // 触发事件 - me.fireEvent("zeroclipboardready", client); - } - - return { - bindEvents: { - ready: function() { - if (!browser.ie) { - if (window.ZeroClipboard) { - initZeroClipboard(); - } else { - utils.loadFile( - document, - { - src: - me.options.UEDITOR_HOME_URL + - "third-party/zeroclipboard/ZeroClipboard.js", - tag: "script", - type: "text/javascript", - defer: "defer" - }, - function() { - initZeroClipboard(); - } - ); - } - } - } - }, - commands: { - copy: { - execCommand: function(cmd) { - if (!me.document.execCommand("copy")) { - alert(me.getLang("copymsg")); - } - } - } - } - }; -}); + return { + bindEvents: { + ready: function () { + if (!browser.ie) { + if (window.ZeroClipboard) { + initZeroClipboard(); + } else { + utils.loadFile( + document, + { + src: + me.options.UEDITOR_HOME_URL + + "third-party/zeroclipboard/ZeroClipboard.js", + tag: "script", + type: "text/javascript", + defer: "defer" + }, + function () { + initZeroClipboard(); + } + ); + } + } + } + }, + commands: { + copy: { + execCommand: function (cmd) { + if (!me.document.execCommand("copy")) { + alert(me.getLang("copymsg")); + } + } + } + } + }; + }); // plugins/paste.js @@ -16252,2257 +19536,2272 @@ UE.plugin.register("copy", function() { ///commands 粘贴 ///commandsName PastePlain ///commandsTitle 纯文本粘贴模式 -/** - * @description 粘贴 - * @author zhanyi - */ -UE.plugins["paste"] = function() { - function getClipboardData(callback) { - var doc = this.document; - if (doc.getElementById("baidu_pastebin")) { - return; - } - var range = this.selection.getRange(), - bk = range.createBookmark(), - //创建剪贴的容器div - pastebin = doc.createElement("div"); - pastebin.id = "baidu_pastebin"; - // Safari 要求div必须有内容,才能粘贴内容进来 - browser.webkit && - pastebin.appendChild( - doc.createTextNode(domUtils.fillChar + domUtils.fillChar) - ); - doc.body.appendChild(pastebin); - //trace:717 隐藏的span不能得到top - //bk.start.innerHTML = ' '; - bk.start.style.display = ""; - pastebin.style.cssText = - "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" + - //要在现在光标平行的位置加入,否则会出现跳动的问题 - domUtils.getXY(bk.start).y + - "px"; - - range.selectNodeContents(pastebin).select(true); - - setTimeout(function() { - if (browser.webkit) { - for ( - var i = 0, pastebins = doc.querySelectorAll("#baidu_pastebin"), pi; - (pi = pastebins[i++]); - - ) { - if (domUtils.isEmptyNode(pi)) { - domUtils.remove(pi); - } else { - pastebin = pi; - break; - } - } - } - try { - pastebin.parentNode.removeChild(pastebin); - } catch (e) {} - range.moveToBookmark(bk).select(true); - callback(pastebin); - }, 0); - } - - var me = this; - - me.setOpt({ - retainOnlyLabelPasted: false - }); - - var txtContent, htmlContent, address; - - function getPureHtml(html) { - return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function( - a, - b, - tagName, - attrs - ) { - tagName = tagName.toLowerCase(); - if ({ img: 1 }[tagName]) { - return a; - } - attrs = attrs.replace( - /([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, - function(str, atr, val) { - if ( - { - src: 1, - href: 1, - name: 1 - }[atr.toLowerCase()] - ) { - return atr + "=" + val + " "; - } - return ""; - } - ); - if ( - { - span: 1, - div: 1 - }[tagName] - ) { - return ""; - } else { - return "<" + b + tagName + " " + utils.trim(attrs) + ">"; - } - }); - } - function filter(div) { - var html; - if (div.firstChild) { - //去掉cut中添加的边界值 - var nodes = domUtils.getElementsByTagName(div, "span"); - for (var i = 0, ni; (ni = nodes[i++]); ) { - if (ni.id == "_baidu_cut_start" || ni.id == "_baidu_cut_end") { - domUtils.remove(ni); - } - } - - if (browser.webkit) { - var brs = div.querySelectorAll("div br"); - for (var i = 0, bi; (bi = brs[i++]); ) { - var pN = bi.parentNode; - if (pN.tagName == "DIV" && pN.childNodes.length == 1) { - pN.innerHTML = "


    "; - domUtils.remove(pN); - } - } - var divs = div.querySelectorAll("#baidu_pastebin"); - for (var i = 0, di; (di = divs[i++]); ) { - var tmpP = me.document.createElement("p"); - di.parentNode.insertBefore(tmpP, di); - while (di.firstChild) { - tmpP.appendChild(di.firstChild); - } - domUtils.remove(di); - } - - var metas = div.querySelectorAll("meta"); - for (var i = 0, ci; (ci = metas[i++]); ) { - domUtils.remove(ci); - } - - var brs = div.querySelectorAll("br"); - for (i = 0; (ci = brs[i++]); ) { - if (/^apple-/i.test(ci.className)) { - domUtils.remove(ci); - } - } - } - if (browser.gecko) { - var dirtyNodes = div.querySelectorAll("[_moz_dirty]"); - for (i = 0; (ci = dirtyNodes[i++]); ) { - ci.removeAttribute("_moz_dirty"); - } - } - if (!browser.ie) { - var spans = div.querySelectorAll("span.Apple-style-span"); - for (var i = 0, ci; (ci = spans[i++]); ) { - domUtils.remove(ci, true); - } - } - - //ie下使用innerHTML会产生多余的\r\n字符,也会产生 这里过滤掉 - html = div.innerHTML; //.replace(/>(?:(\s| )*?)<'); - - //过滤word粘贴过来的冗余属性 - html = UE.filterWord(html); - //取消了忽略空白的第二个参数,粘贴过来的有些是有空白的,会被套上相关的标签 - var root = UE.htmlparser(html); - //如果给了过滤规则就先进行过滤 - if (me.options.filterRules) { - UE.filterNode(root, me.options.filterRules); - } - //执行默认的处理 - me.filterInputRule(root); - //针对chrome的处理 - if (browser.webkit) { - var br = root.lastChild(); - if (br && br.type == "element" && br.tagName == "br") { - root.removeChild(br); - } - utils.each(me.body.querySelectorAll("div"), function(node) { - if (domUtils.isEmptyBlock(node)) { - domUtils.remove(node, true); - } - }); - } - html = { html: root.toHtml() }; - me.fireEvent("beforepaste", html, root); - //抢了默认的粘贴,那后边的内容就不执行了,比如表格粘贴 - if (!html.html) { - return; - } - root = UE.htmlparser(html.html, true); - //如果开启了纯文本模式 - if (me.queryCommandState("pasteplain") === 1) { - me.execCommand( - "insertHtml", - UE.filterNode(root, me.options.filterTxtRules).toHtml(), - true - ); - } else { - //文本模式 - UE.filterNode(root, me.options.filterTxtRules); - txtContent = root.toHtml(); - //完全模式 - htmlContent = html.html; - - address = me.selection.getRange().createAddress(true); - me.execCommand( - "insertHtml", - me.getOpt("retainOnlyLabelPasted") === true - ? getPureHtml(htmlContent) - : htmlContent, - true - ); - } - me.fireEvent("afterpaste", html); - } - } - - me.addListener("pasteTransfer", function(cmd, plainType) { - if (address && txtContent && htmlContent && txtContent != htmlContent) { - var range = me.selection.getRange(); - range.moveToAddress(address, true); - - if (!range.collapsed) { - while (!domUtils.isBody(range.startContainer)) { - var start = range.startContainer; - if (start.nodeType == 1) { - start = start.childNodes[range.startOffset]; - if (!start) { - range.setStartBefore(range.startContainer); - continue; + /** + * @description 粘贴 + * @author zhanyi + */ + UE.plugins["paste"] = function () { + function getClipboardData(callback) { + var doc = this.document; + if (doc.getElementById("baidu_pastebin")) { + return; } - var pre = start.previousSibling; + var range = this.selection.getRange(), + bk = range.createBookmark(), + //创建剪贴的容器div + pastebin = doc.createElement("div"); + pastebin.id = "baidu_pastebin"; + // Safari 要求div必须有内容,才能粘贴内容进来 + browser.webkit && + pastebin.appendChild( + doc.createTextNode(domUtils.fillChar + domUtils.fillChar) + ); + doc.body.appendChild(pastebin); + //trace:717 隐藏的span不能得到top + //bk.start.innerHTML = ' '; + bk.start.style.display = ""; + pastebin.style.cssText = + "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" + + //要在现在光标平行的位置加入,否则会出现跳动的问题 + domUtils.getXY(bk.start).y + + "px"; - if ( - pre && - pre.nodeType == 3 && - new RegExp("^[\n\r\t " + domUtils.fillChar + "]*$").test( - pre.nodeValue - ) + range.selectNodeContents(pastebin).select(true); + + setTimeout(function () { + if (browser.webkit) { + for ( + var i = 0, pastebins = doc.querySelectorAll("#baidu_pastebin"), pi; + (pi = pastebins[i++]); + ) { + if (domUtils.isEmptyNode(pi)) { + domUtils.remove(pi); + } else { + pastebin = pi; + break; + } + } + } + try { + pastebin.parentNode.removeChild(pastebin); + } catch (e) { + } + range.moveToBookmark(bk).select(true); + callback(pastebin); + }, 0); + } + + var me = this; + + me.setOpt({ + retainOnlyLabelPasted: false + }); + + var txtContent, htmlContent, address; + + function getPureHtml(html) { + return html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function ( + a, + b, + tagName, + attrs ) { - range.setStartBefore(pre); - } - } - if (range.startOffset == 0) { - range.setStartBefore(range.startContainer); - } else { - break; - } + tagName = tagName.toLowerCase(); + if ({img: 1}[tagName]) { + return a; + } + attrs = attrs.replace( + /([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, + function (str, atr, val) { + if ( + { + src: 1, + href: 1, + name: 1 + }[atr.toLowerCase()] + ) { + return atr + "=" + val + " "; + } + return ""; + } + ); + if ( + { + span: 1, + div: 1 + }[tagName] + ) { + return ""; + } else { + return "<" + b + tagName + " " + utils.trim(attrs) + ">"; + } + }); } - while (!domUtils.isBody(range.endContainer)) { - var end = range.endContainer; - if (end.nodeType == 1) { - end = end.childNodes[range.endOffset]; - if (!end) { - range.setEndAfter(range.endContainer); - continue; + + function filter(div) { + var html; + if (div.firstChild) { + //去掉cut中添加的边界值 + var nodes = domUtils.getElementsByTagName(div, "span"); + for (var i = 0, ni; (ni = nodes[i++]);) { + if (ni.id == "_baidu_cut_start" || ni.id == "_baidu_cut_end") { + domUtils.remove(ni); + } + } + + if (browser.webkit) { + var brs = div.querySelectorAll("div br"); + for (var i = 0, bi; (bi = brs[i++]);) { + var pN = bi.parentNode; + if (pN.tagName == "DIV" && pN.childNodes.length == 1) { + pN.innerHTML = "


    "; + domUtils.remove(pN); + } + } + var divs = div.querySelectorAll("#baidu_pastebin"); + for (var i = 0, di; (di = divs[i++]);) { + var tmpP = me.document.createElement("p"); + di.parentNode.insertBefore(tmpP, di); + while (di.firstChild) { + tmpP.appendChild(di.firstChild); + } + domUtils.remove(di); + } + + var metas = div.querySelectorAll("meta"); + for (var i = 0, ci; (ci = metas[i++]);) { + domUtils.remove(ci); + } + + var brs = div.querySelectorAll("br"); + for (i = 0; (ci = brs[i++]);) { + if (/^apple-/i.test(ci.className)) { + domUtils.remove(ci); + } + } + } + if (browser.gecko) { + var dirtyNodes = div.querySelectorAll("[_moz_dirty]"); + for (i = 0; (ci = dirtyNodes[i++]);) { + ci.removeAttribute("_moz_dirty"); + } + } + if (!browser.ie) { + var spans = div.querySelectorAll("span.Apple-style-span"); + for (var i = 0, ci; (ci = spans[i++]);) { + domUtils.remove(ci, true); + } + } + + //ie下使用innerHTML会产生多余的\r\n字符,也会产生 这里过滤掉 + html = div.innerHTML; //.replace(/>(?:(\s| )*?)<'); + + //过滤word粘贴过来的冗余属性 + html = UE.filterWord(html); + //取消了忽略空白的第二个参数,粘贴过来的有些是有空白的,会被套上相关的标签 + var root = UE.htmlparser(html); + //如果给了过滤规则就先进行过滤 + if (me.options.filterRules) { + UE.filterNode(root, me.options.filterRules); + } + //执行默认的处理 + me.filterInputRule(root); + //针对chrome的处理 + if (browser.webkit) { + var br = root.lastChild(); + if (br && br.type == "element" && br.tagName == "br") { + root.removeChild(br); + } + utils.each(me.body.querySelectorAll("div"), function (node) { + if (domUtils.isEmptyBlock(node)) { + domUtils.remove(node, true); + } + }); + } + html = {html: root.toHtml()}; + me.fireEvent("beforepaste", html, root); + //抢了默认的粘贴,那后边的内容就不执行了,比如表格粘贴 + if (!html.html) { + return; + } + root = UE.htmlparser(html.html, true); + //如果开启了纯文本模式 + if (me.queryCommandState("pasteplain") === 1) { + me.execCommand( + "insertHtml", + UE.filterNode(root, me.options.filterTxtRules).toHtml(), + true + ); + } else { + //文本模式 + UE.filterNode(root, me.options.filterTxtRules); + txtContent = root.toHtml(); + //完全模式 + htmlContent = html.html; + + address = me.selection.getRange().createAddress(true); + me.execCommand( + "insertHtml", + me.getOpt("retainOnlyLabelPasted") === true + ? getPureHtml(htmlContent) + : htmlContent, + true + ); + } + me.fireEvent("afterpaste", html); } - var next = end.nextSibling; - if ( - next && - next.nodeType == 3 && - new RegExp("^[\n\r\t" + domUtils.fillChar + "]*$").test( - next.nodeValue - ) - ) { - range.setEndAfter(next); + } + + me.addListener("pasteTransfer", function (cmd, plainType) { + if (address && txtContent && htmlContent && txtContent != htmlContent) { + var range = me.selection.getRange(); + range.moveToAddress(address, true); + + if (!range.collapsed) { + while (!domUtils.isBody(range.startContainer)) { + var start = range.startContainer; + if (start.nodeType == 1) { + start = start.childNodes[range.startOffset]; + if (!start) { + range.setStartBefore(range.startContainer); + continue; + } + var pre = start.previousSibling; + + if ( + pre && + pre.nodeType == 3 && + new RegExp("^[\n\r\t " + domUtils.fillChar + "]*$").test( + pre.nodeValue + ) + ) { + range.setStartBefore(pre); + } + } + if (range.startOffset == 0) { + range.setStartBefore(range.startContainer); + } else { + break; + } + } + while (!domUtils.isBody(range.endContainer)) { + var end = range.endContainer; + if (end.nodeType == 1) { + end = end.childNodes[range.endOffset]; + if (!end) { + range.setEndAfter(range.endContainer); + continue; + } + var next = end.nextSibling; + if ( + next && + next.nodeType == 3 && + new RegExp("^[\n\r\t" + domUtils.fillChar + "]*$").test( + next.nodeValue + ) + ) { + range.setEndAfter(next); + } + } + if ( + range.endOffset == + range.endContainer[ + range.endContainer.nodeType == 3 ? "nodeValue" : "childNodes" + ].length + ) { + range.setEndAfter(range.endContainer); + } else { + break; + } + } + } + + range.deleteContents(); + range.select(true); + me.__hasEnterExecCommand = true; + var html = htmlContent; + if (plainType === 2) { + html = getPureHtml(html); + } else if (plainType) { + html = txtContent; + } + me.execCommand("inserthtml", html, true); + me.__hasEnterExecCommand = false; + var rng = me.selection.getRange(); + while ( + !domUtils.isBody(rng.startContainer) && + !rng.startOffset && + rng.startContainer[ + rng.startContainer.nodeType == 3 ? "nodeValue" : "childNodes" + ].length + ) { + rng.setStartBefore(rng.startContainer); + } + var tmpAddress = rng.createAddress(true); + address.endAddress = tmpAddress.startAddress; } - } - if ( - range.endOffset == - range.endContainer[ - range.endContainer.nodeType == 3 ? "nodeValue" : "childNodes" - ].length - ) { - range.setEndAfter(range.endContainer); - } else { - break; - } - } - } - - range.deleteContents(); - range.select(true); - me.__hasEnterExecCommand = true; - var html = htmlContent; - if (plainType === 2) { - html = getPureHtml(html); - } else if (plainType) { - html = txtContent; - } - me.execCommand("inserthtml", html, true); - me.__hasEnterExecCommand = false; - var rng = me.selection.getRange(); - while ( - !domUtils.isBody(rng.startContainer) && - !rng.startOffset && - rng.startContainer[ - rng.startContainer.nodeType == 3 ? "nodeValue" : "childNodes" - ].length - ) { - rng.setStartBefore(rng.startContainer); - } - var tmpAddress = rng.createAddress(true); - address.endAddress = tmpAddress.startAddress; - } - }); - - me.addListener("ready", function() { - domUtils.on(me.body, "cut", function() { - var range = me.selection.getRange(); - if (!range.collapsed && me.undoManger) { - me.undoManger.save(); - } - }); - - //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理 - domUtils.on( - me.body, - browser.ie || browser.opera ? "keydown" : "paste", - function(e) { - if ( - (browser.ie || browser.opera) && - ((!e.ctrlKey && !e.metaKey) || e.keyCode != "86") - ) { - return; - } - getClipboardData.call(me, function(div) { - filter(div); }); - } - ); - }); - me.commands["paste"] = { - execCommand: function(cmd) { - if (browser.ie) { - getClipboardData.call(me, function(div) { - filter(div); + me.addListener("ready", function () { + domUtils.on(me.body, "cut", function () { + var range = me.selection.getRange(); + if (!range.collapsed && me.undoManger) { + me.undoManger.save(); + } + }); + + //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理 + domUtils.on( + me.body, + browser.ie || browser.opera ? "keydown" : "paste", + function (e) { + if ( + (browser.ie || browser.opera) && + ((!e.ctrlKey && !e.metaKey) || e.keyCode != "86") + ) { + return; + } + getClipboardData.call(me, function (div) { + filter(div); + }); + } + ); }); - me.document.execCommand("paste"); - } else { - alert(me.getLang("pastemsg")); - } - } - }; -}; + + me.commands["paste"] = { + execCommand: function (cmd) { + if (browser.ie) { + getClipboardData.call(me, function (div) { + filter(div); + }); + me.document.execCommand("paste"); + } else { + alert(me.getLang("pastemsg")); + } + } + }; + }; // plugins/puretxtpaste.js -/** - * 纯文本粘贴插件 - * @file - * @since 1.2.6.1 - */ - -UE.plugins["pasteplain"] = function() { - var me = this; - me.setOpt({ - pasteplain: false, - filterTxtRules: (function() { - function transP(node) { - node.tagName = "p"; - node.setStyle(); - } - function removeNode(node) { - node.parentNode.removeChild(node, true); - } - return { - //直接删除及其字节点内容 - "-": "script style object iframe embed input select", - p: { $: {} }, - br: { $: {} }, - div: function(node) { - var tmpNode, - p = UE.uNode.createElement("p"); - while ((tmpNode = node.firstChild())) { - if (tmpNode.type == "text" || !UE.dom.dtd.$block[tmpNode.tagName]) { - p.appendChild(tmpNode); - } else { - if (p.firstChild()) { - node.parentNode.insertBefore(p, node); - p = UE.uNode.createElement("p"); - } else { - node.parentNode.insertBefore(tmpNode, node); - } - } - } - if (p.firstChild()) { - node.parentNode.insertBefore(p, node); - } - node.parentNode.removeChild(node); - }, - ol: removeNode, - ul: removeNode, - dl: removeNode, - dt: removeNode, - dd: removeNode, - li: removeNode, - caption: transP, - th: transP, - tr: transP, - h1: transP, - h2: transP, - h3: transP, - h4: transP, - h5: transP, - h6: transP, - td: function(node) { - //没有内容的td直接删掉 - var txt = !!node.innerText(); - if (txt) { - node.parentNode.insertAfter( - UE.uNode.createText("    "), - node - ); - } - node.parentNode.removeChild(node, node.innerText()); - } - }; - })() - }); - //暂时这里支持一下老版本的属性 - var pasteplain = me.options.pasteplain; - - /** - * 启用或取消纯文本粘贴模式 - * @command pasteplain - * @method execCommand - * @param { String } cmd 命令字符串 - * @example - * ```javascript - * editor.queryCommandState( 'pasteplain' ); - * ``` - */ - - /** - * 查询当前是否处于纯文本粘贴模式 - * @command pasteplain - * @method queryCommandState - * @param { String } cmd 命令字符串 - * @return { int } 如果处于纯文本模式,返回1,否则,返回0 - * @example - * ```javascript - * editor.queryCommandState( 'pasteplain' ); - * ``` - */ - me.commands["pasteplain"] = { - queryCommandState: function() { - return pasteplain ? 1 : 0; - }, - execCommand: function() { - pasteplain = !pasteplain | 0; - }, - notNeedUndo: 1 - }; -}; - - -// plugins/list.js -/** - * 有序列表,无序列表插件 - * @file - * @since 1.2.6.1 - */ - -UE.plugins["list"] = function() { - var me = this, - notExchange = { - TD: 1, - PRE: 1, - BLOCKQUOTE: 1 - }; - var customStyle = { - cn: "cn-1-", - cn1: "cn-2-", - cn2: "cn-3-", - num: "num-1-", - num1: "num-2-", - num2: "num-3-", - dash: "dash", - dot: "dot" - }; - - me.setOpt({ - autoTransWordToList: false, - insertorderedlist: { - num: "", - num1: "", - num2: "", - cn: "", - cn1: "", - cn2: "", - decimal: "", - "lower-alpha": "", - "lower-roman": "", - "upper-alpha": "", - "upper-roman": "" - }, - insertunorderedlist: { - circle: "", - disc: "", - square: "", - dash: "", - dot: "" - }, - listDefaultPaddingLeft: "30", - listiconpath: "http://bs.baidu.com/listicon/", - maxListLevel: -1, //-1不限制 - disablePInList: false - }); - function listToArray(list) { - var arr = []; - for (var p in list) { - arr.push(p); - } - return arr; - } - var listStyle = { - OL: listToArray(me.options.insertorderedlist), - UL: listToArray(me.options.insertunorderedlist) - }; - var liiconpath = me.options.listiconpath; - - //根据用户配置,调整customStyle - for (var s in customStyle) { - if ( - !me.options.insertorderedlist.hasOwnProperty(s) && - !me.options.insertunorderedlist.hasOwnProperty(s) - ) { - delete customStyle[s]; - } - } - - me.ready(function() { - var customCss = []; - for (var p in customStyle) { - if (p == "dash" || p == "dot") { - customCss.push( - "li.list-" + - customStyle[p] + - "{background-image:url(" + - liiconpath + - customStyle[p] + - ".gif)}" - ); - customCss.push( - "ul.custom_" + - p + - "{list-style:none;}ul.custom_" + - p + - " li{background-position:0 3px;background-repeat:no-repeat}" - ); - } else { - for (var i = 0; i < 99; i++) { - customCss.push( - "li.list-" + - customStyle[p] + - i + - "{background-image:url(" + - liiconpath + - "list-" + - customStyle[p] + - i + - ".gif)}" - ); - } - customCss.push( - "ol.custom_" + - p + - "{list-style:none;}ol.custom_" + - p + - " li{background-position:0 3px;background-repeat:no-repeat}" - ); - } - switch (p) { - case "cn": - customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}"); - customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); - customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}"); - break; - case "cn1": - customCss.push("li.list-" + p + "-paddingleft-1{padding-left:30px}"); - customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); - customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}"); - break; - case "cn2": - customCss.push("li.list-" + p + "-paddingleft-1{padding-left:40px}"); - customCss.push("li.list-" + p + "-paddingleft-2{padding-left:55px}"); - customCss.push("li.list-" + p + "-paddingleft-3{padding-left:68px}"); - break; - case "num": - case "num1": - customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}"); - break; - case "num2": - customCss.push("li.list-" + p + "-paddingleft-1{padding-left:35px}"); - customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); - break; - case "dash": - customCss.push("li.list-" + p + "-paddingleft{padding-left:35px}"); - break; - case "dot": - customCss.push("li.list-" + p + "-paddingleft{padding-left:20px}"); - } - } - customCss.push(".list-paddingleft-1{padding-left:0}"); - customCss.push( - ".list-paddingleft-2{padding-left:" + - me.options.listDefaultPaddingLeft + - "px}" - ); - customCss.push( - ".list-paddingleft-3{padding-left:" + - me.options.listDefaultPaddingLeft * 2 + - "px}" - ); - //如果不给宽度会在自定应样式里出现滚动条 - utils.cssRule( - "list", - "ol,ul{margin:0;pading:0;" + - (browser.ie ? "" : "width:95%") + - "}li{clear:both;}" + - customCss.join("\n"), - me.document - ); - }); - //单独处理剪切的问题 - me.ready(function() { - domUtils.on(me.body, "cut", function() { - setTimeout(function() { - var rng = me.selection.getRange(), - li; - //trace:3416 - if (!rng.collapsed) { - if ( - (li = domUtils.findParentByTagName(rng.startContainer, "li", true)) - ) { - if (!li.nextSibling && domUtils.isEmptyBlock(li)) { - var pn = li.parentNode, - node; - if ((node = pn.previousSibling)) { - domUtils.remove(pn); - rng.setStartAtLast(node).collapse(true); - rng.select(true); - } else if ((node = pn.nextSibling)) { - domUtils.remove(pn); - rng.setStartAtFirst(node).collapse(true); - rng.select(true); - } else { - var tmpNode = me.document.createElement("p"); - domUtils.fillNode(me.document, tmpNode); - pn.parentNode.insertBefore(tmpNode, pn); - domUtils.remove(pn); - rng.setStart(tmpNode, 0).collapse(true); - rng.select(true); - } - } - } - } - }); - }); - }); - - function getStyle(node) { - var cls = node.className; - if (domUtils.hasClass(node, /custom_/)) { - return cls.match(/custom_(\w+)/)[1]; - } - return domUtils.getStyle(node, "list-style-type"); - } - - me.addListener("beforepaste", function(type, html) { - var me = this, - rng = me.selection.getRange(), - li; - var root = UE.htmlparser(html.html, true); - if ((li = domUtils.findParentByTagName(rng.startContainer, "li", true))) { - var list = li.parentNode, - tagName = list.tagName === "OL" ? "ul" : "ol"; - utils.each(root.getNodesByTagName(tagName), function(n) { - n.tagName = list.tagName; - n.setAttr(); - if (n.parentNode === root) { - type = getStyle(list) || (list.tagName == "OL" ? "decimal" : "disc"); - } else { - var className = n.parentNode.getAttr("class"); - if (className && /custom_/.test(className)) { - type = className.match(/custom_(\w+)/)[1]; - } else { - type = n.parentNode.getStyle("list-style-type"); - } - if (!type) { - type = list.tagName === "OL" ? "decimal" : "disc"; - } - } - var index = utils.indexOf(listStyle[list.tagName], type); - if (n.parentNode !== root) - index = index + 1 === listStyle[list.tagName].length ? 0 : index + 1; - var currentStyle = listStyle[list.tagName][index]; - if (customStyle[currentStyle]) { - n.setAttr("class", "custom_" + currentStyle); - } else { - n.setStyle("list-style-type", currentStyle); - } - }); - } - - html.html = root.toHtml(); - }); - //导出时,去掉p标签 - me.getOpt("disablePInList") === true && - me.addOutputRule(function(root) { - utils.each(root.getNodesByTagName("li"), function(li) { - var newChildrens = [], - index = 0; - utils.each(li.children, function(n) { - if (n.tagName == "p") { - var tmpNode; - while ((tmpNode = n.children.pop())) { - newChildrens.splice(index, 0, tmpNode); - tmpNode.parentNode = li; - lastNode = tmpNode; - } - tmpNode = newChildrens[newChildrens.length - 1]; - if ( - !tmpNode || - tmpNode.type !== "element" || - tmpNode.tagName !== "br" - ) { - var br = UE.uNode.createElement("br"); - br.parentNode = li; - newChildrens.push(br); - } - - index = newChildrens.length; - } - }); - if (newChildrens.length) { - li.children = newChildrens; - } - }); - }); - //进入编辑器的li要套p标签 - me.addInputRule(function(root) { - utils.each(root.getNodesByTagName("li"), function(li) { - var tmpP = UE.uNode.createElement("p"); - for (var i = 0, ci; (ci = li.children[i]); ) { - if (ci.type === "text" || dtd.p[ci.tagName]) { - tmpP.appendChild(ci); - } else { - if (tmpP.firstChild()) { - li.insertBefore(tmpP, ci); - tmpP = UE.uNode.createElement("p"); - i = i + 2; - } else { - i++; - } - } - } - if ((tmpP.firstChild() && !tmpP.parentNode) || !li.firstChild()) { - li.appendChild(tmpP); - } - //trace:3357 - //p不能为空 - if (!tmpP.firstChild()) { - tmpP.innerHTML(browser.ie ? " " : "
    "); - } - //去掉末尾的空白 - var p = li.firstChild(); - var lastChild = p.lastChild(); - if ( - lastChild && - lastChild.type === "text" && - /^\s*$/.test(lastChild.data) - ) { - p.removeChild(lastChild); - } - }); - if (me.options.autoTransWordToList) { - var orderlisttype = { - num1: /^\d+\)/, - decimal: /^\d+\./, - "lower-alpha": /^[a-z]+\)/, - "upper-alpha": /^[A-Z]+\./, - cn: /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/, - cn2: /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/ - }, - unorderlisttype = { - square: "n" - }; - function checkListType(content, container) { - var span = container.firstChild(); - if ( - span && - span.type === "element" && - span.tagName === "span" && - /Wingdings|Symbol/.test(span.getStyle("font-family")) - ) { - for (var p in unorderlisttype) { - if (unorderlisttype[p] == span.data) { - return p; - } - } - return "disc"; - } - for (var p in orderlisttype) { - if (orderlisttype[p].test(content)) { - return p; - } - } - } - utils.each(root.getNodesByTagName("p"), function(node) { - if (node.getAttr("class") !== "MsoListParagraph") { - return; - } - - //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视 - node.setStyle("margin", ""); - node.setStyle("margin-left", ""); - node.setAttr("class", ""); - - function appendLi(list, p, type) { - if (list.tagName === "ol") { - if (browser.ie) { - var first = p.firstChild(); - if ( - first.type === "element" && - first.tagName === "span" && - orderlisttype[type].test(first.innerText()) - ) { - p.removeChild(first); - } - } else { - p.innerHTML(p.innerHTML().replace(orderlisttype[type], "")); - } - } else { - p.removeChild(p.firstChild()); - } - - var li = UE.uNode.createElement("li"); - li.appendChild(p); - list.appendChild(li); - } - var tmp = node, - type, - cacheNode = node; - - if ( - node.parentNode.tagName !== "li" && - (type = checkListType(node.innerText(), node)) - ) { - var list = UE.uNode.createElement( - me.options.insertorderedlist.hasOwnProperty(type) ? "ol" : "ul" - ); - if (customStyle[type]) { - list.setAttr("class", "custom_" + type); - } else { - list.setStyle("list-style-type", type); - } - while ( - node && - node.parentNode.tagName !== "li" && - checkListType(node.innerText(), node) - ) { - tmp = node.nextSibling(); - if (!tmp) { - node.parentNode.insertBefore(list, node); - } - appendLi(list, node, type); - node = tmp; - } - if (!list.parentNode && node && node.parentNode) { - node.parentNode.insertBefore(list, node); - } - } - var span = cacheNode.firstChild(); - if ( - span && - span.type == "element" && - span.tagName == "span" && - /^\s*( )+\s*$/.test(span.innerText()) - ) { - span.parentNode.removeChild(span); - } - }); - } - }); - - //调整索引标签 - me.addListener("contentchange", function() { - adjustListStyle(me.document); - }); - - function adjustListStyle(doc, ignore) { - utils.each(domUtils.getElementsByTagName(doc, "ol ul"), function(node) { - if (!domUtils.inDoc(node, doc)) return; - - var parent = node.parentNode; - if (parent.tagName === node.tagName) { - var nodeStyleType = - getStyle(node) || (node.tagName === "OL" ? "decimal" : "disc"), - parentStyleType = - getStyle(parent) || (parent.tagName === "OL" ? "decimal" : "disc"); - if (nodeStyleType === parentStyleType) { - var styleIndex = utils.indexOf( - listStyle[node.tagName], - nodeStyleType - ); - styleIndex = styleIndex + 1 === listStyle[node.tagName].length - ? 0 - : styleIndex + 1; - setListStyle(node, listStyle[node.tagName][styleIndex]); - } - } - var index = 0, - type = 2; - if (domUtils.hasClass(node, /custom_/)) { - if ( - !( - /[ou]l/i.test(parent.tagName) && - domUtils.hasClass(parent, /custom_/) - ) - ) { - type = 1; - } - } else { - if ( - /[ou]l/i.test(parent.tagName) && - domUtils.hasClass(parent, /custom_/) - ) { - type = 3; - } - } - - var style = domUtils.getStyle(node, "list-style-type"); - style && (node.style.cssText = "list-style-type:" + style); - node.className = - utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) + - " list-paddingleft-" + - type; - utils.each(domUtils.getElementsByTagName(node, "li"), function(li) { - li.style.cssText && (li.style.cssText = ""); - if (!li.firstChild) { - domUtils.remove(li); - return; - } - if (li.parentNode !== node) { - return; - } - index++; - if (domUtils.hasClass(node, /custom_/)) { - var paddingLeft = 1, - currentStyle = getStyle(node); - if (node.tagName === "OL") { - if (currentStyle) { - switch (currentStyle) { - case "cn": - case "cn1": - case "cn2": - if ( - index > 10 && - (index % 10 === 0 || (index > 10 && index < 20)) - ) { - paddingLeft = 2; - } else if (index > 20) { - paddingLeft = 3; - } - break; - case "num2": - if (index > 9) { - paddingLeft = 2; - } - } - } - li.className = - "list-" + - customStyle[currentStyle] + - index + - " " + - "list-" + - currentStyle + - "-paddingleft-" + - paddingLeft; - } else { - li.className = - "list-" + - customStyle[currentStyle] + - " " + - "list-" + - currentStyle + - "-paddingleft"; - } - } else { - li.className = li.className.replace(/list-[\w\-]+/gi, ""); - } - var className = li.getAttribute("class"); - if (className !== null && !className.replace(/\s/g, "")) { - domUtils.removeAttributes(li, "class"); - } - }); - !ignore && - adjustList( - node, - node.tagName.toLowerCase(), - getStyle(node) || domUtils.getStyle(node, "list-style-type"), - true - ); - }); - } - function adjustList(list, tag, style, ignoreEmpty) { - var nextList = list.nextSibling; - if ( - nextList && - nextList.nodeType === 1 && - nextList.tagName.toLowerCase() === tag && - (getStyle(nextList) || - domUtils.getStyle(nextList, "list-style-type") || - (tag == "ol" ? "decimal" : "disc")) == style - ) { - domUtils.moveChild(nextList, list); - if (nextList.childNodes.length === 0) { - domUtils.remove(nextList); - } - } - if (nextList && domUtils.isFillChar(nextList)) { - domUtils.remove(nextList); - } - var preList = list.previousSibling; - if ( - preList && - preList.nodeType === 1 && - preList.tagName.toLowerCase() == tag && - (getStyle(preList) || - domUtils.getStyle(preList, "list-style-type") || - (tag == "ol" ? "decimal" : "disc")) === style - ) { - domUtils.moveChild(list, preList); - } - if (preList && domUtils.isFillChar(preList)) { - domUtils.remove(preList); - } - !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list); - if (getStyle(list)) { - adjustListStyle(list.ownerDocument, true); - } - } - - function setListStyle(list, style) { - if (customStyle[style]) { - list.className = "custom_" + style; - } - try { - domUtils.setStyle(list, "list-style-type", style); - } catch (e) {} - } - function clearEmptySibling(node) { - var tmpNode = node.previousSibling; - if (tmpNode && domUtils.isEmptyBlock(tmpNode)) { - domUtils.remove(tmpNode); - } - tmpNode = node.nextSibling; - if (tmpNode && domUtils.isEmptyBlock(tmpNode)) { - domUtils.remove(tmpNode); - } - } - - me.addListener("keydown", function(type, evt) { - function preventAndSave() { - evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); - me.fireEvent("contentchange"); - me.undoManger && me.undoManger.save(); - } - function findList(node, filterFn) { - while (node && !domUtils.isBody(node)) { - if (filterFn(node)) { - return null; - } - if (node.nodeType === 1 && /[ou]l/i.test(node.tagName)) { - return node; - } - node = node.parentNode; - } - return null; - } - var keyCode = evt.keyCode || evt.which; - if (keyCode === 13 && !evt.shiftKey) { - //回车 - var rng = me.selection.getRange(), - parent = domUtils.findParent( - rng.startContainer, - function(node) { - return domUtils.isBlockElm(node); - }, - true - ), - li = domUtils.findParentByTagName(rng.startContainer, "li", true); - if (parent && parent.tagName !== "PRE" && !li) { - var html = parent.innerHTML.replace( - new RegExp(domUtils.fillChar, "g"), - "" - ); - if (/^\s*1\s*\.[^\d]/.test(html)) { - parent.innerHTML = html.replace(/^\s*1\s*\./, ""); - rng.setStartAtLast(parent).collapse(true).select(); - me.__hasEnterExecCommand = true; - me.execCommand("insertorderedlist"); - me.__hasEnterExecCommand = false; - } - } - var range = me.selection.getRange(), - start = findList(range.startContainer, function(node) { - return node.tagName === "TABLE"; - }), - end = range.collapsed - ? start - : findList(range.endContainer, function(node) { - return node.tagName === "TABLE"; - }); - - if (start && end && start === end) { - if (!range.collapsed) { - start = domUtils.findParentByTagName( - range.startContainer, - "li", - true - ); - end = domUtils.findParentByTagName(range.endContainer, "li", true); - if (start && end && start === end) { - range.deleteContents(); - li = domUtils.findParentByTagName(range.startContainer, "li", true); - if (li && domUtils.isEmptyBlock(li)) { - pre = li.previousSibling; - next = li.nextSibling; - p = me.document.createElement("p"); - - domUtils.fillNode(me.document, p); - parentList = li.parentNode; - if (pre && next) { - range.setStart(next, 0).collapse(true).select(true); - domUtils.remove(li); - } else { - if ((!pre && !next) || !pre) { - parentList.parentNode.insertBefore(p, parentList); - } else { - li.parentNode.parentNode.insertBefore( - p, - parentList.nextSibling - ); - } - domUtils.remove(li); - if (!parentList.firstChild) { - domUtils.remove(parentList); - } - range.setStart(p, 0).setCursor(); - } - preventAndSave(); - return; - } - } else { - var tmpRange = range.cloneRange(), - bk = tmpRange.collapse(false).createBookmark(); - - range.deleteContents(); - tmpRange.moveToBookmark(bk); - var li = domUtils.findParentByTagName( - tmpRange.startContainer, - "li", - true - ); - - clearEmptySibling(li); - tmpRange.select(); - preventAndSave(); - return; - } - } - - li = domUtils.findParentByTagName(range.startContainer, "li", true); - - if (li) { - if (domUtils.isEmptyBlock(li)) { - bk = range.createBookmark(); - var parentList = li.parentNode; - if (li !== parentList.lastChild) { - domUtils.breakParent(li, parentList); - clearEmptySibling(li); - } else { - parentList.parentNode.insertBefore(li, parentList.nextSibling); - if (domUtils.isEmptyNode(parentList)) { - domUtils.remove(parentList); - } - } - //嵌套不处理 - if (!dtd.$list[li.parentNode.tagName]) { - if (!domUtils.isBlockElm(li.firstChild)) { - p = me.document.createElement("p"); - li.parentNode.insertBefore(p, li); - while (li.firstChild) { - p.appendChild(li.firstChild); - } - domUtils.remove(li); - } else { - domUtils.remove(li, true); - } - } - range.moveToBookmark(bk).select(); - } else { - var first = li.firstChild; - if (!first || !domUtils.isBlockElm(first)) { - var p = me.document.createElement("p"); - - !li.firstChild && domUtils.fillNode(me.document, p); - while (li.firstChild) { - p.appendChild(li.firstChild); - } - li.appendChild(p); - first = p; - } - - var span = me.document.createElement("span"); - - range.insertNode(span); - domUtils.breakParent(span, li); - - var nextLi = span.nextSibling; - first = nextLi.firstChild; - - if (!first) { - p = me.document.createElement("p"); - - domUtils.fillNode(me.document, p); - nextLi.appendChild(p); - first = p; - } - if (domUtils.isEmptyNode(first)) { - first.innerHTML = ""; - domUtils.fillNode(me.document, first); - } - - range.setStart(first, 0).collapse(true).shrinkBoundary().select(); - domUtils.remove(span); - var pre = nextLi.previousSibling; - if (pre && domUtils.isEmptyBlock(pre)) { - pre.innerHTML = "

    "; - domUtils.fillNode(me.document, pre.firstChild); - } - } - // } - preventAndSave(); - } - } - } - if (keyCode === 8) { - //修中ie中li下的问题 - range = me.selection.getRange(); - if (range.collapsed && domUtils.isStartInblock(range)) { - tmpRange = range.cloneRange().trimBoundary(); - li = domUtils.findParentByTagName(range.startContainer, "li", true); - //要在li的最左边,才能处理 - if (li && domUtils.isStartInblock(tmpRange)) { - start = domUtils.findParentByTagName(range.startContainer, "p", true); - if (start && start !== li.firstChild) { - var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]); - domUtils.breakParent(start, parentList); - clearEmptySibling(start); - me.fireEvent("contentchange"); - range.setStart(start, 0).setCursor(false, true); - me.fireEvent("saveScene"); - domUtils.preventDefault(evt); - return; - } - - if (li && (pre = li.previousSibling)) { - if (keyCode === 46 && li.childNodes.length) { - return; - } - //有可能上边的兄弟节点是个2级菜单,要追加到2级菜单的最后的li - if (dtd.$list[pre.tagName]) { - pre = pre.lastChild; - } - me.undoManger && me.undoManger.save(); - first = li.firstChild; - if (domUtils.isBlockElm(first)) { - if (domUtils.isEmptyNode(first)) { - // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); - pre.appendChild(first); - range.setStart(first, 0).setCursor(false, true); - //first不是唯一的节点 - while (li.firstChild) { - pre.appendChild(li.firstChild); - } - } else { - span = me.document.createElement("span"); - range.insertNode(span); - //判断pre是否是空的节点,如果是


    类型的空节点,干掉p标签防止它占位 - if (domUtils.isEmptyBlock(pre)) { - pre.innerHTML = ""; - } - domUtils.moveChild(li, pre); - range.setStartBefore(span).collapse(true).select(true); - - domUtils.remove(span); - } - } else { - if (domUtils.isEmptyNode(li)) { - var p = me.document.createElement("p"); - pre.appendChild(p); - range.setStart(p, 0).setCursor(); - // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); - } else { - range - .setEnd(pre, pre.childNodes.length) - .collapse() - .select(true); - while (li.firstChild) { - pre.appendChild(li.firstChild); - } - } - } - domUtils.remove(li); - me.fireEvent("contentchange"); - me.fireEvent("saveScene"); - domUtils.preventDefault(evt); - return; - } - //trace:980 - - if (li && !li.previousSibling) { - var parentList = li.parentNode; - var bk = range.createBookmark(); - if (domUtils.isTagNode(parentList.parentNode, "ol ul")) { - parentList.parentNode.insertBefore(li, parentList); - if (domUtils.isEmptyNode(parentList)) { - domUtils.remove(parentList); - } - } else { - while (li.firstChild) { - parentList.parentNode.insertBefore(li.firstChild, parentList); - } - - domUtils.remove(li); - if (domUtils.isEmptyNode(parentList)) { - domUtils.remove(parentList); - } - } - range.moveToBookmark(bk).setCursor(false, true); - me.fireEvent("contentchange"); - me.fireEvent("saveScene"); - domUtils.preventDefault(evt); - return; - } - } - } - } - }); - - me.addListener("keyup", function(type, evt) { - var keyCode = evt.keyCode || evt.which; - if (keyCode == 8) { - var rng = me.selection.getRange(), - list; - if ( - (list = domUtils.findParentByTagName( - rng.startContainer, - ["ol", "ul"], - true - )) - ) { - adjustList( - list, - list.tagName.toLowerCase(), - getStyle(list) || domUtils.getComputedStyle(list, "list-style-type"), - true - ); - } - } - }); - //处理tab键 - me.addListener("tabkeydown", function() { - var range = me.selection.getRange(); - - //控制级数 - function checkLevel(li) { - if (me.options.maxListLevel != -1) { - var level = li.parentNode, - levelNum = 0; - while (/[ou]l/i.test(level.tagName)) { - levelNum++; - level = level.parentNode; - } - if (levelNum >= me.options.maxListLevel) { - return true; - } - } - } - //只以开始为准 - //todo 后续改进 - var li = domUtils.findParentByTagName(range.startContainer, "li", true); - if (li) { - var bk; - if (range.collapsed) { - if (checkLevel(li)) return true; - var parentLi = li.parentNode, - list = me.document.createElement(parentLi.tagName), - index = utils.indexOf( - listStyle[list.tagName], - getStyle(parentLi) || - domUtils.getComputedStyle(parentLi, "list-style-type") - ); - index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1; - var currentStyle = listStyle[list.tagName][index]; - setListStyle(list, currentStyle); - if (domUtils.isStartInblock(range)) { - me.fireEvent("saveScene"); - bk = range.createBookmark(); - parentLi.insertBefore(list, li); - list.appendChild(li); - adjustList(list, list.tagName.toLowerCase(), currentStyle); - me.fireEvent("contentchange"); - range.moveToBookmark(bk).select(true); - return true; - } - } else { - me.fireEvent("saveScene"); - bk = range.createBookmark(); - for ( - var i = 0, closeList, parents = domUtils.findParents(li), ci; - (ci = parents[i++]); - - ) { - if (domUtils.isTagNode(ci, "ol ul")) { - closeList = ci; - break; - } - } - var current = li; - if (bk.end) { - while ( - current && - !( - domUtils.getPosition(current, bk.end) & - domUtils.POSITION_FOLLOWING - ) - ) { - if (checkLevel(current)) { - current = domUtils.getNextDomNode(current, false, null, function( - node - ) { - return node !== closeList; - }); - continue; - } - var parentLi = current.parentNode, - list = me.document.createElement(parentLi.tagName), - index = utils.indexOf( - listStyle[list.tagName], - getStyle(parentLi) || - domUtils.getComputedStyle(parentLi, "list-style-type") - ); - var currentIndex = index + 1 == listStyle[list.tagName].length - ? 0 - : index + 1; - var currentStyle = listStyle[list.tagName][currentIndex]; - setListStyle(list, currentStyle); - parentLi.insertBefore(list, current); - while ( - current && - !( - domUtils.getPosition(current, bk.end) & - domUtils.POSITION_FOLLOWING - ) - ) { - li = current.nextSibling; - list.appendChild(current); - if (!li || domUtils.isTagNode(li, "ol ul")) { - if (li) { - while ((li = li.firstChild)) { - if (li.tagName == "LI") { - break; - } - } - } else { - li = domUtils.getNextDomNode(current, false, null, function( - node - ) { - return node !== closeList; - }); - } - break; - } - current = li; - } - adjustList(list, list.tagName.toLowerCase(), currentStyle); - current = li; - } - } - me.fireEvent("contentchange"); - range.moveToBookmark(bk).select(); - return true; - } - } - }); - function getLi(start) { - while (start && !domUtils.isBody(start)) { - if (start.nodeName == "TABLE") { - return null; - } - if (start.nodeName == "LI") { - return start; - } - start = start.parentNode; - } - } - - /** - * 有序列表,与“insertunorderedlist”命令互斥 - * @command insertorderedlist - * @method execCommand - * @param { String } command 命令字符串 - * @param { String } style 插入的有序列表类型,值为:decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2 - * @example - * ```javascript - * editor.execCommand( 'insertorderedlist','decimal'); - * ``` - */ - /** - * 查询当前选区内容是否有序列表 - * @command insertorderedlist - * @method queryCommandState - * @param { String } cmd 命令字符串 - * @return { int } 如果当前选区是有序列表返回1,否则返回0 - * @example - * ```javascript - * editor.queryCommandState( 'insertorderedlist' ); - * ``` - */ - /** - * 查询当前选区内容是否有序列表 - * @command insertorderedlist - * @method queryCommandValue - * @param { String } cmd 命令字符串 - * @return { String } 返回当前有序列表的类型,值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2 - * @example - * ```javascript - * editor.queryCommandValue( 'insertorderedlist' ); - * ``` - */ - - /** - * 无序列表,与“insertorderedlist”命令互斥 - * @command insertunorderedlist - * @method execCommand - * @param { String } command 命令字符串 - * @param { String } style 插入的无序列表类型,值为:circle,disc,square,dash,dot - * @example - * ```javascript - * editor.execCommand( 'insertunorderedlist','circle'); - * ``` - */ - /** - * 查询当前是否有word文档粘贴进来的图片 - * @command insertunorderedlist - * @method insertunorderedlist - * @param { String } command 命令字符串 - * @return { int } 如果当前选区是无序列表返回1,否则返回0 - * @example - * ```javascript - * editor.queryCommandState( 'insertunorderedlist' ); - * ``` - */ - /** - * 查询当前选区内容是否有序列表 - * @command insertunorderedlist - * @method queryCommandValue - * @param { String } command 命令字符串 - * @return { String } 返回当前无序列表的类型,值为null或circle,disc,square,dash,dot - * @example - * ```javascript - * editor.queryCommandValue( 'insertunorderedlist' ); - * ``` - */ - - me.commands["insertorderedlist"] = me.commands["insertunorderedlist"] = { - execCommand: function(command, style) { - if (!style) { - style = command.toLowerCase() == "insertorderedlist" - ? "decimal" - : "disc"; - } - var me = this, - range = this.selection.getRange(), - filterFn = function(node) { - return node.nodeType == 1 - ? node.tagName.toLowerCase() != "br" - : !domUtils.isWhitespace(node); - }, - tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul", - frag = me.document.createDocumentFragment(); - //去掉是因为会出现选到末尾,导致adjustmentBoundary缩到ol/ul的位置 - //range.shrinkBoundary();//.adjustmentBoundary(); - range.adjustmentBoundary().shrinkBoundary(); - var bko = range.createBookmark(true), - start = getLi(me.document.getElementById(bko.start)), - modifyStart = 0, - end = getLi(me.document.getElementById(bko.end)), - modifyEnd = 0, - startParent, - endParent, - list, - tmp; - - if (start || end) { - start && (startParent = start.parentNode); - if (!bko.end) { - end = start; - } - end && (endParent = end.parentNode); - - if (startParent === endParent) { - while (start !== end) { - tmp = start; - start = start.nextSibling; - if (!domUtils.isBlockElm(tmp.firstChild)) { - var p = me.document.createElement("p"); - while (tmp.firstChild) { - p.appendChild(tmp.firstChild); - } - tmp.appendChild(p); - } - frag.appendChild(tmp); - } - tmp = me.document.createElement("span"); - startParent.insertBefore(tmp, end); - if (!domUtils.isBlockElm(end.firstChild)) { - p = me.document.createElement("p"); - while (end.firstChild) { - p.appendChild(end.firstChild); - } - end.appendChild(p); - } - frag.appendChild(end); - domUtils.breakParent(tmp, startParent); - if (domUtils.isEmptyNode(tmp.previousSibling)) { - domUtils.remove(tmp.previousSibling); - } - if (domUtils.isEmptyNode(tmp.nextSibling)) { - domUtils.remove(tmp.nextSibling); - } - var nodeStyle = - getStyle(startParent) || - domUtils.getComputedStyle(startParent, "list-style-type") || - (command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc"); - if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) { - for ( - var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); - (ci = frag.firstChild); - - ) { - if (domUtils.isTagNode(ci, "ol ul")) { - // 删除时,子列表不处理 - // utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){ - // while(li.firstChild){ - // tmpFrag.appendChild(li.firstChild); - // } - // - // }); - tmpFrag.appendChild(ci); - } else { - while (ci.firstChild) { - tmpFrag.appendChild(ci.firstChild); - domUtils.remove(ci); - } - } - } - tmp.parentNode.insertBefore(tmpFrag, tmp); - } else { - list = me.document.createElement(tag); - setListStyle(list, style); - list.appendChild(frag); - tmp.parentNode.insertBefore(list, tmp); - } - - domUtils.remove(tmp); - list && adjustList(list, tag, style); - range.moveToBookmark(bko).select(); - return; - } - //开始 - if (start) { - while (start) { - tmp = start.nextSibling; - if (domUtils.isTagNode(start, "ol ul")) { - frag.appendChild(start); - } else { - var tmpfrag = me.document.createDocumentFragment(), - hasBlock = 0; - while (start.firstChild) { - if (domUtils.isBlockElm(start.firstChild)) { - hasBlock = 1; - } - tmpfrag.appendChild(start.firstChild); - } - if (!hasBlock) { - var tmpP = me.document.createElement("p"); - tmpP.appendChild(tmpfrag); - frag.appendChild(tmpP); - } else { - frag.appendChild(tmpfrag); - } - domUtils.remove(start); - } - - start = tmp; - } - startParent.parentNode.insertBefore(frag, startParent.nextSibling); - if (domUtils.isEmptyNode(startParent)) { - range.setStartBefore(startParent); - domUtils.remove(startParent); - } else { - range.setStartAfter(startParent); - } - modifyStart = 1; - } - - if (end && domUtils.inDoc(endParent, me.document)) { - //结束 - start = endParent.firstChild; - while (start && start !== end) { - tmp = start.nextSibling; - if (domUtils.isTagNode(start, "ol ul")) { - frag.appendChild(start); - } else { - tmpfrag = me.document.createDocumentFragment(); - hasBlock = 0; - while (start.firstChild) { - if (domUtils.isBlockElm(start.firstChild)) { - hasBlock = 1; - } - tmpfrag.appendChild(start.firstChild); - } - if (!hasBlock) { - tmpP = me.document.createElement("p"); - tmpP.appendChild(tmpfrag); - frag.appendChild(tmpP); - } else { - frag.appendChild(tmpfrag); - } - domUtils.remove(start); - } - start = tmp; - } - var tmpDiv = domUtils.createElement(me.document, "div", { - tmpDiv: 1 - }); - domUtils.moveChild(end, tmpDiv); - - frag.appendChild(tmpDiv); - domUtils.remove(end); - endParent.parentNode.insertBefore(frag, endParent); - range.setEndBefore(endParent); - if (domUtils.isEmptyNode(endParent)) { - domUtils.remove(endParent); - } - - modifyEnd = 1; - } - } - - if (!modifyStart) { - range.setStartBefore(me.document.getElementById(bko.start)); - } - if (bko.end && !modifyEnd) { - range.setEndAfter(me.document.getElementById(bko.end)); - } - range.enlarge(true, function(node) { - return notExchange[node.tagName]; - }); - - frag = me.document.createDocumentFragment(); - - var bk = range.createBookmark(), - current = domUtils.getNextDomNode(bk.start, false, filterFn), - tmpRange = range.cloneRange(), - tmpNode, - block = domUtils.isBlockElm; - - while ( - current && - current !== bk.end && - domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING - ) { - if (current.nodeType == 3 || dtd.li[current.tagName]) { - if (current.nodeType == 1 && dtd.$list[current.tagName]) { - while (current.firstChild) { - frag.appendChild(current.firstChild); - } - tmpNode = domUtils.getNextDomNode(current, false, filterFn); - domUtils.remove(current); - current = tmpNode; - continue; - } - tmpNode = current; - tmpRange.setStartBefore(current); - - while ( - current && - current !== bk.end && - (!block(current) || domUtils.isBookmarkNode(current)) - ) { - tmpNode = current; - current = domUtils.getNextDomNode(current, false, null, function( - node - ) { - return !notExchange[node.tagName]; - }); - } - - if (current && block(current)) { - tmp = domUtils.getNextDomNode(tmpNode, false, filterFn); - if (tmp && domUtils.isBookmarkNode(tmp)) { - current = domUtils.getNextDomNode(tmp, false, filterFn); - tmpNode = tmp; - } - } - tmpRange.setEndAfter(tmpNode); - - current = domUtils.getNextDomNode(tmpNode, false, filterFn); - - var li = range.document.createElement("li"); - - li.appendChild(tmpRange.extractContents()); - if (domUtils.isEmptyNode(li)) { - var tmpNode = range.document.createElement("p"); - while (li.firstChild) { - tmpNode.appendChild(li.firstChild); - } - li.appendChild(tmpNode); - } - frag.appendChild(li); - } else { - current = domUtils.getNextDomNode(current, true, filterFn); - } - } - range.moveToBookmark(bk).collapse(true); - list = me.document.createElement(tag); - setListStyle(list, style); - list.appendChild(frag); - range.insertNode(list); - //当前list上下看能否合并 - adjustList(list, tag, style); - //去掉冗余的tmpDiv - for ( - var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, "div"); - (ci = tmpDivs[i++]); - - ) { - if (ci.getAttribute("tmpDiv")) { - domUtils.remove(ci, true); - } - } - range.moveToBookmark(bko).select(); - }, - queryCommandState: function(command) { - var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul"; - var path = this.selection.getStartElementPath(); - for (var i = 0, ci; (ci = path[i++]); ) { - if (ci.nodeName == "TABLE") { - return 0; - } - if (tag == ci.nodeName.toLowerCase()) { - return 1; - } - } - return 0; - }, - queryCommandValue: function(command) { - var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul"; - var path = this.selection.getStartElementPath(), - node; - for (var i = 0, ci; (ci = path[i++]); ) { - if (ci.nodeName == "TABLE") { - node = null; - break; - } - if (tag == ci.nodeName.toLowerCase()) { - node = ci; - break; - } - } - return node - ? getStyle(node) || domUtils.getComputedStyle(node, "list-style-type") - : null; - } - }; -}; - - -// plugins/source.js -/** - * 源码编辑插件 - * @file - * @since 1.2.6.1 - */ - -(function() { - var sourceEditors = { - textarea: function(editor, holder) { - var textarea = holder.ownerDocument.createElement("textarea"); - textarea.style.cssText = - "position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;"; - // todo: IE下只有onresize属性可用... 很纠结 - if (browser.ie && browser.version < 8) { - textarea.style.width = holder.offsetWidth + "px"; - textarea.style.height = holder.offsetHeight + "px"; - holder.onresize = function() { - textarea.style.width = holder.offsetWidth + "px"; - textarea.style.height = holder.offsetHeight + "px"; - }; - } - holder.appendChild(textarea); - return { - setContent: function(content) { - textarea.value = content; - }, - getContent: function() { - return textarea.value; - }, - select: function() { - var range; - if (browser.ie) { - range = textarea.createTextRange(); - range.collapse(true); - range.select(); - } else { - //todo: chrome下无法设置焦点 - textarea.setSelectionRange(0, 0); - textarea.focus(); - } - }, - dispose: function() { - holder.removeChild(textarea); - // todo - holder.onresize = null; - textarea = null; - holder = null; - }, - focus: function (){ - textarea.focus(); - }, - blur: function (){ - textarea.blur(); - } - }; - }, - codemirror: function(editor, holder) { - var codeEditor = window.CodeMirror(holder, { - mode: "text/html", - tabMode: "indent", - lineNumbers: true, - lineWrapping: true, - onChange: function(v){ - editor.sync(); - editor.fireEvent("contentchange"); - // console.log('CodeMirror.onChange',v.getValue()); - } - }); - // console.log('sourceEditor',codeEditor); - var dom = codeEditor.getWrapperElement(); - dom.style.cssText = - 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;'; - codeEditor.getScrollerElement().style.cssText = - "position:absolute;left:0;top:0;width:100%;height:100%;"; - codeEditor.refresh(); - return { - getCodeMirror: function() { - return codeEditor; - }, - setContent: function(content) { - codeEditor.setValue(content); - }, - getContent: function() { - return codeEditor.getValue(); - }, - select: function() { - codeEditor.focus(); - }, - dispose: function() { - holder.removeChild(dom); - dom = null; - codeEditor = null; - }, - focus: function (){ - codeEditor.focus(); - }, - blur: function (){ - // codeEditor.blur(); - // since codemirror not support blur() - codeEditor.setOption('readOnly', true); - codeEditor.setOption('readOnly', false); - } - }; - } - }; - - UE.plugins["source"] = function() { - var me = this; - var opt = this.options; - var sourceMode = false; - var sourceEditor; - var orgSetContent; - var orgFocus; - var orgBlur; - opt.sourceEditor = browser.ie - ? "textarea" - : opt.sourceEditor || "codemirror"; - - me.setOpt({ - sourceEditorFirst: false - }); - function createSourceEditor(holder) { - return sourceEditors[ - opt.sourceEditor == "codemirror" && window.CodeMirror - ? "codemirror" - : "textarea" - ](me, holder); - } - - var bakCssText; - //解决在源码模式下getContent不能得到最新的内容问题 - var oldGetContent, bakAddress; - /** - * 切换源码模式和编辑模式 - * @command source + * 纯文本粘贴插件 + * @file + * @since 1.2.6.1 + */ + + UE.plugins["pasteplain"] = function () { + var me = this; + me.setOpt({ + pasteplain: false, + filterTxtRules: (function () { + function transP(node) { + node.tagName = "p"; + node.setStyle(); + } + + function removeNode(node) { + node.parentNode.removeChild(node, true); + } + + return { + //直接删除及其字节点内容 + "-": "script style object iframe embed input select", + p: {$: {}}, + br: {$: {}}, + div: function (node) { + var tmpNode, + p = UE.uNode.createElement("p"); + while ((tmpNode = node.firstChild())) { + if (tmpNode.type == "text" || !UE.dom.dtd.$block[tmpNode.tagName]) { + p.appendChild(tmpNode); + } else { + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + p = UE.uNode.createElement("p"); + } else { + node.parentNode.insertBefore(tmpNode, node); + } + } + } + if (p.firstChild()) { + node.parentNode.insertBefore(p, node); + } + node.parentNode.removeChild(node); + }, + ol: removeNode, + ul: removeNode, + dl: removeNode, + dt: removeNode, + dd: removeNode, + li: removeNode, + caption: transP, + th: transP, + tr: transP, + h1: transP, + h2: transP, + h3: transP, + h4: transP, + h5: transP, + h6: transP, + td: function (node) { + //没有内容的td直接删掉 + var txt = !!node.innerText(); + if (txt) { + node.parentNode.insertAfter( + UE.uNode.createText("    "), + node + ); + } + node.parentNode.removeChild(node, node.innerText()); + } + }; + })() + }); + //暂时这里支持一下老版本的属性 + var pasteplain = me.options.pasteplain; + + /** + * 启用或取消纯文本粘贴模式 + * @command pasteplain * @method execCommand * @param { String } cmd 命令字符串 * @example * ```javascript - * editor.execCommand( 'source'); + * editor.queryCommandState( 'pasteplain' ); * ``` */ - /** - * 查询当前编辑区域的状态是源码模式还是可视化模式 - * @command source + /** + * 查询当前是否处于纯文本粘贴模式 + * @command pasteplain * @method queryCommandState * @param { String } cmd 命令字符串 - * @return { int } 如果当前是源码编辑模式,返回1,否则返回0 + * @return { int } 如果处于纯文本模式,返回1,否则,返回0 * @example * ```javascript - * editor.queryCommandState( 'source' ); + * editor.queryCommandState( 'pasteplain' ); + * ``` + */ + me.commands["pasteplain"] = { + queryCommandState: function () { + return pasteplain ? 1 : 0; + }, + execCommand: function () { + pasteplain = !pasteplain | 0; + }, + notNeedUndo: 1 + }; + }; + + +// plugins/list.js + /** + * 有序列表,无序列表插件 + * @file + * @since 1.2.6.1 + */ + + UE.plugins["list"] = function () { + var me = this, + notExchange = { + TD: 1, + PRE: 1, + BLOCKQUOTE: 1 + }; + // var customStyle = { + // cn: "cn-1-", + // cn1: "cn-2-", + // cn2: "cn-3-", + // num: "num-1-", + // num1: "num-2-", + // num2: "num-3-", + // dash: "dash", + // dot: "dot" + // }; + + me.setOpt({ + autoTransWordToList: false, + insertorderedlist: { + // num: "", + // num1: "", + // num2: "", + // cn: "", + // cn1: "", + // cn2: "", + decimal: "", + "lower-alpha": "", + "lower-roman": "", + "upper-alpha": "", + "upper-roman": "" + }, + insertunorderedlist: { + circle: "", + disc: "", + square: "", + // dash: "", + // dot: "" + }, + listDefaultPaddingLeft: "30", + listiconpath: "http://bs.baidu.com/listicon/", + maxListLevel: -1, //-1不限制 + disablePInList: false + }); + + function listToArray(list) { + var arr = []; + for (var p in list) { + arr.push(p); + } + return arr; + } + + var listStyle = { + OL: listToArray(me.options.insertorderedlist), + UL: listToArray(me.options.insertunorderedlist) + }; + var liiconpath = me.options.listiconpath; + + //根据用户配置,调整customStyle + // for (var s in customStyle) { + // if ( + // !me.options.insertorderedlist.hasOwnProperty(s) && + // !me.options.insertunorderedlist.hasOwnProperty(s) + // ) { + // delete customStyle[s]; + // } + // } + + me.ready(function () { + var customCss = []; + // for (var p in customStyle) { + // if (p == "dash" || p == "dot") { + // customCss.push( + // "li.list-" + + // customStyle[p] + + // "{background-image:url(" + + // liiconpath + + // customStyle[p] + + // ".gif)}" + // ); + // customCss.push( + // "ul.custom_" + + // p + + // "{list-style:none;}ul.custom_" + + // p + + // " li{background-position:0 3px;background-repeat:no-repeat}" + // ); + // } else { + // for (var i = 0; i < 99; i++) { + // customCss.push( + // "li.list-" + + // customStyle[p] + + // i + + // "{background-image:url(" + + // liiconpath + + // "list-" + + // customStyle[p] + + // i + + // ".gif)}" + // ); + // } + // customCss.push( + // "ol.custom_" + + // p + + // "{list-style:none;}ol.custom_" + + // p + + // " li{background-position:0 3px;background-repeat:no-repeat}" + // ); + // } + // switch (p) { + // case "cn": + // customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}"); + // customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); + // customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}"); + // break; + // case "cn1": + // customCss.push("li.list-" + p + "-paddingleft-1{padding-left:30px}"); + // customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); + // customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}"); + // break; + // case "cn2": + // customCss.push("li.list-" + p + "-paddingleft-1{padding-left:40px}"); + // customCss.push("li.list-" + p + "-paddingleft-2{padding-left:55px}"); + // customCss.push("li.list-" + p + "-paddingleft-3{padding-left:68px}"); + // break; + // case "num": + // case "num1": + // customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}"); + // break; + // case "num2": + // customCss.push("li.list-" + p + "-paddingleft-1{padding-left:35px}"); + // customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}"); + // break; + // case "dash": + // customCss.push("li.list-" + p + "-paddingleft{padding-left:35px}"); + // break; + // case "dot": + // customCss.push("li.list-" + p + "-paddingleft{padding-left:20px}"); + // } + // } + customCss.push(".list-paddingleft-1{padding-left:0}"); + customCss.push( + ".list-paddingleft-2{padding-left:" + + me.options.listDefaultPaddingLeft + + "px}" + ); + customCss.push( + ".list-paddingleft-3{padding-left:" + + me.options.listDefaultPaddingLeft * 2 + + "px}" + ); + //如果不给宽度会在自定应样式里出现滚动条 + utils.cssRule( + "list", + "ol,ul{margin:0;pading:0;" + + (browser.ie ? "" : "width:95%") + + "}li{clear:both;}" + + customCss.join("\n"), + me.document + ); + }); + //单独处理剪切的问题 + me.ready(function () { + domUtils.on(me.body, "cut", function () { + setTimeout(function () { + var rng = me.selection.getRange(), + li; + //trace:3416 + if (!rng.collapsed) { + if ( + (li = domUtils.findParentByTagName(rng.startContainer, "li", true)) + ) { + if (!li.nextSibling && domUtils.isEmptyBlock(li)) { + var pn = li.parentNode, + node; + if ((node = pn.previousSibling)) { + domUtils.remove(pn); + rng.setStartAtLast(node).collapse(true); + rng.select(true); + } else if ((node = pn.nextSibling)) { + domUtils.remove(pn); + rng.setStartAtFirst(node).collapse(true); + rng.select(true); + } else { + var tmpNode = me.document.createElement("p"); + domUtils.fillNode(me.document, tmpNode); + pn.parentNode.insertBefore(tmpNode, pn); + domUtils.remove(pn); + rng.setStart(tmpNode, 0).collapse(true); + rng.select(true); + } + } + } + } + }); + }); + }); + + function getStyle(node) { + var cls = node.className; + if (domUtils.hasClass(node, /custom_/)) { + return cls.match(/custom_(\w+)/)[1]; + } + return domUtils.getStyle(node, "list-style-type"); + } + + me.addListener("beforepaste", function (type, html) { + var me = this, + rng = me.selection.getRange(), + li; + var root = UE.htmlparser(html.html, true); + if ((li = domUtils.findParentByTagName(rng.startContainer, "li", true))) { + var list = li.parentNode, + tagName = list.tagName === "OL" ? "ul" : "ol"; + utils.each(root.getNodesByTagName(tagName), function (n) { + n.tagName = list.tagName; + n.setAttr(); + if (n.parentNode === root) { + type = getStyle(list) || (list.tagName == "OL" ? "decimal" : "disc"); + } else { + var className = n.parentNode.getAttr("class"); + if (className && /custom_/.test(className)) { + type = className.match(/custom_(\w+)/)[1]; + } else { + type = n.parentNode.getStyle("list-style-type"); + } + if (!type) { + type = list.tagName === "OL" ? "decimal" : "disc"; + } + } + var index = utils.indexOf(listStyle[list.tagName], type); + if (n.parentNode !== root) + index = index + 1 === listStyle[list.tagName].length ? 0 : index + 1; + var currentStyle = listStyle[list.tagName][index]; + // if (customStyle[currentStyle]) { + // n.setAttr("class", "custom_" + currentStyle); + // } else { + n.setStyle("list-style-type", currentStyle); + // } + }); + } + + html.html = root.toHtml(); + }); + //导出时,去掉p标签 + me.getOpt("disablePInList") === true && + me.addOutputRule(function (root) { + utils.each(root.getNodesByTagName("li"), function (li) { + var newChildrens = [], + index = 0; + utils.each(li.children, function (n) { + if (n.tagName == "p") { + var tmpNode; + while ((tmpNode = n.children.pop())) { + newChildrens.splice(index, 0, tmpNode); + tmpNode.parentNode = li; + lastNode = tmpNode; + } + tmpNode = newChildrens[newChildrens.length - 1]; + if ( + !tmpNode || + tmpNode.type !== "element" || + tmpNode.tagName !== "br" + ) { + var br = UE.uNode.createElement("br"); + br.parentNode = li; + newChildrens.push(br); + } + + index = newChildrens.length; + } + }); + if (newChildrens.length) { + li.children = newChildrens; + } + }); + }); + //进入编辑器的li要套p标签 + me.addInputRule(function (root) { + utils.each(root.getNodesByTagName("li"), function (li) { + var tmpP = UE.uNode.createElement("p"); + for (var i = 0, ci; (ci = li.children[i]);) { + if (ci.type === "text" || dtd.p[ci.tagName]) { + tmpP.appendChild(ci); + } else { + if (tmpP.firstChild()) { + li.insertBefore(tmpP, ci); + tmpP = UE.uNode.createElement("p"); + i = i + 2; + } else { + i++; + } + } + } + if ((tmpP.firstChild() && !tmpP.parentNode) || !li.firstChild()) { + li.appendChild(tmpP); + } + //trace:3357 + //p不能为空 + if (!tmpP.firstChild()) { + tmpP.innerHTML(browser.ie ? " " : "
    "); + } + //去掉末尾的空白 + var p = li.firstChild(); + var lastChild = p.lastChild(); + if ( + lastChild && + lastChild.type === "text" && + /^\s*$/.test(lastChild.data) + ) { + p.removeChild(lastChild); + } + }); + if (me.options.autoTransWordToList) { + var orderlisttype = { + num1: /^\d+\)/, + decimal: /^\d+\./, + "lower-alpha": /^[a-z]+\)/, + "upper-alpha": /^[A-Z]+\./, + cn: /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/, + cn2: /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/ + }, + unorderlisttype = { + square: "n" + }; + + function checkListType(content, container) { + var span = container.firstChild(); + if ( + span && + span.type === "element" && + span.tagName === "span" && + /Wingdings|Symbol/.test(span.getStyle("font-family")) + ) { + for (var p in unorderlisttype) { + if (unorderlisttype[p] == span.data) { + return p; + } + } + return "disc"; + } + for (var p in orderlisttype) { + if (orderlisttype[p].test(content)) { + return p; + } + } + } + + utils.each(root.getNodesByTagName("p"), function (node) { + if (node.getAttr("class") !== "MsoListParagraph") { + return; + } + + //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视 + node.setStyle("margin", ""); + node.setStyle("margin-left", ""); + node.setAttr("class", ""); + + function appendLi(list, p, type) { + if (list.tagName === "ol") { + if (browser.ie) { + var first = p.firstChild(); + if ( + first.type === "element" && + first.tagName === "span" && + orderlisttype[type].test(first.innerText()) + ) { + p.removeChild(first); + } + } else { + p.innerHTML(p.innerHTML().replace(orderlisttype[type], "")); + } + } else { + p.removeChild(p.firstChild()); + } + + var li = UE.uNode.createElement("li"); + li.appendChild(p); + list.appendChild(li); + } + + var tmp = node, + type, + cacheNode = node; + + if ( + node.parentNode.tagName !== "li" && + (type = checkListType(node.innerText(), node)) + ) { + var list = UE.uNode.createElement( + me.options.insertorderedlist.hasOwnProperty(type) ? "ol" : "ul" + ); + // if (customStyle[type]) { + // list.setAttr("class", "custom_" + type); + // } else { + list.setStyle("list-style-type", type); + // } + while ( + node && + node.parentNode.tagName !== "li" && + checkListType(node.innerText(), node) + ) { + tmp = node.nextSibling(); + if (!tmp) { + node.parentNode.insertBefore(list, node); + } + appendLi(list, node, type); + node = tmp; + } + if (!list.parentNode && node && node.parentNode) { + node.parentNode.insertBefore(list, node); + } + } + var span = cacheNode.firstChild(); + if ( + span && + span.type == "element" && + span.tagName == "span" && + /^\s*( )+\s*$/.test(span.innerText()) + ) { + span.parentNode.removeChild(span); + } + }); + } + }); + + //调整索引标签 + me.addListener("contentchange", function () { + adjustListStyle(me.document); + }); + + function adjustListStyle(doc, ignore) { + utils.each(domUtils.getElementsByTagName(doc, "ol ul"), function (node) { + if (!domUtils.inDoc(node, doc)) return; + + var parent = node.parentNode; + if (parent.tagName === node.tagName) { + var nodeStyleType = + getStyle(node) || (node.tagName === "OL" ? "decimal" : "disc"), + parentStyleType = + getStyle(parent) || (parent.tagName === "OL" ? "decimal" : "disc"); + if (nodeStyleType === parentStyleType) { + var styleIndex = utils.indexOf( + listStyle[node.tagName], + nodeStyleType + ); + styleIndex = styleIndex + 1 === listStyle[node.tagName].length + ? 0 + : styleIndex + 1; + setListStyle(node, listStyle[node.tagName][styleIndex]); + } + } + var index = 0, + type = 2; + if (domUtils.hasClass(node, /custom_/)) { + if ( + !( + /[ou]l/i.test(parent.tagName) && + domUtils.hasClass(parent, /custom_/) + ) + ) { + type = 1; + } + } else { + if ( + /[ou]l/i.test(parent.tagName) && + domUtils.hasClass(parent, /custom_/) + ) { + type = 3; + } + } + + var style = domUtils.getStyle(node, "list-style-type"); + style && (node.style.cssText = "list-style-type:" + style); + node.className = + utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) + + " list-paddingleft-" + + type; + utils.each(domUtils.getElementsByTagName(node, "li"), function (li) { + li.style.cssText && (li.style.cssText = ""); + if (!li.firstChild) { + domUtils.remove(li); + return; + } + if (li.parentNode !== node) { + return; + } + index++; + if (domUtils.hasClass(node, /custom_/)) { + var paddingLeft = 1, + currentStyle = getStyle(node); + if (node.tagName === "OL") { + if (currentStyle) { + switch (currentStyle) { + case "cn": + case "cn1": + case "cn2": + if ( + index > 10 && + (index % 10 === 0 || (index > 10 && index < 20)) + ) { + paddingLeft = 2; + } else if (index > 20) { + paddingLeft = 3; + } + break; + case "num2": + if (index > 9) { + paddingLeft = 2; + } + } + } + li.className = + // "list-" + + // customStyle[currentStyle] + + // index + + // " " + + "list-" + + currentStyle + + "-paddingleft-" + + paddingLeft; + } else { + li.className = + // "list-" + + // customStyle[currentStyle] + + // " " + + "list-" + + currentStyle + + "-paddingleft"; + } + } else { + li.className = li.className.replace(/list-[\w\-]+/gi, ""); + } + var className = li.getAttribute("class"); + if (className !== null && !className.replace(/\s/g, "")) { + domUtils.removeAttributes(li, "class"); + } + }); + !ignore && + adjustList( + node, + node.tagName.toLowerCase(), + getStyle(node) || domUtils.getStyle(node, "list-style-type"), + true + ); + }); + } + + function adjustList(list, tag, style, ignoreEmpty) { + var nextList = list.nextSibling; + if ( + nextList && + nextList.nodeType === 1 && + nextList.tagName.toLowerCase() === tag && + (getStyle(nextList) || + domUtils.getStyle(nextList, "list-style-type") || + (tag == "ol" ? "decimal" : "disc")) == style + ) { + domUtils.moveChild(nextList, list); + if (nextList.childNodes.length === 0) { + domUtils.remove(nextList); + } + } + if (nextList && domUtils.isFillChar(nextList)) { + domUtils.remove(nextList); + } + var preList = list.previousSibling; + if ( + preList && + preList.nodeType === 1 && + preList.tagName.toLowerCase() == tag && + (getStyle(preList) || + domUtils.getStyle(preList, "list-style-type") || + (tag == "ol" ? "decimal" : "disc")) === style + ) { + domUtils.moveChild(list, preList); + } + if (preList && domUtils.isFillChar(preList)) { + domUtils.remove(preList); + } + !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list); + if (getStyle(list)) { + adjustListStyle(list.ownerDocument, true); + } + } + + function setListStyle(list, style) { + // if (customStyle[style]) { + // list.className = "custom_" + style; + // } + try { + domUtils.setStyle(list, "list-style-type", style); + } catch (e) { + } + } + + function clearEmptySibling(node) { + var tmpNode = node.previousSibling; + if (tmpNode && domUtils.isEmptyBlock(tmpNode)) { + domUtils.remove(tmpNode); + } + tmpNode = node.nextSibling; + if (tmpNode && domUtils.isEmptyBlock(tmpNode)) { + domUtils.remove(tmpNode); + } + } + + me.addListener("keydown", function (type, evt) { + function preventAndSave() { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + me.fireEvent("contentchange"); + me.undoManger && me.undoManger.save(); + } + + function findList(node, filterFn) { + while (node && !domUtils.isBody(node)) { + if (filterFn(node)) { + return null; + } + if (node.nodeType === 1 && /[ou]l/i.test(node.tagName)) { + return node; + } + node = node.parentNode; + } + return null; + } + + var keyCode = evt.keyCode || evt.which; + if (keyCode === 13 && !evt.shiftKey) { + //回车 + var rng = me.selection.getRange(), + parent = domUtils.findParent( + rng.startContainer, + function (node) { + return domUtils.isBlockElm(node); + }, + true + ), + li = domUtils.findParentByTagName(rng.startContainer, "li", true); + if (parent && parent.tagName !== "PRE" && !li) { + var html = parent.innerHTML.replace( + new RegExp(domUtils.fillChar, "g"), + "" + ); + if (/^\s*1\s*\.[^\d]/.test(html)) { + parent.innerHTML = html.replace(/^\s*1\s*\./, ""); + rng.setStartAtLast(parent).collapse(true).select(); + me.__hasEnterExecCommand = true; + me.execCommand("insertorderedlist"); + me.__hasEnterExecCommand = false; + } + } + var range = me.selection.getRange(), + start = findList(range.startContainer, function (node) { + return node.tagName === "TABLE"; + }), + end = range.collapsed + ? start + : findList(range.endContainer, function (node) { + return node.tagName === "TABLE"; + }); + + if (start && end && start === end) { + if (!range.collapsed) { + start = domUtils.findParentByTagName( + range.startContainer, + "li", + true + ); + end = domUtils.findParentByTagName(range.endContainer, "li", true); + if (start && end && start === end) { + range.deleteContents(); + li = domUtils.findParentByTagName(range.startContainer, "li", true); + if (li && domUtils.isEmptyBlock(li)) { + pre = li.previousSibling; + next = li.nextSibling; + p = me.document.createElement("p"); + + domUtils.fillNode(me.document, p); + parentList = li.parentNode; + if (pre && next) { + range.setStart(next, 0).collapse(true).select(true); + domUtils.remove(li); + } else { + if ((!pre && !next) || !pre) { + parentList.parentNode.insertBefore(p, parentList); + } else { + li.parentNode.parentNode.insertBefore( + p, + parentList.nextSibling + ); + } + domUtils.remove(li); + if (!parentList.firstChild) { + domUtils.remove(parentList); + } + range.setStart(p, 0).setCursor(); + } + preventAndSave(); + return; + } + } else { + var tmpRange = range.cloneRange(), + bk = tmpRange.collapse(false).createBookmark(); + + range.deleteContents(); + tmpRange.moveToBookmark(bk); + var li = domUtils.findParentByTagName( + tmpRange.startContainer, + "li", + true + ); + + clearEmptySibling(li); + tmpRange.select(); + preventAndSave(); + return; + } + } + + li = domUtils.findParentByTagName(range.startContainer, "li", true); + + if (li) { + if (domUtils.isEmptyBlock(li)) { + bk = range.createBookmark(); + var parentList = li.parentNode; + if (li !== parentList.lastChild) { + domUtils.breakParent(li, parentList); + clearEmptySibling(li); + } else { + parentList.parentNode.insertBefore(li, parentList.nextSibling); + if (domUtils.isEmptyNode(parentList)) { + domUtils.remove(parentList); + } + } + //嵌套不处理 + if (!dtd.$list[li.parentNode.tagName]) { + if (!domUtils.isBlockElm(li.firstChild)) { + p = me.document.createElement("p"); + li.parentNode.insertBefore(p, li); + while (li.firstChild) { + p.appendChild(li.firstChild); + } + domUtils.remove(li); + } else { + domUtils.remove(li, true); + } + } + range.moveToBookmark(bk).select(); + } else { + var first = li.firstChild; + if (!first || !domUtils.isBlockElm(first)) { + var p = me.document.createElement("p"); + + !li.firstChild && domUtils.fillNode(me.document, p); + while (li.firstChild) { + p.appendChild(li.firstChild); + } + li.appendChild(p); + first = p; + } + + var span = me.document.createElement("span"); + + range.insertNode(span); + domUtils.breakParent(span, li); + + var nextLi = span.nextSibling; + first = nextLi.firstChild; + + if (!first) { + p = me.document.createElement("p"); + + domUtils.fillNode(me.document, p); + nextLi.appendChild(p); + first = p; + } + if (domUtils.isEmptyNode(first)) { + first.innerHTML = ""; + domUtils.fillNode(me.document, first); + } + + range.setStart(first, 0).collapse(true).shrinkBoundary().select(); + domUtils.remove(span); + var pre = nextLi.previousSibling; + if (pre && domUtils.isEmptyBlock(pre)) { + pre.innerHTML = "

    "; + domUtils.fillNode(me.document, pre.firstChild); + } + } + // } + preventAndSave(); + } + } + } + if (keyCode === 8) { + //修中ie中li下的问题 + range = me.selection.getRange(); + if (range.collapsed && domUtils.isStartInblock(range)) { + tmpRange = range.cloneRange().trimBoundary(); + li = domUtils.findParentByTagName(range.startContainer, "li", true); + //要在li的最左边,才能处理 + if (li && domUtils.isStartInblock(tmpRange)) { + start = domUtils.findParentByTagName(range.startContainer, "p", true); + if (start && start !== li.firstChild) { + var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]); + domUtils.breakParent(start, parentList); + clearEmptySibling(start); + me.fireEvent("contentchange"); + range.setStart(start, 0).setCursor(false, true); + me.fireEvent("saveScene"); + domUtils.preventDefault(evt); + return; + } + + if (li && (pre = li.previousSibling)) { + if (keyCode === 46 && li.childNodes.length) { + return; + } + //有可能上边的兄弟节点是个2级菜单,要追加到2级菜单的最后的li + if (dtd.$list[pre.tagName]) { + pre = pre.lastChild; + } + me.undoManger && me.undoManger.save(); + first = li.firstChild; + if (domUtils.isBlockElm(first)) { + if (domUtils.isEmptyNode(first)) { + // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); + pre.appendChild(first); + range.setStart(first, 0).setCursor(false, true); + //first不是唯一的节点 + while (li.firstChild) { + pre.appendChild(li.firstChild); + } + } else { + span = me.document.createElement("span"); + range.insertNode(span); + //判断pre是否是空的节点,如果是


    类型的空节点,干掉p标签防止它占位 + if (domUtils.isEmptyBlock(pre)) { + pre.innerHTML = ""; + } + domUtils.moveChild(li, pre); + range.setStartBefore(span).collapse(true).select(true); + + domUtils.remove(span); + } + } else { + if (domUtils.isEmptyNode(li)) { + var p = me.document.createElement("p"); + pre.appendChild(p); + range.setStart(p, 0).setCursor(); + // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); + } else { + range + .setEnd(pre, pre.childNodes.length) + .collapse() + .select(true); + while (li.firstChild) { + pre.appendChild(li.firstChild); + } + } + } + domUtils.remove(li); + me.fireEvent("contentchange"); + me.fireEvent("saveScene"); + domUtils.preventDefault(evt); + return; + } + //trace:980 + + if (li && !li.previousSibling) { + var parentList = li.parentNode; + var bk = range.createBookmark(); + if (domUtils.isTagNode(parentList.parentNode, "ol ul")) { + parentList.parentNode.insertBefore(li, parentList); + if (domUtils.isEmptyNode(parentList)) { + domUtils.remove(parentList); + } + } else { + while (li.firstChild) { + parentList.parentNode.insertBefore(li.firstChild, parentList); + } + + domUtils.remove(li); + if (domUtils.isEmptyNode(parentList)) { + domUtils.remove(parentList); + } + } + range.moveToBookmark(bk).setCursor(false, true); + me.fireEvent("contentchange"); + me.fireEvent("saveScene"); + domUtils.preventDefault(evt); + return; + } + } + } + } + }); + + me.addListener("keyup", function (type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 8) { + var rng = me.selection.getRange(), + list; + if ( + (list = domUtils.findParentByTagName( + rng.startContainer, + ["ol", "ul"], + true + )) + ) { + adjustList( + list, + list.tagName.toLowerCase(), + getStyle(list) || domUtils.getComputedStyle(list, "list-style-type"), + true + ); + } + } + }); + //处理tab键 + me.addListener("tabkeydown", function () { + var range = me.selection.getRange(); + + //控制级数 + function checkLevel(li) { + if (me.options.maxListLevel != -1) { + var level = li.parentNode, + levelNum = 0; + while (/[ou]l/i.test(level.tagName)) { + levelNum++; + level = level.parentNode; + } + if (levelNum >= me.options.maxListLevel) { + return true; + } + } + } + + //只以开始为准 + //todo 后续改进 + var li = domUtils.findParentByTagName(range.startContainer, "li", true); + if (li) { + var bk; + if (range.collapsed) { + if (checkLevel(li)) return true; + var parentLi = li.parentNode, + list = me.document.createElement(parentLi.tagName), + index = utils.indexOf( + listStyle[list.tagName], + getStyle(parentLi) || + domUtils.getComputedStyle(parentLi, "list-style-type") + ); + index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1; + var currentStyle = listStyle[list.tagName][index]; + setListStyle(list, currentStyle); + if (domUtils.isStartInblock(range)) { + me.fireEvent("saveScene"); + bk = range.createBookmark(); + parentLi.insertBefore(list, li); + list.appendChild(li); + adjustList(list, list.tagName.toLowerCase(), currentStyle); + me.fireEvent("contentchange"); + range.moveToBookmark(bk).select(true); + return true; + } + } else { + me.fireEvent("saveScene"); + bk = range.createBookmark(); + for ( + var i = 0, closeList, parents = domUtils.findParents(li), ci; + (ci = parents[i++]); + ) { + if (domUtils.isTagNode(ci, "ol ul")) { + closeList = ci; + break; + } + } + var current = li; + if (bk.end) { + while ( + current && + !( + domUtils.getPosition(current, bk.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + if (checkLevel(current)) { + current = domUtils.getNextDomNode(current, false, null, function ( + node + ) { + return node !== closeList; + }); + continue; + } + var parentLi = current.parentNode, + list = me.document.createElement(parentLi.tagName), + index = utils.indexOf( + listStyle[list.tagName], + getStyle(parentLi) || + domUtils.getComputedStyle(parentLi, "list-style-type") + ); + var currentIndex = index + 1 == listStyle[list.tagName].length + ? 0 + : index + 1; + var currentStyle = listStyle[list.tagName][currentIndex]; + setListStyle(list, currentStyle); + parentLi.insertBefore(list, current); + while ( + current && + !( + domUtils.getPosition(current, bk.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + li = current.nextSibling; + list.appendChild(current); + if (!li || domUtils.isTagNode(li, "ol ul")) { + if (li) { + while ((li = li.firstChild)) { + if (li.tagName == "LI") { + break; + } + } + } else { + li = domUtils.getNextDomNode(current, false, null, function ( + node + ) { + return node !== closeList; + }); + } + break; + } + current = li; + } + adjustList(list, list.tagName.toLowerCase(), currentStyle); + current = li; + } + } + me.fireEvent("contentchange"); + range.moveToBookmark(bk).select(); + return true; + } + } + }); + + function getLi(start) { + while (start && !domUtils.isBody(start)) { + if (start.nodeName == "TABLE") { + return null; + } + if (start.nodeName == "LI") { + return start; + } + start = start.parentNode; + } + } + + /** + * 有序列表,与“insertunorderedlist”命令互斥 + * @command insertorderedlist + * @method execCommand + * @param { String } command 命令字符串 + * @param { String } style 插入的有序列表类型,值为:decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2 + * @example + * ```javascript + * editor.execCommand( 'insertorderedlist','decimal'); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertorderedlist + * @method queryCommandState + * @param { String } cmd 命令字符串 + * @return { int } 如果当前选区是有序列表返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'insertorderedlist' ); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertorderedlist + * @method queryCommandValue + * @param { String } cmd 命令字符串 + * @return { String } 返回当前有序列表的类型,值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2 + * @example + * ```javascript + * editor.queryCommandValue( 'insertorderedlist' ); * ``` */ - me.commands["source"] = { - execCommand: function() { - sourceMode = !sourceMode; - if (sourceMode) { - bakAddress = me.selection.getRange().createAddress(false, true); - me.undoManger && me.undoManger.save(true); - if (browser.gecko) { - me.body.contentEditable = false; - } + /** + * 无序列表,与“insertorderedlist”命令互斥 + * @command insertunorderedlist + * @method execCommand + * @param { String } command 命令字符串 + * @param { String } style 插入的无序列表类型,值为:circle,disc,square,dash,dot + * @example + * ```javascript + * editor.execCommand( 'insertunorderedlist','circle'); + * ``` + */ + /** + * 查询当前是否有word文档粘贴进来的图片 + * @command insertunorderedlist + * @method insertunorderedlist + * @param { String } command 命令字符串 + * @return { int } 如果当前选区是无序列表返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'insertunorderedlist' ); + * ``` + */ + /** + * 查询当前选区内容是否有序列表 + * @command insertunorderedlist + * @method queryCommandValue + * @param { String } command 命令字符串 + * @return { String } 返回当前无序列表的类型,值为null或circle,disc,square,dash,dot + * @example + * ```javascript + * editor.queryCommandValue( 'insertunorderedlist' ); + * ``` + */ - bakCssText = me.iframe.style.cssText; - me.iframe.style.cssText += - "position:absolute;left:-32768px;top:-32768px;"; + me.commands["insertorderedlist"] = me.commands["insertunorderedlist"] = { + execCommand: function (command, style) { + if (!style) { + style = command.toLowerCase() == "insertorderedlist" + ? "decimal" + : "disc"; + } + var me = this, + range = this.selection.getRange(), + filterFn = function (node) { + return node.nodeType == 1 + ? node.tagName.toLowerCase() != "br" + : !domUtils.isWhitespace(node); + }, + tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul", + frag = me.document.createDocumentFragment(); + //去掉是因为会出现选到末尾,导致adjustmentBoundary缩到ol/ul的位置 + //range.shrinkBoundary();//.adjustmentBoundary(); + range.adjustmentBoundary().shrinkBoundary(); + var bko = range.createBookmark(true), + start = getLi(me.document.getElementById(bko.start)), + modifyStart = 0, + end = getLi(me.document.getElementById(bko.end)), + modifyEnd = 0, + startParent, + endParent, + list, + tmp; - me.fireEvent("beforegetcontent"); - var root = UE.htmlparser(me.body.innerHTML); - me.filterOutputRule(root); - root.traversal(function(node) { - if (node.type == "element") { - switch (node.tagName) { - case "td": - case "th": - case "caption": - if (node.children && node.children.length == 1) { - if (node.firstChild().tagName == "br") { - node.removeChild(node.firstChild()); + if (start || end) { + start && (startParent = start.parentNode); + if (!bko.end) { + end = start; } - } - break; - case "pre": - node.innerText(node.innerText().replace(/ /g, " ")); - } + end && (endParent = end.parentNode); + + if (startParent === endParent) { + while (start !== end) { + tmp = start; + start = start.nextSibling; + if (!domUtils.isBlockElm(tmp.firstChild)) { + var p = me.document.createElement("p"); + while (tmp.firstChild) { + p.appendChild(tmp.firstChild); + } + tmp.appendChild(p); + } + frag.appendChild(tmp); + } + tmp = me.document.createElement("span"); + startParent.insertBefore(tmp, end); + if (!domUtils.isBlockElm(end.firstChild)) { + p = me.document.createElement("p"); + while (end.firstChild) { + p.appendChild(end.firstChild); + } + end.appendChild(p); + } + frag.appendChild(end); + domUtils.breakParent(tmp, startParent); + if (domUtils.isEmptyNode(tmp.previousSibling)) { + domUtils.remove(tmp.previousSibling); + } + if (domUtils.isEmptyNode(tmp.nextSibling)) { + domUtils.remove(tmp.nextSibling); + } + var nodeStyle = + getStyle(startParent) || + domUtils.getComputedStyle(startParent, "list-style-type") || + (command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc"); + if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) { + for ( + var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); + (ci = frag.firstChild); + ) { + if (domUtils.isTagNode(ci, "ol ul")) { + // 删除时,子列表不处理 + // utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){ + // while(li.firstChild){ + // tmpFrag.appendChild(li.firstChild); + // } + // + // }); + tmpFrag.appendChild(ci); + } else { + while (ci.firstChild) { + tmpFrag.appendChild(ci.firstChild); + domUtils.remove(ci); + } + } + } + tmp.parentNode.insertBefore(tmpFrag, tmp); + } else { + list = me.document.createElement(tag); + setListStyle(list, style); + list.appendChild(frag); + tmp.parentNode.insertBefore(list, tmp); + } + + domUtils.remove(tmp); + list && adjustList(list, tag, style); + range.moveToBookmark(bko).select(); + return; + } + //开始 + if (start) { + while (start) { + tmp = start.nextSibling; + if (domUtils.isTagNode(start, "ol ul")) { + frag.appendChild(start); + } else { + var tmpfrag = me.document.createDocumentFragment(), + hasBlock = 0; + while (start.firstChild) { + if (domUtils.isBlockElm(start.firstChild)) { + hasBlock = 1; + } + tmpfrag.appendChild(start.firstChild); + } + if (!hasBlock) { + var tmpP = me.document.createElement("p"); + tmpP.appendChild(tmpfrag); + frag.appendChild(tmpP); + } else { + frag.appendChild(tmpfrag); + } + domUtils.remove(start); + } + + start = tmp; + } + startParent.parentNode.insertBefore(frag, startParent.nextSibling); + if (domUtils.isEmptyNode(startParent)) { + range.setStartBefore(startParent); + domUtils.remove(startParent); + } else { + range.setStartAfter(startParent); + } + modifyStart = 1; + } + + if (end && domUtils.inDoc(endParent, me.document)) { + //结束 + start = endParent.firstChild; + while (start && start !== end) { + tmp = start.nextSibling; + if (domUtils.isTagNode(start, "ol ul")) { + frag.appendChild(start); + } else { + tmpfrag = me.document.createDocumentFragment(); + hasBlock = 0; + while (start.firstChild) { + if (domUtils.isBlockElm(start.firstChild)) { + hasBlock = 1; + } + tmpfrag.appendChild(start.firstChild); + } + if (!hasBlock) { + tmpP = me.document.createElement("p"); + tmpP.appendChild(tmpfrag); + frag.appendChild(tmpP); + } else { + frag.appendChild(tmpfrag); + } + domUtils.remove(start); + } + start = tmp; + } + var tmpDiv = domUtils.createElement(me.document, "div", { + tmpDiv: 1 + }); + domUtils.moveChild(end, tmpDiv); + + frag.appendChild(tmpDiv); + domUtils.remove(end); + endParent.parentNode.insertBefore(frag, endParent); + range.setEndBefore(endParent); + if (domUtils.isEmptyNode(endParent)) { + domUtils.remove(endParent); + } + + modifyEnd = 1; + } + } + + if (!modifyStart) { + range.setStartBefore(me.document.getElementById(bko.start)); + } + if (bko.end && !modifyEnd) { + range.setEndAfter(me.document.getElementById(bko.end)); + } + range.enlarge(true, function (node) { + return notExchange[node.tagName]; + }); + + frag = me.document.createDocumentFragment(); + + var bk = range.createBookmark(), + current = domUtils.getNextDomNode(bk.start, false, filterFn), + tmpRange = range.cloneRange(), + tmpNode, + block = domUtils.isBlockElm; + + while ( + current && + current !== bk.end && + domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING + ) { + if (current.nodeType == 3 || dtd.li[current.tagName]) { + if (current.nodeType == 1 && dtd.$list[current.tagName]) { + while (current.firstChild) { + frag.appendChild(current.firstChild); + } + tmpNode = domUtils.getNextDomNode(current, false, filterFn); + domUtils.remove(current); + current = tmpNode; + continue; + } + tmpNode = current; + tmpRange.setStartBefore(current); + + while ( + current && + current !== bk.end && + (!block(current) || domUtils.isBookmarkNode(current)) + ) { + tmpNode = current; + current = domUtils.getNextDomNode(current, false, null, function ( + node + ) { + return !notExchange[node.tagName]; + }); + } + + if (current && block(current)) { + tmp = domUtils.getNextDomNode(tmpNode, false, filterFn); + if (tmp && domUtils.isBookmarkNode(tmp)) { + current = domUtils.getNextDomNode(tmp, false, filterFn); + tmpNode = tmp; + } + } + tmpRange.setEndAfter(tmpNode); + + current = domUtils.getNextDomNode(tmpNode, false, filterFn); + + var li = range.document.createElement("li"); + + li.appendChild(tmpRange.extractContents()); + if (domUtils.isEmptyNode(li)) { + var tmpNode = range.document.createElement("p"); + while (li.firstChild) { + tmpNode.appendChild(li.firstChild); + } + li.appendChild(tmpNode); + } + frag.appendChild(li); + } else { + current = domUtils.getNextDomNode(current, true, filterFn); + } + } + range.moveToBookmark(bk).collapse(true); + list = me.document.createElement(tag); + setListStyle(list, style); + list.appendChild(frag); + range.insertNode(list); + //当前list上下看能否合并 + adjustList(list, tag, style); + //去掉冗余的tmpDiv + for ( + var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, "div"); + (ci = tmpDivs[i++]); + ) { + if (ci.getAttribute("tmpDiv")) { + domUtils.remove(ci, true); + } + } + range.moveToBookmark(bko).select(); + }, + queryCommandState: function (command) { + var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul"; + var path = this.selection.getStartElementPath(); + for (var i = 0, ci; (ci = path[i++]);) { + if (ci.nodeName == "TABLE") { + return 0; + } + if (tag == ci.nodeName.toLowerCase()) { + return 1; + } + } + return 0; + }, + queryCommandValue: function (command) { + var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul"; + var path = this.selection.getStartElementPath(), + node; + for (var i = 0, ci; (ci = path[i++]);) { + if (ci.nodeName == "TABLE") { + node = null; + break; + } + if (tag == ci.nodeName.toLowerCase()) { + node = ci; + break; + } + } + return node + ? getStyle(node) || domUtils.getComputedStyle(node, "list-style-type") + : null; } - }); - - me.fireEvent("aftergetcontent"); - - var content = root.toHtml(true); - - sourceEditor = createSourceEditor(me.iframe.parentNode); - - sourceEditor.setContent(content); - - orgSetContent = me.setContent; - - me.setContent = function(html) { - //这里暂时不触发事件,防止报错 - var root = UE.htmlparser(html); - me.filterInputRule(root); - html = root.toHtml(); - sourceEditor.setContent(html); - }; - - setTimeout(function() { - sourceEditor.select(); - me.addListener("fullscreenchanged", function() { - try { - sourceEditor.getCodeMirror().refresh(); - } catch (e) {} - }); - }); - - //重置getContent,源码模式下取值也能是最新的数据 - oldGetContent = me.getContent; - me.getContent = function() { - return ( - sourceEditor.getContent() || - "

    " + (browser.ie ? "" : "
    ") + "

    " - ); - }; - - orgFocus = me.focus; - orgBlur = me.blur; - - me.focus = function(){ - sourceEditor.focus(); - }; - - me.blur = function(){ - orgBlur.call(me); - sourceEditor.blur(); - }; - } else { - me.iframe.style.cssText = bakCssText; - var cont = - sourceEditor.getContent() || - "

    " + (browser.ie ? "" : "
    ") + "

    "; - //处理掉block节点前后的空格,有可能会误命中,暂时不考虑 - cont = cont.replace( - new RegExp("[\\r\\t\\n ]*]*)>", "g"), - function(a, b) { - if (b && !dtd.$inlineWithA[b.toLowerCase()]) { - return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g, ""); - } - return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g, ""); - } - ); - - me.setContent = orgSetContent; - - me.setContent(cont); - sourceEditor.dispose(); - sourceEditor = null; - //还原getContent方法 - me.getContent = oldGetContent; - - me.focus = orgFocus; - me.blur = orgBlur; - - var first = me.body.firstChild; - //trace:1106 都删除空了,下边会报错,所以补充一个p占位 - if (!first) { - me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; - first = me.body.firstChild; - } - - //要在ifm为显示时ff才能取到selection,否则报错 - //这里不能比较位置了 - me.undoManger && me.undoManger.save(true); - - if (browser.gecko) { - var input = document.createElement("input"); - input.style.cssText = "position:absolute;left:0;top:-32768px"; - - document.body.appendChild(input); - - me.body.contentEditable = false; - setTimeout(function() { - domUtils.setViewportOffset(input, { left: -32768, top: 0 }); - input.focus(); - setTimeout(function() { - me.body.contentEditable = true; - me.selection.getRange().moveToAddress(bakAddress).select(true); - domUtils.remove(input); - }); - }); - } else { - //ie下有可能报错,比如在代码顶头的情况 - try { - me.selection.getRange().moveToAddress(bakAddress).select(true); - } catch (e) {} - } - } - this.fireEvent("sourcemodechanged", sourceMode); - }, - queryCommandState: function() { - return sourceMode | 0; - }, - notNeedUndo: 1 - }; - var oldQueryCommandState = me.queryCommandState; - - me.queryCommandState = function(cmdName) { - cmdName = cmdName.toLowerCase(); - if (sourceMode) { - //源码模式下可以开启的命令 - return cmdName in - { - source: 1, - fullscreen: 1 - } - ? 1 - : -1; - } - return oldQueryCommandState.apply(this, arguments); + }; }; - if (opt.sourceEditor == "codemirror") { - me.addListener("ready", function() { - utils.loadFile( - document, - { - src: - opt.codeMirrorJsUrl || - opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.js", - tag: "script", - type: "text/javascript", - defer: "defer" - }, - function() { - if (opt.sourceEditorFirst) { - setTimeout(function() { - me.execCommand("source"); - }, 0); + +// plugins/source.js + /** + * 源码编辑插件 + * @file + * @since 1.2.6.1 + */ + + (function () { + var sourceEditors = { + textarea: function (editor, holder) { + var textarea = holder.ownerDocument.createElement("textarea"); + textarea.style.cssText = + "position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;"; + // todo: IE下只有onresize属性可用... 很纠结 + if (browser.ie && browser.version < 8) { + textarea.style.width = holder.offsetWidth + "px"; + textarea.style.height = holder.offsetHeight + "px"; + holder.onresize = function () { + textarea.style.width = holder.offsetWidth + "px"; + textarea.style.height = holder.offsetHeight + "px"; + }; + } + holder.appendChild(textarea); + return { + setContent: function (content) { + textarea.value = content; + }, + getContent: function () { + return textarea.value; + }, + select: function () { + var range; + if (browser.ie) { + range = textarea.createTextRange(); + range.collapse(true); + range.select(); + } else { + //todo: chrome下无法设置焦点 + textarea.setSelectionRange(0, 0); + textarea.focus(); + } + }, + dispose: function () { + holder.removeChild(textarea); + // todo + holder.onresize = null; + textarea = null; + holder = null; + }, + focus: function () { + textarea.focus(); + }, + blur: function () { + textarea.blur(); + } + }; + }, + codemirror: function (editor, holder) { + var codeEditor = window.CodeMirror(holder, { + mode: "text/html", + tabMode: "indent", + lineNumbers: true, + lineWrapping: true, + onChange: function (v) { + editor.sync(); + editor.fireEvent("contentchange"); + // console.log('CodeMirror.onChange',v.getValue()); + } + }); + // console.log('sourceEditor',codeEditor); + var dom = codeEditor.getWrapperElement(); + dom.style.cssText = + 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;'; + codeEditor.getScrollerElement().style.cssText = + "position:absolute;left:0;top:0;width:100%;height:100%;"; + codeEditor.refresh(); + return { + getCodeMirror: function () { + return codeEditor; + }, + setContent: function (content) { + codeEditor.setValue(content); + }, + getContent: function () { + return codeEditor.getValue(); + }, + select: function () { + codeEditor.focus(); + }, + dispose: function () { + holder.removeChild(dom); + dom = null; + codeEditor = null; + }, + focus: function () { + codeEditor.focus(); + }, + blur: function () { + // codeEditor.blur(); + // since codemirror not support blur() + codeEditor.setOption('readOnly', true); + codeEditor.setOption('readOnly', false); + } + }; } - } - ); - utils.loadFile(document, { - tag: "link", - rel: "stylesheet", - type: "text/css", - href: - opt.codeMirrorCssUrl || - opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.css?221123" - }); - }); - } - }; -})(); + }; + + UE.plugins["source"] = function () { + var me = this; + var opt = this.options; + var sourceMode = false; + var sourceEditor; + var orgSetContent; + var orgFocus; + var orgBlur; + opt.sourceEditor = browser.ie + ? "textarea" + : opt.sourceEditor || "codemirror"; + + me.setOpt({ + sourceEditorFirst: false + }); + + function createSourceEditor(holder) { + return sourceEditors[ + opt.sourceEditor == "codemirror" && window.CodeMirror + ? "codemirror" + : "textarea" + ](me, holder); + } + + var bakCssText; + //解决在源码模式下getContent不能得到最新的内容问题 + var oldGetContent, bakAddress; + + /** + * 切换源码模式和编辑模式 + * @command source + * @method execCommand + * @param { String } cmd 命令字符串 + * @example + * ```javascript + * editor.execCommand( 'source'); + * ``` + */ + + /** + * 查询当前编辑区域的状态是源码模式还是可视化模式 + * @command source + * @method queryCommandState + * @param { String } cmd 命令字符串 + * @return { int } 如果当前是源码编辑模式,返回1,否则返回0 + * @example + * ```javascript + * editor.queryCommandState( 'source' ); + * ``` + */ + + me.commands["source"] = { + execCommand: function () { + sourceMode = !sourceMode; + if (sourceMode) { + bakAddress = me.selection.getRange().createAddress(false, true); + me.undoManger && me.undoManger.save(true); + if (browser.gecko) { + me.body.contentEditable = false; + } + + bakCssText = me.iframe.style.cssText; + me.iframe.style.cssText += + "position:absolute;left:-32768px;top:-32768px;"; + + me.fireEvent("beforegetcontent"); + var root = UE.htmlparser(me.body.innerHTML); + me.filterOutputRule(root); + root.traversal(function (node) { + if (node.type == "element") { + switch (node.tagName) { + case "td": + case "th": + case "caption": + if (node.children && node.children.length == 1) { + if (node.firstChild().tagName == "br") { + node.removeChild(node.firstChild()); + } + } + break; + case "pre": + node.innerText(node.innerText().replace(/ /g, " ")); + } + } + }); + + me.fireEvent("aftergetcontent"); + + var content = root.toHtml(true); + + sourceEditor = createSourceEditor(me.iframe.parentNode); + + sourceEditor.setContent(content); + + orgSetContent = me.setContent; + + me.setContent = function (html) { + //这里暂时不触发事件,防止报错 + var root = UE.htmlparser(html); + me.filterInputRule(root); + html = root.toHtml(); + sourceEditor.setContent(html); + }; + + setTimeout(function () { + sourceEditor.select(); + me.addListener("fullscreenchanged", function () { + try { + sourceEditor.getCodeMirror().refresh(); + } catch (e) { + } + }); + }); + + //重置getContent,源码模式下取值也能是最新的数据 + oldGetContent = me.getContent; + me.getContent = function () { + return ( + sourceEditor.getContent() || + "

    " + (browser.ie ? "" : "
    ") + "

    " + ); + }; + + orgFocus = me.focus; + orgBlur = me.blur; + + me.focus = function () { + sourceEditor.focus(); + }; + + me.blur = function () { + orgBlur.call(me); + sourceEditor.blur(); + }; + } else { + me.iframe.style.cssText = bakCssText; + var cont = + sourceEditor.getContent() || + "

    " + (browser.ie ? "" : "
    ") + "

    "; + //处理掉block节点前后的空格,有可能会误命中,暂时不考虑 + cont = cont.replace( + new RegExp("[\\r\\t\\n ]*]*)>", "g"), + function (a, b) { + if (b && !dtd.$inlineWithA[b.toLowerCase()]) { + return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g, ""); + } + return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g, ""); + } + ); + + me.setContent = orgSetContent; + + me.setContent(cont); + sourceEditor.dispose(); + sourceEditor = null; + //还原getContent方法 + me.getContent = oldGetContent; + + me.focus = orgFocus; + me.blur = orgBlur; + + var first = me.body.firstChild; + //trace:1106 都删除空了,下边会报错,所以补充一个p占位 + if (!first) { + me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; + first = me.body.firstChild; + } + + //要在ifm为显示时ff才能取到selection,否则报错 + //这里不能比较位置了 + me.undoManger && me.undoManger.save(true); + + if (browser.gecko) { + var input = document.createElement("input"); + input.style.cssText = "position:absolute;left:0;top:-32768px"; + + document.body.appendChild(input); + + me.body.contentEditable = false; + setTimeout(function () { + domUtils.setViewportOffset(input, {left: -32768, top: 0}); + input.focus(); + setTimeout(function () { + me.body.contentEditable = true; + me.selection.getRange().moveToAddress(bakAddress).select(true); + domUtils.remove(input); + }); + }); + } else { + //ie下有可能报错,比如在代码顶头的情况 + try { + me.selection.getRange().moveToAddress(bakAddress).select(true); + } catch (e) { + } + } + } + this.fireEvent("sourcemodechanged", sourceMode); + }, + queryCommandState: function () { + return sourceMode | 0; + }, + notNeedUndo: 1 + }; + var oldQueryCommandState = me.queryCommandState; + + me.queryCommandState = function (cmdName) { + cmdName = cmdName.toLowerCase(); + if (sourceMode) { + //源码模式下可以开启的命令 + return cmdName in + { + source: 1, + fullscreen: 1 + } + ? 1 + : -1; + } + return oldQueryCommandState.apply(this, arguments); + }; + + if (opt.sourceEditor == "codemirror") { + me.addListener("ready", function () { + utils.loadFile( + document, + { + src: + opt.codeMirrorJsUrl || + opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.js", + tag: "script", + type: "text/javascript", + defer: "defer" + }, + function () { + if (opt.sourceEditorFirst) { + setTimeout(function () { + me.execCommand("source"); + }, 0); + } + } + ); + utils.loadFile(document, { + tag: "link", + rel: "stylesheet", + type: "text/css", + href: + opt.codeMirrorCssUrl || + opt.UEDITOR_HOME_URL + "third-party/codemirror/codemirror.css?221123" + }); + }); + } + }; + })(); // plugins/enterkey.js @@ -18511,469 +21810,469 @@ UE.plugins["list"] = function() { ///commands 设置回车标签p或br ///commandsName EnterKey ///commandsTitle 设置回车标签p或br -/** - * @description 处理回车 - * @author zhanyi - */ -UE.plugins["enterkey"] = function() { - var hTag, - me = this, - tag = me.options.enterTag; - me.addListener("keyup", function(type, evt) { - var keyCode = evt.keyCode || evt.which; - if (keyCode == 13) { - var range = me.selection.getRange(), - start = range.startContainer, - doSave; + /** + * @description 处理回车 + * @author zhanyi + */ + UE.plugins["enterkey"] = function () { + var hTag, + me = this, + tag = me.options.enterTag; + me.addListener("keyup", function (type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) { + var range = me.selection.getRange(), + start = range.startContainer, + doSave; - //修正在h1-h6里边回车后不能嵌套p的问题 - if (!browser.ie) { - if (/h\d/i.test(hTag)) { - if (browser.gecko) { - var h = domUtils.findParentByTagName( - start, - [ - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "blockquote", - "caption", - "table" - ], - true - ); - if (!h) { - me.document.execCommand("formatBlock", false, "

    "); - doSave = 1; - } - } else { - //chrome remove div - if (start.nodeType == 1) { - var tmp = me.document.createTextNode(""), - div; - range.insertNode(tmp); - div = domUtils.findParentByTagName(tmp, "div", true); - if (div) { - var p = me.document.createElement("p"); - while (div.firstChild) { - p.appendChild(div.firstChild); + //修正在h1-h6里边回车后不能嵌套p的问题 + if (!browser.ie) { + if (/h\d/i.test(hTag)) { + if (browser.gecko) { + var h = domUtils.findParentByTagName( + start, + [ + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "blockquote", + "caption", + "table" + ], + true + ); + if (!h) { + me.document.execCommand("formatBlock", false, "

    "); + doSave = 1; + } + } else { + //chrome remove div + if (start.nodeType == 1) { + var tmp = me.document.createTextNode(""), + div; + range.insertNode(tmp); + div = domUtils.findParentByTagName(tmp, "div", true); + if (div) { + var p = me.document.createElement("p"); + while (div.firstChild) { + p.appendChild(div.firstChild); + } + div.parentNode.insertBefore(p, div); + domUtils.remove(div); + range.setStartBefore(tmp).setCursor(); + doSave = 1; + } + domUtils.remove(tmp); + } + } + + if (me.undoManger && doSave) { + me.undoManger.save(); + } + } + //没有站位符,会出现多行的问题 + browser.opera && range.select(); + } else { + me.fireEvent("saveScene", true, true); } - div.parentNode.insertBefore(p, div); - domUtils.remove(div); - range.setStartBefore(tmp).setCursor(); - doSave = 1; - } - domUtils.remove(tmp); } - } + }); - if (me.undoManger && doSave) { - me.undoManger.save(); - } - } - //没有站位符,会出现多行的问题 - browser.opera && range.select(); - } else { - me.fireEvent("saveScene", true, true); - } - } - }); - - me.addListener("keydown", function(type, evt) { - var keyCode = evt.keyCode || evt.which; - if (keyCode == 13) { - //回车 - if (me.fireEvent("beforeenterkeydown")) { - domUtils.preventDefault(evt); - return; - } - me.fireEvent("saveScene", true, true); - hTag = ""; - - var range = me.selection.getRange(); - - if (!range.collapsed) { - //跨td不能删 - var start = range.startContainer, - end = range.endContainer, - startTd = domUtils.findParentByTagName(start, "td", true), - endTd = domUtils.findParentByTagName(end, "td", true); - if ( - (startTd && endTd && startTd !== endTd) || - (!startTd && endTd) || - (startTd && !endTd) - ) { - evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); - return; - } - } - if (tag == "p") { - if (!browser.ie) { - start = domUtils.findParentByTagName( - range.startContainer, - [ - "ol", - "ul", - "p", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "blockquote", - "caption" - ], - true - ); - - //opera下执行formatblock会在table的场景下有问题,回车在opera原生支持很好,所以暂时在opera去掉调用这个原生的command - //trace:2431 - if (!start && !browser.opera) { - me.document.execCommand("formatBlock", false, "

    "); - - if (browser.gecko) { - range = me.selection.getRange(); - start = domUtils.findParentByTagName( - range.startContainer, - "p", - true - ); - start && domUtils.removeDirtyAttr(start); - } - } else { - hTag = start.tagName; - start.tagName.toLowerCase() == "p" && - browser.gecko && - domUtils.removeDirtyAttr(start); - } - } - } else { - evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); - - if (!range.collapsed) { - range.deleteContents(); - start = range.startContainer; - if ( - start.nodeType == 1 && - (start = start.childNodes[range.startOffset]) - ) { - while (start.nodeType == 1) { - if (dtd.$empty[start.tagName]) { - range.setStartBefore(start).setCursor(); - if (me.undoManger) { - me.undoManger.save(); + me.addListener("keydown", function (type, evt) { + var keyCode = evt.keyCode || evt.which; + if (keyCode == 13) { + //回车 + if (me.fireEvent("beforeenterkeydown")) { + domUtils.preventDefault(evt); + return; } - return false; - } - if (!start.firstChild) { - var br = range.document.createElement("br"); - start.appendChild(br); - range.setStart(start, 0).setCursor(); - if (me.undoManger) { - me.undoManger.save(); + me.fireEvent("saveScene", true, true); + hTag = ""; + + var range = me.selection.getRange(); + + if (!range.collapsed) { + //跨td不能删 + var start = range.startContainer, + end = range.endContainer, + startTd = domUtils.findParentByTagName(start, "td", true), + endTd = domUtils.findParentByTagName(end, "td", true); + if ( + (startTd && endTd && startTd !== endTd) || + (!startTd && endTd) || + (startTd && !endTd) + ) { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + return; + } + } + if (tag == "p") { + if (!browser.ie) { + start = domUtils.findParentByTagName( + range.startContainer, + [ + "ol", + "ul", + "p", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "blockquote", + "caption" + ], + true + ); + + //opera下执行formatblock会在table的场景下有问题,回车在opera原生支持很好,所以暂时在opera去掉调用这个原生的command + //trace:2431 + if (!start && !browser.opera) { + me.document.execCommand("formatBlock", false, "

    "); + + if (browser.gecko) { + range = me.selection.getRange(); + start = domUtils.findParentByTagName( + range.startContainer, + "p", + true + ); + start && domUtils.removeDirtyAttr(start); + } + } else { + hTag = start.tagName; + start.tagName.toLowerCase() == "p" && + browser.gecko && + domUtils.removeDirtyAttr(start); + } + } + } else { + evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); + + if (!range.collapsed) { + range.deleteContents(); + start = range.startContainer; + if ( + start.nodeType == 1 && + (start = start.childNodes[range.startOffset]) + ) { + while (start.nodeType == 1) { + if (dtd.$empty[start.tagName]) { + range.setStartBefore(start).setCursor(); + if (me.undoManger) { + me.undoManger.save(); + } + return false; + } + if (!start.firstChild) { + var br = range.document.createElement("br"); + start.appendChild(br); + range.setStart(start, 0).setCursor(); + if (me.undoManger) { + me.undoManger.save(); + } + return false; + } + start = start.firstChild; + } + if (start === range.startContainer.childNodes[range.startOffset]) { + br = range.document.createElement("br"); + range.insertNode(br).setCursor(); + } else { + range.setStart(start, 0).setCursor(); + } + } else { + br = range.document.createElement("br"); + range.insertNode(br).setStartAfter(br).setCursor(); + } + } else { + br = range.document.createElement("br"); + range.insertNode(br); + var parent = br.parentNode; + if (parent.lastChild === br) { + br.parentNode.insertBefore(br.cloneNode(true), br); + range.setStartBefore(br); + } else { + range.setStartAfter(br); + } + range.setCursor(); + } } - return false; - } - start = start.firstChild; } - if (start === range.startContainer.childNodes[range.startOffset]) { - br = range.document.createElement("br"); - range.insertNode(br).setCursor(); - } else { - range.setStart(start, 0).setCursor(); - } - } else { - br = range.document.createElement("br"); - range.insertNode(br).setStartAfter(br).setCursor(); - } - } else { - br = range.document.createElement("br"); - range.insertNode(br); - var parent = br.parentNode; - if (parent.lastChild === br) { - br.parentNode.insertBefore(br.cloneNode(true), br); - range.setStartBefore(br); - } else { - range.setStartAfter(br); - } - range.setCursor(); - } - } - } - }); -}; + }); + }; // plugins/keystrokes.js -/* 处理特殊键的兼容性问题 */ -UE.plugins["keystrokes"] = function() { - var me = this; - var collapsed = true; - me.addListener("keydown", function(type, evt) { - var keyCode = evt.keyCode || evt.which, - rng = me.selection.getRange(); + /* 处理特殊键的兼容性问题 */ + UE.plugins["keystrokes"] = function () { + var me = this; + var collapsed = true; + me.addListener("keydown", function (type, evt) { + var keyCode = evt.keyCode || evt.which, + rng = me.selection.getRange(); - //处理全选的情况 - if ( - !rng.collapsed && - !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && - ((keyCode >= 65 && keyCode <= 90) || - (keyCode >= 48 && keyCode <= 57) || - (keyCode >= 96 && keyCode <= 111) || - { - 13: 1, - 8: 1, - 46: 1 - }[keyCode]) - ) { - var tmpNode = rng.startContainer; - if (domUtils.isFillChar(tmpNode)) { - rng.setStartBefore(tmpNode); - } - tmpNode = rng.endContainer; - if (domUtils.isFillChar(tmpNode)) { - rng.setEndAfter(tmpNode); - } - rng.txtToElmBoundary(); - //结束边界可能放到了br的前边,要把br包含进来 - // x[xxx]
    - if (rng.endContainer && rng.endContainer.nodeType == 1) { - tmpNode = rng.endContainer.childNodes[rng.endOffset]; - if (tmpNode && domUtils.isBr(tmpNode)) { - rng.setEndAfter(tmpNode); - } - } - if (rng.startOffset == 0) { - tmpNode = rng.startContainer; - if (domUtils.isBoundaryNode(tmpNode, "firstChild")) { - tmpNode = rng.endContainer; - if ( - rng.endOffset == - (tmpNode.nodeType == 3 - ? tmpNode.nodeValue.length - : tmpNode.childNodes.length) && - domUtils.isBoundaryNode(tmpNode, "lastChild") - ) { - me.fireEvent("saveScene"); - me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; - rng.setStart(me.body.firstChild, 0).setCursor(false, true); - me._selectionChange(); - return; - } - } - } - } - - //处理backspace - if (keyCode == keymap.Backspace) { - rng = me.selection.getRange(); - collapsed = rng.collapsed; - if (me.fireEvent("delkeydown", evt)) { - return; - } - var start, end; - //避免按两次删除才能生效的问题 - if (rng.collapsed && rng.inFillChar()) { - start = rng.startContainer; - - if (domUtils.isFillChar(start)) { - rng.setStartBefore(start).shrinkBoundary(true).collapse(true); - domUtils.remove(start); - } else { - start.nodeValue = start.nodeValue.replace( - new RegExp("^" + domUtils.fillChar), - "" - ); - rng.startOffset--; - rng.collapse(true).select(true); - } - } - - //解决选中control元素不能删除的问题 - if ((start = rng.getClosedNode())) { - me.fireEvent("saveScene"); - rng.setStartBefore(start); - domUtils.remove(start); - rng.setCursor(); - me.fireEvent("saveScene"); - domUtils.preventDefault(evt); - return; - } - //阻止在table上的删除 - if (!browser.ie) { - start = domUtils.findParentByTagName(rng.startContainer, "table", true); - end = domUtils.findParentByTagName(rng.endContainer, "table", true); - if ((start && !end) || (!start && end) || start !== end) { - evt.preventDefault(); - return; - } - } - } - //处理tab键的逻辑 - if (keyCode == keymap.Tab) { - //不处理以下标签 - var excludeTagNameForTabKey = { - ol: 1, - ul: 1, - table: 1 - }; - //处理组件里的tab按下事件 - if (me.fireEvent("tabkeydown", evt)) { - domUtils.preventDefault(evt); - return; - } - var range = me.selection.getRange(); - me.fireEvent("saveScene"); - for ( - var i = 0, - txt = "", - tabSize = me.options.tabSize || 4, - tabNode = me.options.tabNode || " "; - i < tabSize; - i++ - ) { - txt += tabNode; - } - var span = me.document.createElement("span"); - span.innerHTML = txt + domUtils.fillChar; - if (range.collapsed) { - range.insertNode(span.cloneNode(true).firstChild).setCursor(true); - } else { - var filterFn = function(node) { - return ( - domUtils.isBlockElm(node) && - !excludeTagNameForTabKey[node.tagName.toLowerCase()] - ); - }; - //普通的情况 - start = domUtils.findParent(range.startContainer, filterFn, true); - end = domUtils.findParent(range.endContainer, filterFn, true); - if (start && end && start === end) { - range.deleteContents(); - range.insertNode(span.cloneNode(true).firstChild).setCursor(true); - } else { - var bookmark = range.createBookmark(); - range.enlarge(true); - var bookmark2 = range.createBookmark(), - current = domUtils.getNextDomNode(bookmark2.start, false, filterFn); - while ( - current && - !( - domUtils.getPosition(current, bookmark2.end) & - domUtils.POSITION_FOLLOWING - ) - ) { - current.insertBefore( - span.cloneNode(true).firstChild, - current.firstChild - ); - current = domUtils.getNextDomNode(current, false, filterFn); - } - range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select(); - } - } - domUtils.preventDefault(evt); - } - //trace:1634 - //ff的del键在容器空的时候,也会删除 - if (browser.gecko && keyCode == 46) { - range = me.selection.getRange(); - if (range.collapsed) { - start = range.startContainer; - if (domUtils.isEmptyBlock(start)) { - var parent = start.parentNode; - while ( - domUtils.getChildCount(parent) == 1 && - !domUtils.isBody(parent) - ) { - start = parent; - parent = parent.parentNode; - } - if (start === parent.lastChild) evt.preventDefault(); - return; - } - } - } - - /* 修复在编辑区域快捷键 (Mac:meta+alt+I; Win:ctrl+shift+I) 打不开 chrome 控制台的问题 */ - browser.chrome && - me.on("keydown", function(type, e) { - var keyCode = e.keyCode || e.which; - if ( - ((e.metaKey && e.altKey) || (e.ctrlKey && e.shiftKey)) && - keyCode == 73 - ) { - return true; - } - }); - }); - me.addListener("keyup", function(type, evt) { - var keyCode = evt.keyCode || evt.which, - rng, - me = this; - if (keyCode == keymap.Backspace) { - if (me.fireEvent("delkeyup")) { - return; - } - rng = me.selection.getRange(); - if (rng.collapsed) { - var tmpNode, - autoClearTagName = ["h1", "h2", "h3", "h4", "h5", "h6"]; - if ( - (tmpNode = domUtils.findParentByTagName( - rng.startContainer, - autoClearTagName, - true - )) - ) { - if (domUtils.isEmptyBlock(tmpNode)) { - var pre = tmpNode.previousSibling; - if (pre && pre.nodeName != "TABLE") { - domUtils.remove(tmpNode); - rng.setStartAtLast(pre).setCursor(false, true); - return; - } else { - var next = tmpNode.nextSibling; - if (next && next.nodeName != "TABLE") { - domUtils.remove(tmpNode); - rng.setStartAtFirst(next).setCursor(false, true); - return; - } + //处理全选的情况 + if ( + !rng.collapsed && + !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && + ((keyCode >= 65 && keyCode <= 90) || + (keyCode >= 48 && keyCode <= 57) || + (keyCode >= 96 && keyCode <= 111) || + { + 13: 1, + 8: 1, + 46: 1 + }[keyCode]) + ) { + var tmpNode = rng.startContainer; + if (domUtils.isFillChar(tmpNode)) { + rng.setStartBefore(tmpNode); + } + tmpNode = rng.endContainer; + if (domUtils.isFillChar(tmpNode)) { + rng.setEndAfter(tmpNode); + } + rng.txtToElmBoundary(); + //结束边界可能放到了br的前边,要把br包含进来 + // x[xxx]
    + if (rng.endContainer && rng.endContainer.nodeType == 1) { + tmpNode = rng.endContainer.childNodes[rng.endOffset]; + if (tmpNode && domUtils.isBr(tmpNode)) { + rng.setEndAfter(tmpNode); + } + } + if (rng.startOffset == 0) { + tmpNode = rng.startContainer; + if (domUtils.isBoundaryNode(tmpNode, "firstChild")) { + tmpNode = rng.endContainer; + if ( + rng.endOffset == + (tmpNode.nodeType == 3 + ? tmpNode.nodeValue.length + : tmpNode.childNodes.length) && + domUtils.isBoundaryNode(tmpNode, "lastChild") + ) { + me.fireEvent("saveScene"); + me.body.innerHTML = "

    " + (browser.ie ? "" : "
    ") + "

    "; + rng.setStart(me.body.firstChild, 0).setCursor(false, true); + me._selectionChange(); + return; + } + } + } } - } - } - //处理当删除到body时,要重新给p标签展位 - if (domUtils.isBody(rng.startContainer)) { - var tmpNode = domUtils.createElement(me.document, "p", { - innerHTML: browser.ie ? domUtils.fillChar : "
    " - }); - rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true); - } - } - //chrome下如果删除了inline标签,浏览器会有记忆,在输入文字还是会套上刚才删除的标签,所以这里再选一次就不会了 - if ( - !collapsed && - (rng.startContainer.nodeType == 3 || - (rng.startContainer.nodeType == 1 && - domUtils.isEmptyBlock(rng.startContainer))) - ) { - if (browser.ie) { - var span = rng.document.createElement("span"); - rng.insertNode(span).setStartBefore(span).collapse(true); - rng.select(); - domUtils.remove(span); - } else { - rng.select(); - } - } - } - }); -}; + //处理backspace + if (keyCode == keymap.Backspace) { + rng = me.selection.getRange(); + collapsed = rng.collapsed; + if (me.fireEvent("delkeydown", evt)) { + return; + } + var start, end; + //避免按两次删除才能生效的问题 + if (rng.collapsed && rng.inFillChar()) { + start = rng.startContainer; + + if (domUtils.isFillChar(start)) { + rng.setStartBefore(start).shrinkBoundary(true).collapse(true); + domUtils.remove(start); + } else { + start.nodeValue = start.nodeValue.replace( + new RegExp("^" + domUtils.fillChar), + "" + ); + rng.startOffset--; + rng.collapse(true).select(true); + } + } + + //解决选中control元素不能删除的问题 + if ((start = rng.getClosedNode())) { + me.fireEvent("saveScene"); + rng.setStartBefore(start); + domUtils.remove(start); + rng.setCursor(); + me.fireEvent("saveScene"); + domUtils.preventDefault(evt); + return; + } + //阻止在table上的删除 + if (!browser.ie) { + start = domUtils.findParentByTagName(rng.startContainer, "table", true); + end = domUtils.findParentByTagName(rng.endContainer, "table", true); + if ((start && !end) || (!start && end) || start !== end) { + evt.preventDefault(); + return; + } + } + } + //处理tab键的逻辑 + if (keyCode == keymap.Tab) { + //不处理以下标签 + var excludeTagNameForTabKey = { + ol: 1, + ul: 1, + table: 1 + }; + //处理组件里的tab按下事件 + if (me.fireEvent("tabkeydown", evt)) { + domUtils.preventDefault(evt); + return; + } + var range = me.selection.getRange(); + me.fireEvent("saveScene"); + for ( + var i = 0, + txt = "", + tabSize = me.options.tabSize || 4, + tabNode = me.options.tabNode || " "; + i < tabSize; + i++ + ) { + txt += tabNode; + } + var span = me.document.createElement("span"); + span.innerHTML = txt + domUtils.fillChar; + if (range.collapsed) { + range.insertNode(span.cloneNode(true).firstChild).setCursor(true); + } else { + var filterFn = function (node) { + return ( + domUtils.isBlockElm(node) && + !excludeTagNameForTabKey[node.tagName.toLowerCase()] + ); + }; + //普通的情况 + start = domUtils.findParent(range.startContainer, filterFn, true); + end = domUtils.findParent(range.endContainer, filterFn, true); + if (start && end && start === end) { + range.deleteContents(); + range.insertNode(span.cloneNode(true).firstChild).setCursor(true); + } else { + var bookmark = range.createBookmark(); + range.enlarge(true); + var bookmark2 = range.createBookmark(), + current = domUtils.getNextDomNode(bookmark2.start, false, filterFn); + while ( + current && + !( + domUtils.getPosition(current, bookmark2.end) & + domUtils.POSITION_FOLLOWING + ) + ) { + current.insertBefore( + span.cloneNode(true).firstChild, + current.firstChild + ); + current = domUtils.getNextDomNode(current, false, filterFn); + } + range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select(); + } + } + domUtils.preventDefault(evt); + } + //trace:1634 + //ff的del键在容器空的时候,也会删除 + if (browser.gecko && keyCode == 46) { + range = me.selection.getRange(); + if (range.collapsed) { + start = range.startContainer; + if (domUtils.isEmptyBlock(start)) { + var parent = start.parentNode; + while ( + domUtils.getChildCount(parent) == 1 && + !domUtils.isBody(parent) + ) { + start = parent; + parent = parent.parentNode; + } + if (start === parent.lastChild) evt.preventDefault(); + return; + } + } + } + + /* 修复在编辑区域快捷键 (Mac:meta+alt+I; Win:ctrl+shift+I) 打不开 chrome 控制台的问题 */ + browser.chrome && + me.on("keydown", function (type, e) { + var keyCode = e.keyCode || e.which; + if ( + ((e.metaKey && e.altKey) || (e.ctrlKey && e.shiftKey)) && + keyCode == 73 + ) { + return true; + } + }); + }); + me.addListener("keyup", function (type, evt) { + var keyCode = evt.keyCode || evt.which, + rng, + me = this; + if (keyCode == keymap.Backspace) { + if (me.fireEvent("delkeyup")) { + return; + } + rng = me.selection.getRange(); + if (rng.collapsed) { + var tmpNode, + autoClearTagName = ["h1", "h2", "h3", "h4", "h5", "h6"]; + if ( + (tmpNode = domUtils.findParentByTagName( + rng.startContainer, + autoClearTagName, + true + )) + ) { + if (domUtils.isEmptyBlock(tmpNode)) { + var pre = tmpNode.previousSibling; + if (pre && pre.nodeName != "TABLE") { + domUtils.remove(tmpNode); + rng.setStartAtLast(pre).setCursor(false, true); + return; + } else { + var next = tmpNode.nextSibling; + if (next && next.nodeName != "TABLE") { + domUtils.remove(tmpNode); + rng.setStartAtFirst(next).setCursor(false, true); + return; + } + } + } + } + //处理当删除到body时,要重新给p标签展位 + if (domUtils.isBody(rng.startContainer)) { + var tmpNode = domUtils.createElement(me.document, "p", { + innerHTML: browser.ie ? domUtils.fillChar : "
    " + }); + rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true); + } + } + + //chrome下如果删除了inline标签,浏览器会有记忆,在输入文字还是会套上刚才删除的标签,所以这里再选一次就不会了 + if ( + !collapsed && + (rng.startContainer.nodeType == 3 || + (rng.startContainer.nodeType == 1 && + domUtils.isEmptyBlock(rng.startContainer))) + ) { + if (browser.ie) { + var span = rng.document.createElement("span"); + rng.insertNode(span).setStartBefore(span).collapse(true); + rng.select(); + domUtils.remove(span); + } else { + rng.select(); + } + } + } + }); + }; // plugins/fiximgclick.js @@ -18983,379 +22282,390 @@ UE.plugins["keystrokes"] = function() { ///commandsTitle 修复chrome下图片不能点击的问题,出现八个角可改变大小 //修复chrome下图片不能点击的问题,出现八个角可改变大小 -UE.plugins["fiximgclick"] = (function() { - var elementUpdated = false; - function Scale() { - this.editor = null; - this.resizer = null; - this.cover = null; - this.doc = document; - this.prePos = { x: 0, y: 0 }; - this.startPos = { x: 0, y: 0 }; - } + UE.plugins["fiximgclick"] = (function () { + var elementUpdated = false; - (function() { - var rect = [ - //[left, top, width, height] - [0, 0, -1, -1], - [0, 0, 0, -1], - [0, 0, 1, -1], - [0, 0, -1, 0], - [0, 0, 1, 0], - [0, 0, -1, 1], - [0, 0, 0, 1], - [0, 0, 1, 1] - ]; - - Scale.prototype = { - init: function(editor) { - var me = this; - me.editor = editor; - me.startPos = this.prePos = { x: 0, y: 0 }; - me.dragId = -1; - - var hands = [], - cover = (me.cover = document.createElement("div")), - resizer = (me.resizer = document.createElement("div")); - - cover.id = me.editor.ui.id + "_imagescale_cover"; - cover.style.cssText = - "position:absolute;display:none;z-index:" + - me.editor.options.zIndex + - ";filter:alpha(opacity=0); opacity:0;background:#CCC;"; - domUtils.on(cover, "mousedown click", function() { - me.hide(); - }); - - for (i = 0; i < 8; i++) { - hands.push( - '' - ); + function Scale() { + this.editor = null; + this.resizer = null; + this.cover = null; + this.doc = document; + this.prePos = {x: 0, y: 0}; + this.startPos = {x: 0, y: 0}; } - resizer.id = me.editor.ui.id + "_imagescale"; - resizer.className = "edui-editor-imagescale"; - resizer.innerHTML = hands.join(""); - resizer.style.cssText += - ";display:none;border:1px solid #3b77ff;z-index:" + - me.editor.options.zIndex + - ";"; - me.editor.ui.getDom().appendChild(cover); - me.editor.ui.getDom().appendChild(resizer); + (function () { + var rect = [ + //[left, top, width, height] + [0, 0, -1, -1], + [0, 0, 0, -1], + [0, 0, 1, -1], + [0, 0, -1, 0], + [0, 0, 1, 0], + [0, 0, -1, 1], + [0, 0, 0, 1], + [0, 0, 1, 1] + ]; - me.initStyle(); - me.initEvents(); - }, - initStyle: function() { - utils.cssRule( - "imagescale", - ".edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}" + - ".edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}" + - ".edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}" + - ".edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}" + - ".edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}" + - ".edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}" + - ".edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}" + - ".edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}" + - ".edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}" + - ".edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}" - ); - }, - initEvents: function() { - var me = this; + Scale.prototype = { + init: function (editor) { + var me = this; + me.editor = editor; + me.startPos = this.prePos = {x: 0, y: 0}; + me.dragId = -1; - me.startPos.x = me.startPos.y = 0; - me.isDraging = false; - }, - _eventHandler: function(e) { - var me = this; - switch (e.type) { - case "mousedown": - var hand = e.target || e.srcElement, - hand; - if ( - hand.className.indexOf("edui-editor-imagescale-hand") != -1 && - me.dragId == -1 - ) { - me.dragId = hand.className.slice(-1); - me.startPos.x = me.prePos.x = e.clientX; - me.startPos.y = me.prePos.y = e.clientY; - domUtils.on(me.doc, "mousemove", me.proxy(me._eventHandler, me)); - } - break; - case "mousemove": - if (me.dragId != -1) { - me.updateContainerStyle(me.dragId, { - x: e.clientX - me.prePos.x, - y: e.clientY - me.prePos.y - }); - me.prePos.x = e.clientX; - me.prePos.y = e.clientY; - elementUpdated = true; - me.updateTargetElement(); - } - break; - case "mouseup": - if (me.dragId != -1) { - me.updateContainerStyle(me.dragId, { - x: e.clientX - me.prePos.x, - y: e.clientY - me.prePos.y - }); - me.updateTargetElement(); - if (me.target.parentNode) me.attachTo(me.target); - me.dragId = -1; - } - domUtils.un(me.doc, "mousemove", me.proxy(me._eventHandler, me)); - //修复只是点击挪动点,但没有改变大小,不应该触发contentchange - if (elementUpdated) { - elementUpdated = false; - me.editor.fireEvent("contentchange"); - } + var hands = [], + cover = (me.cover = document.createElement("div")), + resizer = (me.resizer = document.createElement("div")); - break; - default: - break; - } - }, - updateTargetElement: function() { - var me = this; - domUtils.setStyles(me.target, { - width: me.resizer.style.width, - height: me.resizer.style.height - }); - me.target.width = parseInt(me.resizer.style.width); - me.target.height = parseInt(me.resizer.style.height); - me.attachTo(me.target); - }, - updateContainerStyle: function(dir, offset) { - var me = this, - dom = me.resizer, - tmp; + cover.id = me.editor.ui.id + "_imagescale_cover"; + cover.style.cssText = + "position:absolute;display:none;z-index:" + + me.editor.options.zIndex + + ";filter:alpha(opacity=0); opacity:0;background:#CCC;"; + domUtils.on(cover, "mousedown", function (e) { + me.hide(); + }); - if (rect[dir][0] != 0) { - tmp = parseInt(dom.style.left) + offset.x; - dom.style.left = me._validScaledProp("left", tmp) + "px"; - } - if (rect[dir][1] != 0) { - tmp = parseInt(dom.style.top) + offset.y; - dom.style.top = me._validScaledProp("top", tmp) + "px"; - } - if (rect[dir][2] != 0) { - tmp = dom.clientWidth + rect[dir][2] * offset.x; - dom.style.width = me._validScaledProp("width", tmp) + "px"; - } - if (rect[dir][3] != 0) { - tmp = dom.clientHeight + rect[dir][3] * offset.y; - dom.style.height = me._validScaledProp("height", tmp) + "px"; - } - }, - _validScaledProp: function(prop, value) { - var ele = this.resizer, - wrap = document; + for (var i = 0; i < 8; i++) { + hands.push( + '' + ); + } + resizer.id = me.editor.ui.id + "_imagescale"; + resizer.className = "edui-editor-imagescale"; + resizer.innerHTML = hands.join(""); + resizer.style.cssText += + ";display:none;border:1px solid #3b77ff;z-index:" + + me.editor.options.zIndex + + ";"; - value = isNaN(value) ? 0 : value; - switch (prop) { - case "left": - return value < 0 - ? 0 - : value + ele.clientWidth > wrap.clientWidth - ? wrap.clientWidth - ele.clientWidth - : value; - case "top": - return value < 0 - ? 0 - : value + ele.clientHeight > wrap.clientHeight - ? wrap.clientHeight - ele.clientHeight - : value; - case "width": - return value <= 0 - ? 1 - : value + ele.offsetLeft > wrap.clientWidth - ? wrap.clientWidth - ele.offsetLeft - : value; - case "height": - return value <= 0 - ? 1 - : value + ele.offsetTop > wrap.clientHeight - ? wrap.clientHeight - ele.offsetTop - : value; - } - }, - hideCover: function() { - this.cover.style.display = "none"; - }, - showCover: function() { - var me = this, - editorPos = domUtils.getXY(me.editor.ui.getDom()), - iframePos = domUtils.getXY(me.editor.iframe); + me.editor.ui.getDom().appendChild(cover); + me.editor.ui.getDom().appendChild(resizer); - domUtils.setStyles(me.cover, { - width: me.editor.iframe.offsetWidth + "px", - height: me.editor.iframe.offsetHeight + "px", - top: iframePos.y - editorPos.y + "px", - left: iframePos.x - editorPos.x + "px", - position: "absolute", - display: "" - }); - }, - show: function(targetObj) { - var me = this; - me.resizer.style.display = "block"; - if (targetObj) me.attachTo(targetObj); + me.initStyle(); + me.initEvents(); + }, + initStyle: function () { + utils.cssRule( + "imagescale", + ".edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}" + + ".edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}" + + ".edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}" + ); + }, + initEvents: function () { + var me = this; - domUtils.on(this.resizer, "mousedown", me.proxy(me._eventHandler, me)); - domUtils.on(me.doc, "mouseup", me.proxy(me._eventHandler, me)); + me.startPos.x = me.startPos.y = 0; + me.isDraging = false; + }, + _eventHandler: function (e) { + var me = this; + switch (e.type) { + case "mousedown": + var hand = e.target || e.srcElement, + hand; + if ( + hand.className.indexOf("edui-editor-imagescale-hand") !== -1 && + me.dragId === -1 + ) { + me.dragId = hand.className.slice(-1); + me.startPos.x = me.prePos.x = e.clientX; + me.startPos.y = me.prePos.y = e.clientY; + domUtils.on(me.doc, "mousemove", me.proxy(me._eventHandler, me)); + } + break; + case "mousemove": + if (me.dragId !== -1) { + me.updateContainerStyle(me.dragId, { + x: e.clientX - me.prePos.x, + y: e.clientY - me.prePos.y + }); + me.prePos.x = e.clientX; + me.prePos.y = e.clientY; + elementUpdated = true; + me.updateTargetElement(); + } + break; + case "mouseup": + if (me.dragId !== -1) { + me.updateContainerStyle(me.dragId, { + x: e.clientX - me.prePos.x, + y: e.clientY - me.prePos.y + }); + me.updateTargetElement(); + if (me.target.parentNode) { + me.attachTo(me.target); + } + me.dragId = -1; + } + domUtils.un(me.doc, "mousemove", me.proxy(me._eventHandler, me)); + //修复只是点击挪动点,但没有改变大小,不应该触发contentchange + if (elementUpdated) { + elementUpdated = false; + me.editor.fireEvent("contentchange"); + } - me.showCover(); - me.editor.fireEvent("afterscaleshow", me); - me.editor.fireEvent("saveScene"); - }, - hide: function() { - var me = this; - me.hideCover(); - me.resizer.style.display = "none"; + break; + default: + break; + } + }, + updateTargetElement: function () { + var me = this; + domUtils.setStyles(me.target, { + width: me.resizer.style.width, + height: me.resizer.style.height + }); + me.target.width = parseInt(me.resizer.style.width); + me.target.height = parseInt(me.resizer.style.height); + me.attachTo(me.target); + }, + updateContainerStyle: function (dir, offset) { + var me = this, + dom = me.resizer, + tmp; - domUtils.un(me.resizer, "mousedown", me.proxy(me._eventHandler, me)); - domUtils.un(me.doc, "mouseup", me.proxy(me._eventHandler, me)); - me.editor.fireEvent("afterscalehide", me); - }, - proxy: function(fn, context) { - return function(e) { - return fn.apply(context || this, arguments); - }; - }, - attachTo: function(targetObj) { - var me = this, - target = (me.target = targetObj), - resizer = this.resizer, - imgPos = domUtils.getXY(target), - iframePos = domUtils.getXY(me.editor.iframe), - editorPos = domUtils.getXY(resizer.parentNode); + if (rect[dir][0] != 0) { + tmp = parseInt(dom.style.left) + offset.x; + dom.style.left = me._validScaledProp("left", tmp) + "px"; + } + if (rect[dir][1] != 0) { + tmp = parseInt(dom.style.top) + offset.y; + dom.style.top = me._validScaledProp("top", tmp) + "px"; + } + if (rect[dir][2] != 0) { + tmp = dom.clientWidth + rect[dir][2] * offset.x; + dom.style.width = me._validScaledProp("width", tmp) + "px"; + } + if (rect[dir][3] != 0) { + tmp = dom.clientHeight + rect[dir][3] * offset.y; + dom.style.height = me._validScaledProp("height", tmp) + "px"; + } + }, + _validScaledProp: function (prop, value) { + var ele = this.resizer, + wrap = document; - domUtils.setStyles(resizer, { - width: target.width + "px", - height: target.height + "px", - left: - iframePos.x + - imgPos.x - - me.editor.document.body.scrollLeft - - editorPos.x - - parseInt(resizer.style.borderLeftWidth) + - "px", - top: - iframePos.y + - imgPos.y - - me.editor.document.body.scrollTop - - editorPos.y - - parseInt(resizer.style.borderTopWidth) + - "px" - }); - } - }; - })(); + value = isNaN(value) ? 0 : value; + switch (prop) { + case "left": + return value < 0 + ? 0 + : value + ele.clientWidth > wrap.clientWidth + ? wrap.clientWidth - ele.clientWidth + : value; + case "top": + return value < 0 + ? 0 + : value + ele.clientHeight > wrap.clientHeight + ? wrap.clientHeight - ele.clientHeight + : value; + case "width": + return value <= 0 + ? 1 + : value + ele.offsetLeft > wrap.clientWidth + ? wrap.clientWidth - ele.offsetLeft + : value; + case "height": + return value <= 0 + ? 1 + : value + ele.offsetTop > wrap.clientHeight + ? wrap.clientHeight - ele.offsetTop + : value; + } + }, + hideCover: function () { + this.cover.style.display = "none"; + }, + showCover: function () { + var me = this, + editorPos = domUtils.getXY(me.editor.ui.getDom()), + iframePos = domUtils.getXY(me.editor.iframe); - return function() { - var me = this, - imageScale; + domUtils.setStyles(me.cover, { + width: me.editor.iframe.offsetWidth + "px", + height: me.editor.iframe.offsetHeight + "px", + top: iframePos.y - editorPos.y + "px", + left: iframePos.x - editorPos.x + "px", + position: "absolute", + display: "" + }); + }, + show: function (targetObj) { + var me = this; + me.resizer.style.display = "block"; + if (targetObj) { + me.attachTo(targetObj); + } - me.setOpt("imageScaleEnabled", true); + domUtils.on(this.resizer, "mousedown", me.proxy(me._eventHandler, me)); + domUtils.on(me.doc, "mouseup", me.proxy(me._eventHandler, me)); - if (!browser.ie && me.options.imageScaleEnabled) { - me.addListener("click", function(type, e) { - var range = me.selection.getRange(), - img = range.getClosedNode(); + me.showCover(); + me.editor.fireEvent("afterscaleshow", me); + me.editor.fireEvent("saveScene"); + }, + hide: function () { + var me = this; + me.hideCover(); + me.resizer.style.display = "none"; - if (img && img.tagName == "IMG" && me.body.contentEditable != "false") { - if ( - img.getAttribute("anchorname") || - domUtils.hasClass(img, "loadingclass") || - domUtils.hasClass(img, "loaderrorclass") - ) { - return; - } + domUtils.un(me.resizer, "mousedown", me.proxy(me._eventHandler, me)); + domUtils.un(me.doc, "mouseup", me.proxy(me._eventHandler, me)); + me.editor.fireEvent("afterscalehide", me); + }, + proxy: function (fn, context) { + return function (e) { + return fn.apply(context || this, arguments); + }; + }, + attachTo: function (targetObj) { + var me = this, + target = (me.target = targetObj), + resizer = this.resizer, + imgPos = domUtils.getXY(target), + iframePos = domUtils.getXY(me.editor.iframe), + editorPos = domUtils.getXY(resizer.parentNode); - if (!imageScale) { - imageScale = new Scale(); - imageScale.init(me); - me.ui.getDom().appendChild(imageScale.resizer); - - var _keyDownHandler = function(e) { - imageScale.hide(); - if (imageScale.target) - me.selection.getRange().selectNode(imageScale.target).select(); - }, - _mouseDownHandler = function(e) { - var ele = e.target || e.srcElement; - if ( - ele && - (ele.className === undefined || - ele.className.indexOf("edui-editor-imagescale") == -1) - ) { - _keyDownHandler(e); + domUtils.setStyles(resizer, { + width: target.width + "px", + height: target.height + "px", + left: + iframePos.x + + imgPos.x - + me.editor.getScrollLeft() - + editorPos.x - + parseInt(resizer.style.borderLeftWidth) + + "px", + top: + iframePos.y + + imgPos.y - + me.editor.getScrollTop() - + editorPos.y - + parseInt(resizer.style.borderTopWidth) + + "px" + }); } - }, - timer; + }; + })(); - me.addListener("afterscaleshow", function(e) { - me.addListener("beforekeydown", _keyDownHandler); - me.addListener("beforemousedown", _mouseDownHandler); - domUtils.on(document, "keydown", _keyDownHandler); - domUtils.on(document, "mousedown", _mouseDownHandler); - me.selection.getNative().removeAllRanges(); - }); - me.addListener("afterscalehide", function(e) { - me.removeListener("beforekeydown", _keyDownHandler); - me.removeListener("beforemousedown", _mouseDownHandler); - domUtils.un(document, "keydown", _keyDownHandler); - domUtils.un(document, "mousedown", _mouseDownHandler); - var target = imageScale.target; - if (target.parentNode) { - me.selection.getRange().selectNode(target).select(); - } - }); - //TODO 有iframe的情况,mousedown不能往下传。。 - domUtils.on(imageScale.resizer, "mousedown", function(e) { - me.selection.getNative().removeAllRanges(); - var ele = e.target || e.srcElement; - if ( - ele && - ele.className.indexOf("edui-editor-imagescale-hand") == -1 - ) { - timer = setTimeout(function() { - imageScale.hide(); - if (imageScale.target) - me.selection.getRange().selectNode(ele).select(); - }, 200); - } - }); - domUtils.on(imageScale.resizer, "mouseup", function(e) { - var ele = e.target || e.srcElement; - if ( - ele && - ele.className.indexOf("edui-editor-imagescale-hand") == -1 - ) { - clearTimeout(timer); - } - }); - } - imageScale.show(img); - } else { - if (imageScale && imageScale.resizer.style.display != "none") - imageScale.hide(); - } - }); - } + return function () { + var me = this, + imageScale; - if (browser.webkit) { - me.addListener("click", function(type, e) { - if (e.target.tagName == "IMG" && me.body.contentEditable != "false") { - var range = new dom.Range(me.document); - range.selectNode(e.target).select(); - } - }); - } - }; -})(); + me.setOpt("imageScaleEnabled", true); + + if (!browser.ie && me.options.imageScaleEnabled) { + me.addListener("click", function (type, e) { + var range = me.selection.getRange(), + img = range.getClosedNode(); + + if (img + && img.tagName === "IMG" + && me.body.contentEditable !== "false" + && img === e.target + ) { + if ( + img.getAttribute("anchorname") || + domUtils.hasClass(img, "uep-loading") || + domUtils.hasClass(img, "uep-loading-error") + ) { + return; + } + + if (!imageScale) { + imageScale = new Scale(); + imageScale.init(me); + me.ui.getDom().appendChild(imageScale.resizer); + + var _keyDownHandler = function (e) { + imageScale.hide(); + if (imageScale.target) { + me.selection.getRange().selectNode(imageScale.target).select(); + } + }, + _mouseDownHandler = function (e) { + var ele = e.target || e.srcElement; + if ( + ele && + (ele.className === undefined || + ele.className.indexOf("edui-editor-imagescale") === -1) + ) { + _keyDownHandler(e); + } + }, + timer; + + me.addListener("afterscaleshow", function (e) { + me.addListener("beforekeydown", _keyDownHandler); + me.addListener("beforemousedown", _mouseDownHandler); + domUtils.on(document, "keydown", _keyDownHandler); + domUtils.on(document, "mousedown", _mouseDownHandler); + me.selection.getNative().removeAllRanges(); + }); + me.addListener("afterscalehide", function (e) { + me.removeListener("beforekeydown", _keyDownHandler); + me.removeListener("beforemousedown", _mouseDownHandler); + domUtils.un(document, "keydown", _keyDownHandler); + domUtils.un(document, "mousedown", _mouseDownHandler); + var target = imageScale.target; + if (target.parentNode) { + me.selection.getRange().selectNode(target).select(); + } + }); + //TODO 有iframe的情况,mousedown不能往下传。。 + domUtils.on(imageScale.resizer, "mousedown", function (e) { + me.selection.getNative().removeAllRanges(); + var ele = e.target || e.srcElement; + if ( + ele && + ele.className.indexOf("edui-editor-imagescale-hand") === -1 + ) { + timer = setTimeout(function () { + imageScale.hide(); + if (imageScale.target) + me.selection.getRange().selectNode(ele).select(); + }, 200); + } + }); + domUtils.on(imageScale.resizer, "mouseup", function (e) { + var ele = e.target || e.srcElement; + if ( + ele && + ele.className.indexOf("edui-editor-imagescale-hand") === -1 + ) { + clearTimeout(timer); + } + }); + } + imageScale.show(img); + } else { + if (imageScale && imageScale.resizer.style.display !== "none") { + imageScale.hide(); + } + } + }); + } + + if (browser.webkit) { + me.addListener("click", function (type, e) { + if (e.target.tagName === "IMG" && me.body.contentEditable !== "false") { + var range = new dom.Range(me.document); + range.selectNode(e.target).select(); + } + }); + } + }; + })(); // plugins/autolink.js @@ -19363,220 +22673,222 @@ UE.plugins["fiximgclick"] = (function() { ///commands 为非ie浏览器自动添加a标签 ///commandsName AutoLink ///commandsTitle 自动增加链接 -/** - * @description 为非ie浏览器自动添加a标签 - * @author zhanyi - */ + /** + * @description 为非ie浏览器自动添加a标签 + * @author zhanyi + */ -UE.plugin.register( - "autolink", - function() { - var cont = 0; + UE.plugin.register( + "autolink", + function () { + var cont = 0; - return !browser.ie - ? { - bindEvents: { - reset: function() { - cont = 0; - }, - keydown: function(type, evt) { - var me = this; - var keyCode = evt.keyCode || evt.which; + return !browser.ie + ? { + bindEvents: { + reset: function () { + cont = 0; + }, + keydown: function (type, evt) { + var me = this; + var keyCode = evt.keyCode || evt.which; - if (keyCode == 32 || keyCode == 13) { - var sel = me.selection.getNative(), - range = sel.getRangeAt(0).cloneRange(), - offset, - charCode; + if (keyCode == 32 || keyCode == 13) { + var sel = me.selection.getNative(), + range = sel.getRangeAt(0).cloneRange(), + offset, + charCode; - var start = range.startContainer; - while (start.nodeType == 1 && range.startOffset > 0) { - start = - range.startContainer.childNodes[range.startOffset - 1]; - if (!start) { - break; - } - range.setStart( - start, - start.nodeType == 1 - ? start.childNodes.length - : start.nodeValue.length - ); - range.collapse(true); - start = range.startContainer; - } + var start = range.startContainer; + while (start.nodeType == 1 && range.startOffset > 0) { + start = + range.startContainer.childNodes[range.startOffset - 1]; + if (!start) { + break; + } + range.setStart( + start, + start.nodeType == 1 + ? start.childNodes.length + : start.nodeValue.length + ); + range.collapse(true); + start = range.startContainer; + } - do { - if (range.startOffset == 0) { - start = range.startContainer.previousSibling; + do { + if (range.startOffset == 0) { + start = range.startContainer.previousSibling; - while (start && start.nodeType == 1) { - start = start.lastChild; - } - if (!start || domUtils.isFillChar(start)) { - break; - } - offset = start.nodeValue.length; - } else { - start = range.startContainer; - offset = range.startOffset; - } - range.setStart(start, offset - 1); - charCode = range.toString().charCodeAt(0); - } while (charCode != 160 && charCode != 32); + while (start && start.nodeType == 1) { + start = start.lastChild; + } + if (!start || domUtils.isFillChar(start)) { + break; + } + offset = start.nodeValue.length; + } else { + start = range.startContainer; + offset = range.startOffset; + } + range.setStart(start, offset - 1); + charCode = range.toString().charCodeAt(0); + } while (charCode != 160 && charCode != 32); - if ( - range - .toString() - .replace(new RegExp(domUtils.fillChar, "g"), "") - .match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i) - ) { - while (range.toString().length) { - if ( - /^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test( - range.toString() - ) - ) { - break; - } - try { - range.setStart( - range.startContainer, - range.startOffset + 1 - ); - } catch (e) { - //trace:2121 - var start = range.startContainer; - while (!(next = start.nextSibling)) { - if (domUtils.isBody(start)) { - return; + if ( + range + .toString() + .replace(new RegExp(domUtils.fillChar, "g"), "") + .match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i) + ) { + while (range.toString().length) { + if ( + /^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test( + range.toString() + ) + ) { + break; + } + try { + range.setStart( + range.startContainer, + range.startOffset + 1 + ); + } catch (e) { + //trace:2121 + var start = range.startContainer; + while (!(next = start.nextSibling)) { + if (domUtils.isBody(start)) { + return; + } + start = start.parentNode; + } + range.setStart(next, 0); + } + } + //range的开始边界已经在a标签里的不再处理 + if ( + domUtils.findParentByTagName( + range.startContainer, + "a", + true + ) + ) { + return; + } + var a = me.document.createElement("a"), + text = me.document.createTextNode(" "), + href; + + me.undoManger && me.undoManger.save(); + a.appendChild(range.extractContents()); + a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, ""); + href = a + .getAttribute("href") + .replace(new RegExp(domUtils.fillChar, "g"), ""); + href = /^(?:https?:\/\/)/gi.test(href) + ? href + : "http://" + href; + a.setAttribute("_src", utils.html(href)); + a.href = utils.html(href); + + range.insertNode(a); + a.parentNode.insertBefore(text, a.nextSibling); + range.setStart(text, 0); + range.collapse(true); + sel.removeAllRanges(); + sel.addRange(range); + me.undoManger && me.undoManger.save(); + } + } } - start = start.parentNode; - } - range.setStart(next, 0); } - } - //range的开始边界已经在a标签里的不再处理 - if ( - domUtils.findParentByTagName( - range.startContainer, - "a", - true - ) - ) { - return; - } - var a = me.document.createElement("a"), - text = me.document.createTextNode(" "), - href; - - me.undoManger && me.undoManger.save(); - a.appendChild(range.extractContents()); - a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, ""); - href = a - .getAttribute("href") - .replace(new RegExp(domUtils.fillChar, "g"), ""); - href = /^(?:https?:\/\/)/gi.test(href) - ? href - : "http://" + href; - a.setAttribute("_src", utils.html(href)); - a.href = utils.html(href); - - range.insertNode(a); - a.parentNode.insertBefore(text, a.nextSibling); - range.setStart(text, 0); - range.collapse(true); - sel.removeAllRanges(); - sel.addRange(range); - me.undoManger && me.undoManger.save(); } - } - } - } - } - : {}; - }, - function() { - var keyCodes = { - 37: 1, - 38: 1, - 39: 1, - 40: 1, - 13: 1, - 32: 1 - }; - function checkIsCludeLink(node) { - if (node.nodeType == 3) { - return null; - } - if (node.nodeName == "A") { - return node; - } - var lastChild = node.lastChild; + : {}; + }, + function () { + var keyCodes = { + 37: 1, + 38: 1, + 39: 1, + 40: 1, + 13: 1, + 32: 1 + }; - while (lastChild) { - if (lastChild.nodeName == "A") { - return lastChild; - } - if (lastChild.nodeType == 3) { - if (domUtils.isWhitespace(lastChild)) { - lastChild = lastChild.previousSibling; - continue; - } - return null; - } - lastChild = lastChild.lastChild; - } - } - browser.ie && - this.addListener("keyup", function(cmd, evt) { - var me = this, - keyCode = evt.keyCode; - if (keyCodes[keyCode]) { - var rng = me.selection.getRange(); - var start = rng.startContainer; - - if (keyCode == 13) { - while ( - start && - !domUtils.isBody(start) && - !domUtils.isBlockElm(start) - ) { - start = start.parentNode; - } - if (start && !domUtils.isBody(start) && start.nodeName == "P") { - var pre = start.previousSibling; - if (pre && pre.nodeType == 1) { - var pre = checkIsCludeLink(pre); - if (pre && !pre.getAttribute("_href")) { - domUtils.remove(pre, true); + function checkIsCludeLink(node) { + if (node.nodeType == 3) { + return null; } - } - } - } else if (keyCode == 32) { - if (start.nodeType == 3 && /^\s$/.test(start.nodeValue)) { - start = start.previousSibling; - if ( - start && - start.nodeName == "A" && - !start.getAttribute("_href") - ) { - domUtils.remove(start, true); - } - } - } else { - start = domUtils.findParentByTagName(start, "a", true); - if (start && !start.getAttribute("_href")) { - var bk = rng.createBookmark(); + if (node.nodeName == "A") { + return node; + } + var lastChild = node.lastChild; - domUtils.remove(start, true); - rng.moveToBookmark(bk).select(true); + while (lastChild) { + if (lastChild.nodeName == "A") { + return lastChild; + } + if (lastChild.nodeType == 3) { + if (domUtils.isWhitespace(lastChild)) { + lastChild = lastChild.previousSibling; + continue; + } + return null; + } + lastChild = lastChild.lastChild; + } } - } + + browser.ie && + this.addListener("keyup", function (cmd, evt) { + var me = this, + keyCode = evt.keyCode; + if (keyCodes[keyCode]) { + var rng = me.selection.getRange(); + var start = rng.startContainer; + + if (keyCode == 13) { + while ( + start && + !domUtils.isBody(start) && + !domUtils.isBlockElm(start) + ) { + start = start.parentNode; + } + if (start && !domUtils.isBody(start) && start.nodeName == "P") { + var pre = start.previousSibling; + if (pre && pre.nodeType == 1) { + var pre = checkIsCludeLink(pre); + if (pre && !pre.getAttribute("_href")) { + domUtils.remove(pre, true); + } + } + } + } else if (keyCode == 32) { + if (start.nodeType == 3 && /^\s$/.test(start.nodeValue)) { + start = start.previousSibling; + if ( + start && + start.nodeName == "A" && + !start.getAttribute("_href") + ) { + domUtils.remove(start, true); + } + } + } else { + start = domUtils.findParentByTagName(start, "a", true); + if (start && !start.getAttribute("_href")) { + var bk = rng.createBookmark(); + + domUtils.remove(start, true); + rng.moveToBookmark(bk).select(true); + } + } + } + }); } - }); - } -); + ); // plugins/autoheight.js @@ -19584,128 +22896,129 @@ UE.plugin.register( ///commands 当输入内容超过编辑器高度时,编辑器自动增高 ///commandsName AutoHeight,autoHeightEnabled ///commandsTitle 自动增高 -/** - * @description 自动伸展 - * @author zhanyi - */ -UE.plugins["autoheight"] = function() { - var me = this; - //提供开关,就算加载也可以关闭 - me.autoHeightEnabled = me.options.autoHeightEnabled !== false; - if (!me.autoHeightEnabled) { - return; - } - - var bakOverflow, - lastHeight = 0, - options = me.options, - currentHeight, - timer; - - function adjustHeight() { - var me = this; - clearTimeout(timer); - if (isFullscreen) return; - if ( - !me.queryCommandState || - (me.queryCommandState && me.queryCommandState("source") != 1) - ) { - timer = setTimeout(function() { - var node = me.body.lastChild; - while (node && node.nodeType != 1) { - node = node.previousSibling; + /** + * @description 自动伸展 + * @author zhanyi + */ + UE.plugins["autoheight"] = function () { + var me = this; + //提供开关,就算加载也可以关闭 + me.autoHeightEnabled = me.options.autoHeightEnabled !== false; + if (!me.autoHeightEnabled) { + return; } - if (node && node.nodeType == 1) { - node.style.clear = "both"; - currentHeight = Math.max( - domUtils.getXY(node).y + node.offsetHeight + 25, - Math.max(options.minFrameHeight, options.initialFrameHeight) - ); - if (currentHeight !== lastHeight) { - me.iframe.parentNode.style.transition = 'width 0.3s, height 0.3s, easy-in-out'; - if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) { - me.iframe.parentNode.style.height = currentHeight + "px"; + + var bakOverflow, + lastHeight = 0, + options = me.options, + currentHeight, + timer; + + function adjustHeight() { + var me = this; + clearTimeout(timer); + if (isFullscreen) return; + if ( + !me.queryCommandState || + (me.queryCommandState && me.queryCommandState("source") != 1) + ) { + timer = setTimeout(function () { + var node = me.body.lastChild; + while (node && node.nodeType != 1) { + node = node.previousSibling; + } + if (node && node.nodeType == 1) { + node.style.clear = "both"; + currentHeight = Math.max( + domUtils.getXY(node).y + node.offsetHeight + 25, + Math.max(options.minFrameHeight, options.initialFrameHeight) + ); + if (currentHeight !== lastHeight) { + me.iframe.parentNode.style.transition = 'width 0.3s, height 0.3s, easy-in-out'; + if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) { + me.iframe.parentNode.style.height = currentHeight + "px"; + } + me.body.style.height = currentHeight + "px"; + lastHeight = currentHeight; + } + domUtils.removeStyle(node, "clear"); + } + }, 50); } - me.body.style.height = currentHeight + "px"; - lastHeight = currentHeight; - } - domUtils.removeStyle(node, "clear"); } - }, 50); - } - } - var isFullscreen; - me.addListener("fullscreenchanged", function(cmd, f) { - isFullscreen = f; - }); - me.addListener("destroy", function() { - domUtils.un(me.window, "scroll", fixedScrollTop); - me.removeListener( - "contentchange afterinserthtml keyup mouseup", - adjustHeight - ); - }); - me.enableAutoHeight = function() { - var me = this; - if (!me.autoHeightEnabled) { - return; - } - var doc = me.document; - me.autoHeightEnabled = true; - bakOverflow = doc.body.style.overflowY; - doc.body.style.overflowY = "hidden"; - me.addListener("contentchange afterinserthtml keyup mouseup", adjustHeight); - //ff不给事件算得不对 - setTimeout(function() { - adjustHeight.call(me); - }, browser.gecko ? 100 : 0); - me.fireEvent("autoheightchanged", me.autoHeightEnabled); - }; - me.disableAutoHeight = function() { - me.body.style.overflowY = bakOverflow || ""; + var isFullscreen; + me.addListener("fullscreenchanged", function (cmd, f) { + isFullscreen = f; + }); + me.addListener("destroy", function () { + domUtils.un(me.window, "scroll", fixedScrollTop); + me.removeListener( + "contentchange afterinserthtml keyup mouseup", + adjustHeight + ); + }); + me.enableAutoHeight = function () { + var me = this; + if (!me.autoHeightEnabled) { + return; + } + var doc = me.document; + me.autoHeightEnabled = true; + bakOverflow = doc.body.style.overflowY; + doc.body.style.overflowY = "hidden"; + me.addListener("contentchange afterinserthtml keyup mouseup", adjustHeight); + //ff不给事件算得不对 - me.removeListener("contentchange", adjustHeight); - me.removeListener("keyup", adjustHeight); - me.removeListener("mouseup", adjustHeight); - me.autoHeightEnabled = false; - me.fireEvent("autoheightchanged", me.autoHeightEnabled); - }; + setTimeout(function () { + adjustHeight.call(me); + }, browser.gecko ? 100 : 0); + me.fireEvent("autoheightchanged", me.autoHeightEnabled); + }; + me.disableAutoHeight = function () { + me.body.style.overflowY = bakOverflow || ""; - me.on("setHeight", function() { - me.disableAutoHeight(); - }); - me.addListener("ready", function() { - me.enableAutoHeight(); - //trace:1764 - var timer; - domUtils.on( - browser.ie ? me.body : me.document, - browser.webkit ? "dragover" : "drop", - function() { - clearTimeout(timer); - timer = setTimeout(function() { - //trace:3681 - adjustHeight.call(me); - }, 100); - } - ); - //修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题 - domUtils.on(me.window, "scroll", fixedScrollTop); - }); + me.removeListener("contentchange", adjustHeight); + me.removeListener("keyup", adjustHeight); + me.removeListener("mouseup", adjustHeight); + me.autoHeightEnabled = false; + me.fireEvent("autoheightchanged", me.autoHeightEnabled); + }; - var lastScrollY; + me.on("setHeight", function () { + me.disableAutoHeight(); + }); + me.addListener("ready", function () { + me.enableAutoHeight(); + //trace:1764 + var timer; + domUtils.on( + browser.ie ? me.body : me.document, + browser.webkit ? "dragover" : "drop", + function () { + clearTimeout(timer); + timer = setTimeout(function () { + //trace:3681 + adjustHeight.call(me); + }, 100); + } + ); + //修复内容过多时,回到顶部,顶部内容被工具栏遮挡问题 + domUtils.on(me.window, "scroll", fixedScrollTop); + }); - function fixedScrollTop() { - if (!me.window) return; - if (lastScrollY === null) { - lastScrollY = me.window.scrollY; - } else if (me.window.scrollY == 0 && lastScrollY != 0) { - me.window.scrollTo(0, 0); - lastScrollY = null; - } - } -}; + var lastScrollY; + + function fixedScrollTop() { + if (!me.window) return; + if (lastScrollY === null) { + lastScrollY = me.window.scrollY; + } else if (me.window.scrollY == 0 && lastScrollY != 0) { + me.window.scrollTo(0, 0); + lastScrollY = null; + } + } + }; // plugins/autofloat.js @@ -19713,5137 +23026,5150 @@ UE.plugins["autoheight"] = function() { ///commands 悬浮工具栏 ///commandsName AutoFloat,autoFloatEnabled ///commandsTitle 悬浮工具栏 -/** - * modified by chengchao01 - * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉! - */ -UE.plugins["autofloat"] = function() { - var me = this, - lang = me.getLang(); - me.setOpt({ - topOffset: 0 - }); - var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false, - topOffset = me.options.topOffset; + /** + * modified by chengchao01 + * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉! + */ + UE.plugins["autofloat"] = function () { + var me = this, + lang = me.getLang(); + me.setOpt({ + topOffset: 0 + }); + var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false, + topOffset = me.options.topOffset; - //如果不固定toolbar的位置,则直接退出 - if (!optsAutoFloatEnabled) { - return; - } - var uiUtils = UE.ui.uiUtils, - LteIE6 = browser.ie && browser.version <= 6, - quirks = browser.quirks; - - function checkHasUI() { - if (!UE.ui) { - alert(lang.autofloatMsg); - return 0; - } - return 1; - } - function fixIE6FixedPos() { - var docStyle = document.body.style; - docStyle.backgroundImage = 'url("about:blank")'; - docStyle.backgroundAttachment = "fixed"; - } - var bakCssText, - placeHolder = document.createElement("div"), - toolbarBox, - orgTop, - getPosition, - flag = true; //ie7模式下需要偏移 - function setFloating() { - var toobarBoxPos = domUtils.getXY(toolbarBox), - origalFloat = domUtils.getComputedStyle(toolbarBox, "position"), - origalLeft = domUtils.getComputedStyle(toolbarBox, "left"); - toolbarBox.style.width = toolbarBox.offsetWidth + "px"; - toolbarBox.style.zIndex = me.options.zIndex * 1 + 1; - toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox); - if (LteIE6 || (quirks && browser.ie)) { - if (toolbarBox.style.position != "absolute") { - toolbarBox.style.position = "absolute"; - } - toolbarBox.style.top = - (document.body.scrollTop || document.documentElement.scrollTop) - - orgTop + - topOffset + - "px"; - } else { - if (browser.ie7Compat && flag) { - flag = false; - toolbarBox.style.left = - domUtils.getXY(toolbarBox).x - - document.documentElement.getBoundingClientRect().left + - 2 + - "px"; - } - if (toolbarBox.style.position != "fixed") { - toolbarBox.style.position = "fixed"; - toolbarBox.style.top = topOffset + "px"; - (origalFloat == "absolute" || origalFloat == "relative") && - parseFloat(origalLeft) && - (toolbarBox.style.left = toobarBoxPos.x + "px"); - } - } - } - function unsetFloating() { - flag = true; - if (placeHolder.parentNode) { - placeHolder.parentNode.removeChild(placeHolder); - } - - toolbarBox.style.cssText = bakCssText; - } - - me.unsetFloating = unsetFloating; - - function updateFloating() { - var rect3 = getPosition(me.container); - var offset = me.options.toolbarTopOffset || 0; - if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) { - setFloating(); - } else { - unsetFloating(); - } - } - var defer_updateFloating = utils.defer( - function() { - updateFloating(); - }, - browser.ie ? 200 : 100, - true - ); - - me.addListener("destroy", function() { - domUtils.un(window, ["scroll", "resize"], updateFloating); - me.removeListener("keydown", defer_updateFloating); - }); - - me.addListener("ready", function() { - if (checkHasUI(me)) { - //加载了ui组件,但在new时,没有加载ui,导致编辑器实例上没有ui类,所以这里做判断 - if (!me.ui) { - return; - } - getPosition = uiUtils.getClientRect; - toolbarBox = me.ui.getDom("toolbarbox"); - orgTop = getPosition(toolbarBox).top; - bakCssText = toolbarBox.style.cssText; - placeHolder.style.height = toolbarBox.offsetHeight + "px"; - if (LteIE6) { - fixIE6FixedPos(); - } - domUtils.on(window, ["scroll", "resize"], updateFloating); - me.addListener("keydown", defer_updateFloating); - - me.addListener("beforefullscreenchange", function(t, enabled) { - if (enabled) { - unsetFloating(); + //如果不固定toolbar的位置,则直接退出 + if (!optsAutoFloatEnabled) { + return; } - }); - me.addListener("fullscreenchanged", function(t, enabled) { - if (!enabled) { - updateFloating(); + var uiUtils = UE.ui.uiUtils, + LteIE6 = browser.ie && browser.version <= 6, + quirks = browser.quirks; + + function checkHasUI() { + if (!UE.ui) { + alert(lang.autofloatMsg); + return 0; + } + return 1; } - }); - me.addListener("sourcemodechanged", function(t, enabled) { - setTimeout(function() { - updateFloating(); - }, 0); - }); - me.addListener("clearDoc", function() { - setTimeout(function() { - updateFloating(); - }, 0); - }); - } - }); -}; + + function fixIE6FixedPos() { + var docStyle = document.body.style; + docStyle.backgroundImage = 'url("about:blank")'; + docStyle.backgroundAttachment = "fixed"; + } + + var bakCssText, + placeHolder = document.createElement("div"), + toolbarBox, + orgTop, + getPosition, + flag = true; //ie7模式下需要偏移 + function setFloating() { + var toobarBoxPos = domUtils.getXY(toolbarBox), + origalFloat = domUtils.getComputedStyle(toolbarBox, "position"), + origalLeft = domUtils.getComputedStyle(toolbarBox, "left"); + toolbarBox.style.width = toolbarBox.offsetWidth + "px"; + toolbarBox.style.zIndex = me.options.zIndex * 1 + 1; + toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox); + if (LteIE6 || (quirks && browser.ie)) { + if (toolbarBox.style.position != "absolute") { + toolbarBox.style.position = "absolute"; + } + toolbarBox.style.top = + (document.body.scrollTop || document.documentElement.scrollTop) - + orgTop + + topOffset + + "px"; + } else { + if (browser.ie7Compat && flag) { + flag = false; + toolbarBox.style.left = + domUtils.getXY(toolbarBox).x - + document.documentElement.getBoundingClientRect().left + + 2 + + "px"; + } + if (toolbarBox.style.position != "fixed") { + toolbarBox.style.position = "fixed"; + toolbarBox.style.top = topOffset + "px"; + (origalFloat == "absolute" || origalFloat == "relative") && + parseFloat(origalLeft) && + (toolbarBox.style.left = toobarBoxPos.x + "px"); + } + } + } + + function unsetFloating() { + flag = true; + if (placeHolder.parentNode) { + placeHolder.parentNode.removeChild(placeHolder); + } + + toolbarBox.style.cssText = bakCssText; + } + + me.unsetFloating = unsetFloating; + + function updateFloating() { + var rect3 = getPosition(me.container); + var offset = me.options.toolbarTopOffset || 0; + if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) { + setFloating(); + } else { + unsetFloating(); + } + } + + var defer_updateFloating = utils.defer( + function () { + updateFloating(); + }, + browser.ie ? 200 : 100, + true + ); + + me.addListener("destroy", function () { + domUtils.un(window, ["scroll", "resize"], updateFloating); + me.removeListener("keydown", defer_updateFloating); + }); + + me.addListener("ready", function () { + if (checkHasUI(me)) { + //加载了ui组件,但在new时,没有加载ui,导致编辑器实例上没有ui类,所以这里做判断 + if (!me.ui) { + return; + } + getPosition = uiUtils.getClientRect; + toolbarBox = me.ui.getDom("toolbarbox"); + orgTop = getPosition(toolbarBox).top; + bakCssText = toolbarBox.style.cssText; + placeHolder.style.height = toolbarBox.offsetHeight + "px"; + if (LteIE6) { + fixIE6FixedPos(); + } + domUtils.on(window, ["scroll", "resize"], updateFloating); + me.addListener("keydown", defer_updateFloating); + + me.addListener("beforefullscreenchange", function (t, enabled) { + if (enabled) { + unsetFloating(); + } + }); + me.addListener("fullscreenchanged", function (t, enabled) { + if (!enabled) { + updateFloating(); + } + }); + me.addListener("sourcemodechanged", function (t, enabled) { + setTimeout(function () { + updateFloating(); + }, 0); + }); + me.addListener("clearDoc", function () { + setTimeout(function () { + updateFloating(); + }, 0); + }); + } + }); + }; // plugins/video.js -/** - * video插件, 为UEditor提供视频插入支持 - * @file - * @since 1.2.6.1 - */ - -UE.plugins["video"] = function() { - var me = this; - - /** - * 创建插入视频字符窜 - * @param url 视频地址 - * @param width 视频宽度 - * @param height 视频高度 - * @param align 视频对齐 - * @param toEmbed 是否以flash代替显示 - * @param addParagraph 是否需要添加P 标签 + /** + * video插件, 为UEditor提供视频插入支持 + * @file + * @since 1.2.6.1 */ - function creatInsertStr(url, width, height, id, align, classname, type) { - var str; - switch (type) { - case 'iframe': - str = '' + - '
    ' + - '
    ' + - this.getContentHtmlTpl() + - "
    " + - " " + - "" - ); - }, - getContentHtmlTpl: function() { - if (this.content) { - if (typeof this.content == "string") { - return this.content; - } - return this.content.renderHtml(); - } else { - return ""; - } - }, - _UIBase_postRender: UIBase.prototype.postRender, - postRender: function() { - if (this.content instanceof UIBase) { - this.content.postRender(); - } - - //捕获鼠标滚轮 - if (this.captureWheel && !this.captured) { - this.captured = true; - - var winHeight = - (document.documentElement.clientHeight || - document.body.clientHeight) - 80, - _height = this.getDom().offsetHeight, - _top = uiUtils.getClientRect(this.combox.getDom()).top, - content = this.getDom("content"), - ifr = this.getDom("body").getElementsByTagName("iframe"), - me = this; - - ifr.length && (ifr = ifr[0]); - - while (_top + _height > winHeight) { - _height -= 30; - } - content.style.height = _height + "px"; - //同步更改iframe高度 - ifr && (ifr.style.height = _height + "px"); - - //阻止在combox上的鼠标滚轮事件, 防止用户的正常操作被误解 - domUtils.on( - content, - "onmousewheel" in document.body ? "mousewheel" : "DOMMouseScroll", - function(e) { - if (e.preventDefault) { - e.preventDefault(); - } else { - e.returnValue = false; - } - - if (e.wheelDelta) { - content.scrollTop -= e.wheelDelta / 120 * 60; - } else { - content.scrollTop -= e.detail / -3 * 60; - } + function closeAllPopup(evt, el) { + for (var i = 0; i < allPopups.length; i++) { + var pop = allPopups[i]; + if (!pop.isHidden()) { + if (pop.queryAutoHide(el) !== false) { + if ( + evt && + /scroll/gi.test(evt.type) && + pop.className === "edui-wordpastepop" + ) + return; + pop.hide(); + } + } } - ); - } - this.fireEvent("postRenderAfter"); - this.hide(true); - this._UIBase_postRender(); - }, - _doAutoRender: function() { - if (!this.getDom() && this.autoRender) { - this.render(); - } - }, - mesureSize: function() { - var box = this.getDom("content"); - return uiUtils.getClientRect(box); - }, - fitSize: function() { - // console.log('fitSize.popup') - if (this.captureWheel && this.sized) { - return this.__size; - } - this.sized = true; - var popBodyEl = this.getDom("body"); - popBodyEl.style.width = ""; - popBodyEl.style.height = ""; - var size = this.mesureSize(); - if (this.captureWheel) { - popBodyEl.style.width = -(-20 - size.width) + "px"; - var height = parseInt(this.getDom("content").style.height, 10); - !window.isNaN(height) && (size.height = height); - } else { - popBodyEl.style.width = size.width + "px"; - } - popBodyEl.style.height = size.height + "px"; - this.__size = size; - this.captureWheel && (this.getDom("content").style.overflow = "auto"); - return size; - }, - showAnchor: function(element, hoz) { - this.showAnchorRect(uiUtils.getClientRect(element), hoz); - }, - showAnchorRect: function(rect, hoz, adj) { - this._doAutoRender(); - var vpRect = uiUtils.getViewportRect(); - this.getDom().style.visibility = "hidden"; - this._show(); - var popSize = this.fitSize(); - var sideLeft, sideUp, left, top; - if (hoz) { - sideLeft = - this.canSideLeft && - (rect.right + popSize.width > vpRect.right && - rect.left > popSize.width); - sideUp = - this.canSideUp && - (rect.top + popSize.height > vpRect.bottom && - rect.bottom > popSize.height); - left = sideLeft ? rect.left - popSize.width : rect.right; - top = sideUp ? rect.bottom - popSize.height : rect.top; - } else { - sideLeft = - this.canSideLeft && - (rect.right + popSize.width > vpRect.right && - rect.left > popSize.width); - sideUp = - this.canSideUp && - (rect.top + popSize.height > vpRect.bottom && - rect.bottom > popSize.height); - left = sideLeft ? rect.right - popSize.width : rect.left; - top = sideUp ? rect.top - popSize.height : rect.bottom; - } - if(!sideUp){ - if(top + popSize.height > vpRect.bottom){ - top = vpRect.bottom - popSize.height + if (allPopups.length) pop.editor.fireEvent("afterhidepop"); } - } - // console.log('popup.showAnchorRect', vpRect, rect, hoz, sideUp, sideLeft, left, top); - var popEl = this.getDom(); - uiUtils.setViewportOffset(popEl, { - left: left, - top: top - }); - domUtils.removeClasses(popEl, ANCHOR_CLASSES); - popEl.className += - " " + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)]; - if (this.editor) { - popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10; - baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = - popEl.style.zIndex - 1; - } - this.getDom().style.visibility = "visible"; - }, - showAt: function(offset) { - var left = offset.left; - var top = offset.top; - var rect = { - left: left, - top: top, - right: left, - bottom: top, - height: 0, - width: 0 - }; - this.showAnchorRect(rect, false, true); - }, - _show: function() { - if (this._hidden) { - var box = this.getDom(); - box.style.display = ""; - this._hidden = false; - // if (box.setActive) { - // box.setActive(); - // } - this.fireEvent("show"); - } - }, - isHidden: function() { - return this._hidden; - }, - show: function() { - this._doAutoRender(); - this._show(); - }, - hide: function(notNofity) { - if (!this._hidden && this.getDom()) { - this.getDom().style.display = "none"; - this._hidden = true; - if (!notNofity) { - this.fireEvent("hide"); - } - } - }, - queryAutoHide: function(el) { - return !el || !uiUtils.contains(this.getDom(), el); - } - }; - utils.inherits(Popup, UIBase); + Popup.postHide = closeAllPopup; - domUtils.on(document, "mousedown", function(evt) { - var el = evt.target || evt.srcElement; - closeAllPopup(evt, el); - }); - domUtils.on(window, "scroll", function(evt, el) { - closeAllPopup(evt, el); - }); -})(); + var ANCHOR_CLASSES = [ + "edui-anchor-topleft", + "edui-anchor-topright", + "edui-anchor-bottomleft", + "edui-anchor-bottomright" + ]; + Popup.prototype = { + SHADOW_RADIUS: 5, + content: null, + _hidden: false, + autoRender: true, + canSideLeft: true, + canSideUp: true, + initPopup: function () { + this.initUIBase(); + allPopups.push(this); + }, + getHtmlTpl: function () { + return ( + '
    ' + + '
    ' + + ' ' + + '
    ' + + '
    ' + + this.getContentHtmlTpl() + + "
    " + + "
    " + + "
    " + ); + }, + getContentHtmlTpl: function () { + if (this.content) { + if (typeof this.content == "string") { + return this.content; + } + return this.content.renderHtml(); + } else { + return ""; + } + }, + _UIBase_postRender: UIBase.prototype.postRender, + postRender: function () { + if (this.content instanceof UIBase) { + this.content.postRender(); + } + + //捕获鼠标滚轮 + if (this.captureWheel && !this.captured) { + this.captured = true; + + var winHeight = + (document.documentElement.clientHeight || + document.body.clientHeight) - 80, + _height = this.getDom().offsetHeight, + _top = uiUtils.getClientRect(this.combox.getDom()).top, + content = this.getDom("content"), + ifr = this.getDom("body").getElementsByTagName("iframe"), + me = this; + + ifr.length && (ifr = ifr[0]); + + while (_top + _height > winHeight) { + _height -= 30; + } + content.style.height = _height + "px"; + //同步更改iframe高度 + ifr && (ifr.style.height = _height + "px"); + + //阻止在combox上的鼠标滚轮事件, 防止用户的正常操作被误解 + domUtils.on( + content, + "onmousewheel" in document.body ? "mousewheel" : "DOMMouseScroll", + function (e) { + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + + if (e.wheelDelta) { + content.scrollTop -= e.wheelDelta / 120 * 60; + } else { + content.scrollTop -= e.detail / -3 * 60; + } + } + ); + } + this.fireEvent("postRenderAfter"); + this.hide(true); + this._UIBase_postRender(); + }, + _doAutoRender: function () { + if (!this.getDom() && this.autoRender) { + this.render(); + } + }, + mesureSize: function () { + var box = this.getDom("content"); + return uiUtils.getClientRect(box); + }, + fitSize: function () { + // console.log('fitSize.popup') + if (this.captureWheel && this.sized) { + return this.__size; + } + this.sized = true; + var popBodyEl = this.getDom("body"); + popBodyEl.style.width = ""; + popBodyEl.style.height = ""; + var size = this.mesureSize(); + if (this.captureWheel) { + popBodyEl.style.width = -(-20 - size.width) + "px"; + var height = parseInt(this.getDom("content").style.height, 10); + !window.isNaN(height) && (size.height = height); + } else { + popBodyEl.style.width = size.width + "px"; + } + popBodyEl.style.height = size.height + "px"; + this.__size = size; + this.captureWheel && (this.getDom("content").style.overflow = "auto"); + return size; + }, + showAnchor: function (element, hoz) { + this.showAnchorRect(uiUtils.getClientRect(element), hoz); + }, + showAnchorRect: function (rect, hoz, adj) { + this._doAutoRender(); + var vpRect = uiUtils.getViewportRect(); + this.getDom().style.visibility = "hidden"; + this._show(); + var popSize = this.fitSize(); + + var sideLeft, sideUp, left, top; + if (hoz) { + sideLeft = + this.canSideLeft && + (rect.right + popSize.width > vpRect.right && + rect.left > popSize.width); + sideUp = + this.canSideUp && + (rect.top + popSize.height > vpRect.bottom && + rect.bottom > popSize.height); + left = sideLeft ? rect.left - popSize.width : rect.right; + top = sideUp ? rect.bottom - popSize.height : rect.top; + } else { + sideLeft = + this.canSideLeft && + (rect.right + popSize.width > vpRect.right && + rect.left > popSize.width); + sideUp = + this.canSideUp && + (rect.top + popSize.height > vpRect.bottom && + rect.bottom > popSize.height); + left = sideLeft ? rect.right - popSize.width : rect.left; + top = sideUp ? rect.top - popSize.height : rect.bottom; + } + if (!sideUp) { + if (top + popSize.height > vpRect.bottom) { + top = vpRect.bottom - popSize.height + } + } + // console.log('popup.showAnchorRect', vpRect, rect, hoz, sideUp, sideLeft, left, top); + + var popEl = this.getDom(); + uiUtils.setViewportOffset(popEl, { + left: left, + top: top + }); + domUtils.removeClasses(popEl, ANCHOR_CLASSES); + popEl.className += + " " + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)]; + if (this.editor) { + popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10; + baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = + popEl.style.zIndex - 1; + } + this.getDom().style.visibility = "visible"; + }, + showAt: function (offset) { + var left = offset.left; + var top = offset.top; + var rect = { + left: left, + top: top, + right: left, + bottom: top, + height: 0, + width: 0 + }; + this.showAnchorRect(rect, false, true); + }, + _show: function () { + if (this._hidden) { + var box = this.getDom(); + box.style.display = ""; + this._hidden = false; + // if (box.setActive) { + // box.setActive(); + // } + this.fireEvent("show"); + } + }, + isHidden: function () { + return this._hidden; + }, + show: function () { + this._doAutoRender(); + this._show(); + }, + hide: function (notNofity) { + if (!this._hidden && this.getDom()) { + this.getDom().style.display = "none"; + this._hidden = true; + if (!notNofity) { + this.fireEvent("hide"); + } + } + }, + queryAutoHide: function (el) { + return !el || !uiUtils.contains(this.getDom(), el); + } + }; + utils.inherits(Popup, UIBase); + + domUtils.on(document, "mousedown", function (evt) { + var el = evt.target || evt.srcElement; + closeAllPopup(evt, el); + }); + domUtils.on(window, "scroll", function (evt, el) { + closeAllPopup(evt, el); + }); + })(); // ui/colorpicker.js ///import core ///import uicore -(function() { - var utils = baidu.editor.utils, - UIBase = baidu.editor.ui.UIBase, - ColorPicker = (baidu.editor.ui.ColorPicker = function(options) { - this.initOptions(options); - this.noColorText = this.noColorText || this.editor.getLang("clearColor"); - this.initUIBase(); - }); + (function () { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + ColorPicker = (baidu.editor.ui.ColorPicker = function (options) { + this.initOptions(options); + this.noColorText = this.noColorText || this.editor.getLang("clearColor"); + this.initUIBase(); + }); - ColorPicker.prototype = { - getHtmlTpl: function() { - return genColorPicker(this.noColorText, this.editor); - }, - _onTableClick: function(evt) { - var tgt = evt.target || evt.srcElement; - var color = tgt.getAttribute("data-color"); - if (color) { - this.fireEvent("pickcolor", color); - } - }, - _onTableOver: function(evt) { - var tgt = evt.target || evt.srcElement; - var color = tgt.getAttribute("data-color"); - if (color) { - this.getDom("preview").style.backgroundColor = color; - } - }, - _onTableOut: function() { - this.getDom("preview").style.backgroundColor = ""; - }, - _onPickNoColor: function() { - this.fireEvent("picknocolor"); - }, - _onColorSelect: function(evt) { - var input = evt.target || evt.srcElement; - var color = input.value; - if (color) { - this.fireEvent("pickcolor", color); - } - } - }; - utils.inherits(ColorPicker, UIBase); + ColorPicker.prototype = { + getHtmlTpl: function () { + return genColorPicker(this.noColorText, this.editor); + }, + _onTableClick: function (evt) { + var tgt = evt.target || evt.srcElement; + var color = tgt.getAttribute("data-color"); + if (color) { + this.fireEvent("pickcolor", color); + } + }, + _onTableOver: function (evt) { + var tgt = evt.target || evt.srcElement; + var color = tgt.getAttribute("data-color"); + if (color) { + this.getDom("preview").style.backgroundColor = color; + } + }, + _onTableOut: function () { + this.getDom("preview").style.backgroundColor = ""; + }, + _onPickNoColor: function () { + this.fireEvent("picknocolor"); + }, + _onColorSelect: function (evt) { + var input = evt.target || evt.srcElement; + var color = input.value; + if (color) { + this.fireEvent("pickcolor", color); + } + } + }; + utils.inherits(ColorPicker, UIBase); - var COLORS = ("ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646," + - "f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada," + - "d8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5," + - "bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f," + - "a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09," + - "7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806," + - "c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,").split( - "," - ); + var COLORS = ("ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646," + + "f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada," + + "d8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5," + + "bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f," + + "a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09," + + "7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806," + + "c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,").split( + "," + ); - function genColorPicker(noColorText, editor) { - var html = - '
    ' + - '
    ' + - // '
    ' + - '
    ' + - '
    ' + - noColorText + - "
    " + - "
    " + - '' + - '" + - ''; - for (var i = 0; i < COLORS.length; i++) { - if (i && i % 10 === 0) { - html += - "" + - (i == 60 - ? '" - : "") + - ""; - } - html += i < 70 - ? '" - : ""; - } - html += ""; - html += "
    ' + - editor.getLang("themeColor") + - "
    ' + - editor.getLang("standardColor") + - "
    "; - return html; - } -})(); + function genColorPicker(noColorText, editor) { + var html = + '
    ' + + '
    ' + + // '
    ' + + '
    ' + + '
    ' + + noColorText + + "
    " + + "
    " + + '' + + '" + + ''; + for (var i = 0; i < COLORS.length; i++) { + if (i && i % 10 === 0) { + html += + "" + + (i == 60 + ? '" + : "") + + ""; + } + html += i < 70 + ? '" + : ""; + } + html += ""; + html += "
    ' + + editor.getLang("themeColor") + + "
    ' + + editor.getLang("standardColor") + + "
    "; + return html; + } + })(); // ui/tablepicker.js ///import core ///import uicore -(function() { - var utils = baidu.editor.utils, - uiUtils = baidu.editor.ui.uiUtils, - UIBase = baidu.editor.ui.UIBase; + (function () { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase; - var TablePicker = (baidu.editor.ui.TablePicker = function(options) { - this.initOptions(options); - this.initTablePicker(); - }); - TablePicker.prototype = { - defaultNumRows: 10, - defaultNumCols: 10, - maxNumRows: 20, - maxNumCols: 20, - numRows: 10, - numCols: 10, - lengthOfCellSide: 22, - initTablePicker: function() { - this.initUIBase(); - }, - getHtmlTpl: function() { - var me = this; - return ( - '
    ' + - '
    ' + - '
    ' + - '' + - "
    " + - '
    " + - '
    ' + - "
    " + - "
    " + - "
    " - ); - }, - _UIBase_render: UIBase.prototype.render, - render: function(holder) { - this._UIBase_render(holder); - this.getDom("label").innerHTML = - "0" + - this.editor.getLang("t_row") + - " x 0" + - this.editor.getLang("t_col"); - }, - _track: function(numCols, numRows) { - var style = this.getDom("overlay").style; - var sideLen = this.lengthOfCellSide; - style.width = numCols * sideLen + "px"; - style.height = numRows * sideLen + "px"; - var label = this.getDom("label"); - label.innerHTML = - numCols + - this.editor.getLang("t_col") + - " x " + - numRows + - this.editor.getLang("t_row"); - this.numCols = numCols; - this.numRows = numRows; - }, - _onMouseOver: function(evt, el) { - var rel = evt.relatedTarget || evt.fromElement; - if (!uiUtils.contains(el, rel) && el !== rel) { - this.getDom("label").innerHTML = - "0" + - this.editor.getLang("t_col") + - " x 0" + - this.editor.getLang("t_row"); - this.getDom("overlay").style.visibility = ""; - } - }, - _onMouseOut: function(evt, el) { - var rel = evt.relatedTarget || evt.toElement; - if (!uiUtils.contains(el, rel) && el !== rel) { - this.getDom("label").innerHTML = - "0" + - this.editor.getLang("t_col") + - " x 0" + - this.editor.getLang("t_row"); - this.getDom("overlay").style.visibility = "hidden"; - } - }, - _onMouseMove: function(evt, el) { - var style = this.getDom("overlay").style; - var offset = uiUtils.getEventOffset(evt); - var sideLen = this.lengthOfCellSide; - var numCols = Math.ceil(offset.left / sideLen); - var numRows = Math.ceil(offset.top / sideLen); - this._track(numCols, numRows); - }, - _onClick: function() { - this.fireEvent("picktable", this.numCols, this.numRows); - } - }; - utils.inherits(TablePicker, UIBase); -})(); + var TablePicker = (baidu.editor.ui.TablePicker = function (options) { + this.initOptions(options); + this.initTablePicker(); + }); + TablePicker.prototype = { + defaultNumRows: 10, + defaultNumCols: 10, + maxNumRows: 20, + maxNumCols: 20, + numRows: 10, + numCols: 10, + lengthOfCellSide: 22, + initTablePicker: function () { + this.initUIBase(); + }, + getHtmlTpl: function () { + var me = this; + return ( + '
    ' + + '
    ' + + '
    ' + + '' + + "
    " + + '
    " + + '
    ' + + "
    " + + "
    " + + "
    " + ); + }, + _UIBase_render: UIBase.prototype.render, + render: function (holder) { + this._UIBase_render(holder); + this.getDom("label").innerHTML = + "0" + + this.editor.getLang("t_row") + + " x 0" + + this.editor.getLang("t_col"); + }, + _track: function (numCols, numRows) { + var style = this.getDom("overlay").style; + var sideLen = this.lengthOfCellSide; + style.width = numCols * sideLen + "px"; + style.height = numRows * sideLen + "px"; + var label = this.getDom("label"); + label.innerHTML = + numCols + + this.editor.getLang("t_col") + + " x " + + numRows + + this.editor.getLang("t_row"); + this.numCols = numCols; + this.numRows = numRows; + }, + _onMouseOver: function (evt, el) { + var rel = evt.relatedTarget || evt.fromElement; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.getDom("label").innerHTML = + "0" + + this.editor.getLang("t_col") + + " x 0" + + this.editor.getLang("t_row"); + this.getDom("overlay").style.visibility = ""; + } + }, + _onMouseOut: function (evt, el) { + var rel = evt.relatedTarget || evt.toElement; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.getDom("label").innerHTML = + "0" + + this.editor.getLang("t_col") + + " x 0" + + this.editor.getLang("t_row"); + this.getDom("overlay").style.visibility = "hidden"; + } + }, + _onMouseMove: function (evt, el) { + var style = this.getDom("overlay").style; + var offset = uiUtils.getEventOffset(evt); + var sideLen = this.lengthOfCellSide; + var numCols = Math.ceil(offset.left / sideLen); + var numRows = Math.ceil(offset.top / sideLen); + this._track(numCols, numRows); + }, + _onClick: function () { + this.fireEvent("picktable", this.numCols, this.numRows); + } + }; + utils.inherits(TablePicker, UIBase); + })(); // ui/stateful.js -(function() { - var browser = baidu.editor.browser, - domUtils = baidu.editor.dom.domUtils, - uiUtils = baidu.editor.ui.uiUtils; + (function () { + var browser = baidu.editor.browser, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils; - var TPL_STATEFUL = - 'onmousedown="$$.Stateful_onMouseDown(event, this);"' + - ' onmouseup="$$.Stateful_onMouseUp(event, this);"' + - (browser.ie - ? ' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' + - ' onmouseleave="$$.Stateful_onMouseLeave(event, this);"' - : ' onmouseover="$$.Stateful_onMouseOver(event, this);"' + - ' onmouseout="$$.Stateful_onMouseOut(event, this);"'); + var TPL_STATEFUL = + 'onmousedown="$$.Stateful_onMouseDown(event, this);"' + + ' onmouseup="$$.Stateful_onMouseUp(event, this);"' + + (browser.ie + ? ' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' + + ' onmouseleave="$$.Stateful_onMouseLeave(event, this);"' + : ' onmouseover="$$.Stateful_onMouseOver(event, this);"' + + ' onmouseout="$$.Stateful_onMouseOut(event, this);"'); - baidu.editor.ui.Stateful = { - alwalysHoverable: false, - target: null, //目标元素和this指向dom不一样 - Stateful_init: function() { - this._Stateful_dGetHtmlTpl = this.getHtmlTpl; - this.getHtmlTpl = this.Stateful_getHtmlTpl; - }, - Stateful_getHtmlTpl: function() { - var tpl = this._Stateful_dGetHtmlTpl(); - // 使用function避免$转义 - return tpl.replace(/stateful/g, function() { - return TPL_STATEFUL; - }); - }, - Stateful_onMouseEnter: function(evt, el) { - this.target = el; - if (!this.isDisabled() || this.alwalysHoverable) { - this.addState("hover"); - this.fireEvent("over"); - } - }, - Stateful_onMouseLeave: function(evt, el) { - if (!this.isDisabled() || this.alwalysHoverable) { - this.removeState("hover"); - this.removeState("active"); - this.fireEvent("out"); - } - }, - Stateful_onMouseOver: function(evt, el) { - var rel = evt.relatedTarget; - if (!uiUtils.contains(el, rel) && el !== rel) { - this.Stateful_onMouseEnter(evt, el); - } - }, - Stateful_onMouseOut: function(evt, el) { - var rel = evt.relatedTarget; - if (!uiUtils.contains(el, rel) && el !== rel) { - this.Stateful_onMouseLeave(evt, el); - } - }, - Stateful_onMouseDown: function(evt, el) { - if (!this.isDisabled()) { - this.addState("active"); - } - }, - Stateful_onMouseUp: function(evt, el) { - if (!this.isDisabled()) { - this.removeState("active"); - } - }, - Stateful_postRender: function() { - if (this.disabled && !this.hasState("disabled")) { - this.addState("disabled"); - } - }, - hasState: function(state) { - return domUtils.hasClass(this.getStateDom(), "edui-state-" + state); - }, - addState: function(state) { - if (!this.hasState(state)) { - this.getStateDom().className += " edui-state-" + state; - } - }, - removeState: function(state) { - if (this.hasState(state)) { - domUtils.removeClasses(this.getStateDom(), ["edui-state-" + state]); - } - }, - getStateDom: function() { - return this.getDom("state"); - }, - isChecked: function() { - return this.hasState("checked"); - }, - setChecked: function(checked) { - if (!this.isDisabled() && checked) { - this.addState("checked"); - } else { - this.removeState("checked"); - } - }, - isDisabled: function() { - return this.hasState("disabled"); - }, - setDisabled: function(disabled) { - if (disabled) { - this.removeState("hover"); - this.removeState("checked"); - this.removeState("active"); - this.addState("disabled"); - } else { - this.removeState("disabled"); - } - } - }; -})(); + baidu.editor.ui.Stateful = { + alwalysHoverable: false, + target: null, //目标元素和this指向dom不一样 + Stateful_init: function () { + this._Stateful_dGetHtmlTpl = this.getHtmlTpl; + this.getHtmlTpl = this.Stateful_getHtmlTpl; + }, + Stateful_getHtmlTpl: function () { + var tpl = this._Stateful_dGetHtmlTpl(); + // 使用function避免$转义 + return tpl.replace(/stateful/g, function () { + return TPL_STATEFUL; + }); + }, + Stateful_onMouseEnter: function (evt, el) { + this.target = el; + if (!this.isDisabled() || this.alwalysHoverable) { + this.addState("hover"); + this.fireEvent("over"); + } + }, + Stateful_onMouseLeave: function (evt, el) { + if (!this.isDisabled() || this.alwalysHoverable) { + this.removeState("hover"); + this.removeState("active"); + this.fireEvent("out"); + } + }, + Stateful_onMouseOver: function (evt, el) { + var rel = evt.relatedTarget; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.Stateful_onMouseEnter(evt, el); + } + }, + Stateful_onMouseOut: function (evt, el) { + var rel = evt.relatedTarget; + if (!uiUtils.contains(el, rel) && el !== rel) { + this.Stateful_onMouseLeave(evt, el); + } + }, + Stateful_onMouseDown: function (evt, el) { + if (!this.isDisabled()) { + this.addState("active"); + } + }, + Stateful_onMouseUp: function (evt, el) { + if (!this.isDisabled()) { + this.removeState("active"); + } + }, + Stateful_postRender: function () { + if (this.disabled && !this.hasState("disabled")) { + this.addState("disabled"); + } + }, + hasState: function (state) { + return domUtils.hasClass(this.getStateDom(), "edui-state-" + state); + }, + addState: function (state) { + if (!this.hasState(state)) { + this.getStateDom().className += " edui-state-" + state; + } + }, + removeState: function (state) { + if (this.hasState(state)) { + domUtils.removeClasses(this.getStateDom(), ["edui-state-" + state]); + } + }, + getStateDom: function () { + return this.getDom("state"); + }, + isChecked: function () { + return this.hasState("checked"); + }, + setChecked: function (checked) { + if (!this.isDisabled() && checked) { + this.addState("checked"); + } else { + this.removeState("checked"); + } + }, + isDisabled: function () { + return this.hasState("disabled"); + }, + setDisabled: function (disabled) { + if (disabled) { + this.removeState("hover"); + this.removeState("checked"); + this.removeState("active"); + this.addState("disabled"); + } else { + this.removeState("disabled"); + } + } + }; + })(); // ui/button.js ///import core ///import uicore ///import ui/stateful.js -(function() { - var utils = baidu.editor.utils, - UIBase = baidu.editor.ui.UIBase, - Stateful = baidu.editor.ui.Stateful, - Button = (baidu.editor.ui.Button = function(options) { - if (options.name) { - var btnName = options.name; - var cssRules = options.cssRules; - if (!options.className) { - options.className = "edui-for-" + btnName; - } - options.cssRules = - ".edui-" + - (options.theme || "default") + - " .edui-toolbar .edui-button.edui-for-" + - btnName + - " .edui-icon {" + - cssRules + - "}"; - } - this.initOptions(options); - this.initButton(); - }); - Button.prototype = { - uiName: "button", - label: "", - title: "", - showIcon: true, - showText: true, - cssRules: "", - initButton: function() { - this.initUIBase(); - this.Stateful_init(); - if (this.cssRules) { - utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules); - } - }, - getHtmlTpl: function() { - return ( - '
    ' + - '
    ' + - '
    ' + - (this.showIcon ? '
    ' : "") + - (this.showText - ? '
    ' + this.label + "
    " - : "") + - "
    " + - "
    " + - "
    " - ); - }, - postRender: function() { - this.Stateful_postRender(); - this.setDisabled(this.disabled); - }, - _onMouseDown: function(e) { - var target = e.target || e.srcElement, - tagName = target && target.tagName && target.tagName.toLowerCase(); - if (tagName == "input" || tagName == "object" || tagName == "object") { - return false; - } - }, - _onClick: function() { - if (!this.isDisabled()) { - this.fireEvent("click"); - } - }, - setTitle: function(text) { - var label = this.getDom("label"); - label.innerHTML = text; - } - }; - utils.inherits(Button, UIBase); - utils.extend(Button.prototype, Stateful); -})(); + (function () { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + Stateful = baidu.editor.ui.Stateful, + Button = (baidu.editor.ui.Button = function (options) { + if (options.name) { + var btnName = options.name; + var cssRules = options.cssRules; + if (!options.className) { + options.className = "edui-for-" + btnName; + } + options.cssRules = + ".edui-" + + (options.theme || "default") + + " .edui-toolbar .edui-button.edui-for-" + + btnName + + " .edui-icon {" + + cssRules + + "}"; + } + this.initOptions(options); + this.initButton(); + }); + Button.prototype = { + uiName: "button", + label: "", + title: "", + showIcon: true, + showText: true, + cssRules: "", + initButton: function () { + this.initUIBase(); + this.Stateful_init(); + if (this.cssRules) { + utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules); + } + }, + getHtmlTpl: function () { + return ( + '
    ' + + '
    ' + + '
    ' + + (this.showIcon ? '
    ' : "") + + (this.showText + ? '
    ' + this.label + "
    " + : "") + + "
    " + + "
    " + + "
    " + ); + }, + postRender: function () { + this.Stateful_postRender(); + this.setDisabled(this.disabled); + }, + _onMouseDown: function (e) { + var target = e.target || e.srcElement, + tagName = target && target.tagName && target.tagName.toLowerCase(); + if (tagName == "input" || tagName == "object" || tagName == "object") { + return false; + } + }, + _onClick: function () { + if (!this.isDisabled()) { + this.fireEvent("click"); + } + }, + setTitle: function (text) { + var label = this.getDom("label"); + label.innerHTML = text; + } + }; + utils.inherits(Button, UIBase); + utils.extend(Button.prototype, Stateful); + })(); // ui/splitbutton.js ///import core ///import uicore ///import ui/stateful.js -(function() { - var utils = baidu.editor.utils, - uiUtils = baidu.editor.ui.uiUtils, - domUtils = baidu.editor.dom.domUtils, - UIBase = baidu.editor.ui.UIBase, - Stateful = baidu.editor.ui.Stateful, - SplitButton = (baidu.editor.ui.SplitButton = function(options) { - this.initOptions(options); - this.initSplitButton(); - }); - SplitButton.prototype = { - popup: null, - uiName: "splitbutton", - title: "", - initSplitButton: function() { - this.initUIBase(); - this.Stateful_init(); - var me = this; - if (this.popup != null) { - var popup = this.popup; - this.popup = null; - this.setPopup(popup); - } - }, - _UIBase_postRender: UIBase.prototype.postRender, - postRender: function() { - this.Stateful_postRender(); - this._UIBase_postRender(); - }, - setPopup: function(popup) { - if (this.popup === popup) return; - if (this.popup != null) { - this.popup.dispose(); - } - popup.addListener("show", utils.bind(this._onPopupShow, this)); - popup.addListener("hide", utils.bind(this._onPopupHide, this)); - popup.addListener( - "postrender", - utils.bind(function() { - popup - .getDom("body") - .appendChild( - uiUtils.createElementByHtml( - '
    ' - ) - ); - popup.getDom().className += " " + this.className; - }, this) - ); - this.popup = popup; - }, - _onPopupShow: function() { - this.addState("opened"); - }, - _onPopupHide: function() { - this.removeState("opened"); - }, - getHtmlTpl: function() { - return ( - '
    ' + - "
    ' + - '
    ' + - '
    ' + - "
    " + - '
    ' + - '
    ' + - "
    " - ); - }, - showPopup: function() { - // 当popup往上弹出的时候,做特殊处理 - var rect = uiUtils.getClientRect(this.getDom()); - rect.top -= this.popup.SHADOW_RADIUS; - rect.height += this.popup.SHADOW_RADIUS; - this.popup.showAnchorRect(rect); - }, - _onArrowClick: function(event, el) { - if (!this.isDisabled()) { - this.showPopup(); - } - }, - _onButtonClick: function() { - if (!this.isDisabled()) { - this.fireEvent("buttonclick"); - } - } - }; - utils.inherits(SplitButton, UIBase); - utils.extend(SplitButton.prototype, Stateful, true); -})(); + (function () { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + domUtils = baidu.editor.dom.domUtils, + UIBase = baidu.editor.ui.UIBase, + Stateful = baidu.editor.ui.Stateful, + SplitButton = (baidu.editor.ui.SplitButton = function (options) { + this.initOptions(options); + this.initSplitButton(); + }); + SplitButton.prototype = { + popup: null, + uiName: "splitbutton", + title: "", + initSplitButton: function () { + this.initUIBase(); + this.Stateful_init(); + var me = this; + if (this.popup != null) { + var popup = this.popup; + this.popup = null; + this.setPopup(popup); + } + }, + _UIBase_postRender: UIBase.prototype.postRender, + postRender: function () { + this.Stateful_postRender(); + this._UIBase_postRender(); + }, + setPopup: function (popup) { + if (this.popup === popup) return; + if (this.popup != null) { + this.popup.dispose(); + } + popup.addListener("show", utils.bind(this._onPopupShow, this)); + popup.addListener("hide", utils.bind(this._onPopupHide, this)); + popup.addListener( + "postrender", + utils.bind(function () { + popup + .getDom("body") + .appendChild( + uiUtils.createElementByHtml( + '
    ' + ) + ); + popup.getDom().className += " " + this.className; + }, this) + ); + this.popup = popup; + }, + _onPopupShow: function () { + this.addState("opened"); + }, + _onPopupHide: function () { + this.removeState("opened"); + }, + getHtmlTpl: function () { + return ( + '
    ' + + "
    ' + + '
    ' + + '
    ' + + "
    " + + '
    ' + + '
    ' + + "
    " + ); + }, + showPopup: function () { + // 当popup往上弹出的时候,做特殊处理 + var rect = uiUtils.getClientRect(this.getDom()); + rect.top -= this.popup.SHADOW_RADIUS; + rect.height += this.popup.SHADOW_RADIUS; + this.popup.showAnchorRect(rect); + }, + _onArrowClick: function (event, el) { + if (!this.isDisabled()) { + this.showPopup(); + } + }, + _onButtonClick: function () { + if (!this.isDisabled()) { + this.fireEvent("buttonclick"); + } + } + }; + utils.inherits(SplitButton, UIBase); + utils.extend(SplitButton.prototype, Stateful, true); + })(); // ui/colorbutton.js @@ -28813,62 +32246,62 @@ UE.ui = baidu.editor.ui = {}; ///import ui/colorpicker.js ///import ui/popup.js ///import ui/splitbutton.js -(function() { - var utils = baidu.editor.utils, - uiUtils = baidu.editor.ui.uiUtils, - ColorPicker = baidu.editor.ui.ColorPicker, - Popup = baidu.editor.ui.Popup, - SplitButton = baidu.editor.ui.SplitButton, - ColorButton = (baidu.editor.ui.ColorButton = function(options) { - this.initOptions(options); - this.initColorButton(); - }); - ColorButton.prototype = { - initColorButton: function() { - var me = this; - this.popup = new Popup({ - content: new ColorPicker({ - noColorText: me.editor.getLang("clearColor"), - editor: me.editor, - onpickcolor: function(t, color) { - me._onPickColor(color); - }, - onpicknocolor: function(t, color) { - me._onPickNoColor(color); - } - }), - editor: me.editor - }); - this.initSplitButton(); - }, - _SplitButton_postRender: SplitButton.prototype.postRender, - postRender: function() { - this._SplitButton_postRender(); - this.getDom("button_body").appendChild( - uiUtils.createElementByHtml( - '
    ' - ) - ); - this.getDom().className += " edui-colorbutton"; - }, - setColor: function(color) { - this.getDom("colorlump").style.backgroundColor = color; - this.color = color; - }, - _onPickColor: function(color) { - if (this.fireEvent("pickcolor", color) !== false) { - this.setColor(color); - this.popup.hide(); - } - }, - _onPickNoColor: function(color) { - if (this.fireEvent("picknocolor") !== false) { - this.popup.hide(); - } - } - }; - utils.inherits(ColorButton, SplitButton); -})(); + (function () { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + ColorPicker = baidu.editor.ui.ColorPicker, + Popup = baidu.editor.ui.Popup, + SplitButton = baidu.editor.ui.SplitButton, + ColorButton = (baidu.editor.ui.ColorButton = function (options) { + this.initOptions(options); + this.initColorButton(); + }); + ColorButton.prototype = { + initColorButton: function () { + var me = this; + this.popup = new Popup({ + content: new ColorPicker({ + noColorText: me.editor.getLang("clearColor"), + editor: me.editor, + onpickcolor: function (t, color) { + me._onPickColor(color); + }, + onpicknocolor: function (t, color) { + me._onPickNoColor(color); + } + }), + editor: me.editor + }); + this.initSplitButton(); + }, + _SplitButton_postRender: SplitButton.prototype.postRender, + postRender: function () { + this._SplitButton_postRender(); + this.getDom("button_body").appendChild( + uiUtils.createElementByHtml( + '
    ' + ) + ); + this.getDom().className += " edui-colorbutton"; + }, + setColor: function (color) { + this.getDom("colorlump").style.backgroundColor = color; + this.color = color; + }, + _onPickColor: function (color) { + if (this.fireEvent("pickcolor", color) !== false) { + this.setColor(color); + this.popup.hide(); + } + }, + _onPickNoColor: function (color) { + if (this.fireEvent("picknocolor") !== false) { + this.popup.hide(); + } + }, + }; + utils.inherits(ColorButton, SplitButton); + })(); // ui/tablebutton.js @@ -28877,210 +32310,210 @@ UE.ui = baidu.editor.ui = {}; ///import ui/popup.js ///import ui/tablepicker.js ///import ui/splitbutton.js -(function() { - var utils = baidu.editor.utils, - Popup = baidu.editor.ui.Popup, - TablePicker = baidu.editor.ui.TablePicker, - SplitButton = baidu.editor.ui.SplitButton, - TableButton = (baidu.editor.ui.TableButton = function(options) { - this.initOptions(options); - this.initTableButton(); - }); - TableButton.prototype = { - initTableButton: function() { - var me = this; - this.popup = new Popup({ - content: new TablePicker({ - editor: me.editor, - onpicktable: function(t, numCols, numRows) { - me._onPickTable(numCols, numRows); - } - }), - editor: me.editor - }); - this.initSplitButton(); - }, - _onPickTable: function(numCols, numRows) { - if (this.fireEvent("picktable", numCols, numRows) !== false) { - this.popup.hide(); - } - } - }; - utils.inherits(TableButton, SplitButton); -})(); + (function () { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + TablePicker = baidu.editor.ui.TablePicker, + SplitButton = baidu.editor.ui.SplitButton, + TableButton = (baidu.editor.ui.TableButton = function (options) { + this.initOptions(options); + this.initTableButton(); + }); + TableButton.prototype = { + initTableButton: function () { + var me = this; + this.popup = new Popup({ + content: new TablePicker({ + editor: me.editor, + onpicktable: function (t, numCols, numRows) { + me._onPickTable(numCols, numRows); + } + }), + editor: me.editor + }); + this.initSplitButton(); + }, + _onPickTable: function (numCols, numRows) { + if (this.fireEvent("picktable", numCols, numRows) !== false) { + this.popup.hide(); + } + } + }; + utils.inherits(TableButton, SplitButton); + })(); // ui/autotypesetpicker.js ///import core ///import uicore -(function() { - var utils = baidu.editor.utils, - UIBase = baidu.editor.ui.UIBase; + (function () { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase; - var AutoTypeSetPicker = (baidu.editor.ui.AutoTypeSetPicker = function( - options - ) { - this.initOptions(options); - this.initAutoTypeSetPicker(); - }); - AutoTypeSetPicker.prototype = { - initAutoTypeSetPicker: function() { - this.initUIBase(); - }, - getHtmlTpl: function() { - var me = this.editor, - opt = me.options.autotypeset, - lang = me.getLang("autoTypeSet"); + var AutoTypeSetPicker = (baidu.editor.ui.AutoTypeSetPicker = function ( + options + ) { + this.initOptions(options); + this.initAutoTypeSetPicker(); + }); + AutoTypeSetPicker.prototype = { + initAutoTypeSetPicker: function () { + this.initUIBase(); + }, + getHtmlTpl: function () { + var me = this.editor, + opt = me.options.autotypeset, + lang = me.getLang("autoTypeSet"); - var textAlignInputName = "textAlignValue" + me.uid, - imageBlockInputName = "imageBlockLineValue" + me.uid, - symbolConverInputName = "symbolConverValue" + me.uid; + var textAlignInputName = "textAlignValue" + me.uid, + imageBlockInputName = "imageBlockLineValue" + me.uid, + symbolConverInputName = "symbolConverValue" + me.uid; - return ( - '
    ' + - '
    ' + - "" + - '" + - '" + - "" + - '" + - '" + - "" + - "" + - '" + - '" + - "" + - '" + - '" + - '" + - "" + - '" + - '" + - '" + - "" + - "
    " + - lang.mergeLine + - '" + - lang.delLine + - "
    " + - lang.removeFormat + - '" + - lang.indent + - "
    " + - lang.alignment + - "' + - '" + - me.getLang("justifyleft") + - '" + - me.getLang("justifycenter") + - '" + - me.getLang("justifyright") + - "
    " + - lang.imageFloat + - "' + - '" + - me.getLang("default") + - '" + - me.getLang("justifyleft") + - '" + - me.getLang("justifycenter") + - '" + - me.getLang("justifyright") + - "
    " + - lang.removeFontsize + - '" + - lang.removeFontFamily + - "
    " + - lang.removeHtml + - "
    " + - lang.pasteFilter + - "
    " + - lang.symbol + - "' + - '" + - lang.bdc2sb + - '" + - lang.tobdc + - "" + - "
    " + - "
    " + - "
    " - ); - }, - _UIBase_render: UIBase.prototype.render - }; - utils.inherits(AutoTypeSetPicker, UIBase); -})(); + return ( + '
    ' + + '
    ' + + "" + + '" + + '" + + "" + + '" + + '" + + "" + + "" + + '" + + '" + + "" + + '" + + '" + + '" + + "" + + '" + + '" + + '" + + "" + + "
    " + + lang.mergeLine + + '" + + lang.delLine + + "
    " + + lang.removeFormat + + '" + + lang.indent + + "
    " + + lang.alignment + + "' + + '" + + me.getLang("justifyleft") + + '" + + me.getLang("justifycenter") + + '" + + me.getLang("justifyright") + + "
    " + + lang.imageFloat + + "' + + '" + + me.getLang("default") + + '" + + me.getLang("justifyleft") + + '" + + me.getLang("justifycenter") + + '" + + me.getLang("justifyright") + + "
    " + + lang.removeFontsize + + '" + + lang.removeFontFamily + + "
    " + + lang.removeHtml + + "
    " + + lang.pasteFilter + + "
    " + + lang.symbol + + "' + + '" + + lang.bdc2sb + + '" + + lang.tobdc + + "" + + "
    " + + "
    " + + "
    " + ); + }, + _UIBase_render: UIBase.prototype.render + }; + utils.inherits(AutoTypeSetPicker, UIBase); + })(); // ui/autotypesetbutton.js @@ -29089,380 +32522,380 @@ UE.ui = baidu.editor.ui = {}; ///import ui/popup.js ///import ui/autotypesetpicker.js ///import ui/splitbutton.js -(function() { - var utils = baidu.editor.utils, - Popup = baidu.editor.ui.Popup, - AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker, - SplitButton = baidu.editor.ui.SplitButton, - AutoTypeSetButton = (baidu.editor.ui.AutoTypeSetButton = function(options) { - this.initOptions(options); - this.initAutoTypeSetButton(); - }); - function getPara(me) { - var opt = {}, - cont = me.getDom(), - editorId = me.editor.uid, - inputType = null, - attrName = null, - ipts = domUtils.getElementsByTagName(cont, "input"); - for (var i = ipts.length - 1, ipt; (ipt = ipts[i--]); ) { - inputType = ipt.getAttribute("type"); - if (inputType == "checkbox") { - attrName = ipt.getAttribute("name"); - opt[attrName] && delete opt[attrName]; - if (ipt.checked) { - var attrValue = document.getElementById( - attrName + "Value" + editorId - ); - if (attrValue) { - if (/input/gi.test(attrValue.tagName)) { - opt[attrName] = attrValue.value; - } else { - var iptChilds = attrValue.getElementsByTagName("input"); - for ( - var j = iptChilds.length - 1, iptchild; - (iptchild = iptChilds[j--]); + (function () { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker, + SplitButton = baidu.editor.ui.SplitButton, + AutoTypeSetButton = (baidu.editor.ui.AutoTypeSetButton = function (options) { + this.initOptions(options); + this.initAutoTypeSetButton(); + }); - ) { - if (iptchild.checked) { - opt[attrName] = iptchild.value; - break; - } - } - } - } else { - opt[attrName] = true; - } - } else { - opt[attrName] = false; - } - } else { - opt[ipt.getAttribute("value")] = ipt.checked; - } - } - - var selects = domUtils.getElementsByTagName(cont, "select"); - for (var i = 0, si; (si = selects[i++]); ) { - var attr = si.getAttribute("name"); - opt[attr] = opt[attr] ? si.value : ""; - } - - utils.extend(me.editor.options.autotypeset, opt); - - me.editor.setPreferences("autotypeset", opt); - } - - AutoTypeSetButton.prototype = { - initAutoTypeSetButton: function() { - var me = this; - this.popup = new Popup({ - //传入配置参数 - content: new AutoTypeSetPicker({ editor: me.editor }), - editor: me.editor, - hide: function() { - if (!this._hidden && this.getDom()) { - getPara(this); - this.getDom().style.display = "none"; - this._hidden = true; - this.fireEvent("hide"); - } - } - }); - var flag = 0; - this.popup.addListener("postRenderAfter", function() { - var popupUI = this; - if (flag) return; - var cont = this.getDom(), - btn = cont.getElementsByTagName("button")[0]; - - btn.onclick = function() { - getPara(popupUI); - me.editor.execCommand("autotypeset"); - popupUI.hide(); - }; - - domUtils.on(cont, "click", function(e) { - var target = e.target || e.srcElement, - editorId = me.editor.uid; - if (target && target.tagName == "INPUT") { - // 点击图片浮动的checkbox,去除对应的radio - if ( - target.name == "imageBlockLine" || - target.name == "textAlign" || - target.name == "symbolConver" - ) { - var checked = target.checked, - radioTd = document.getElementById( - target.name + "Value" + editorId - ), - radios = radioTd.getElementsByTagName("input"), - defalutSelect = { - imageBlockLine: "none", - textAlign: "left", - symbolConver: "tobdc" - }; - - for (var i = 0; i < radios.length; i++) { - if (checked) { - if (radios[i].value == defalutSelect[target.name]) { - radios[i].checked = "checked"; - } + function getPara(me) { + var opt = {}, + cont = me.getDom(), + editorId = me.editor.uid, + inputType = null, + attrName = null, + ipts = domUtils.getElementsByTagName(cont, "input"); + for (var i = ipts.length - 1, ipt; (ipt = ipts[i--]);) { + inputType = ipt.getAttribute("type"); + if (inputType == "checkbox") { + attrName = ipt.getAttribute("name"); + opt[attrName] && delete opt[attrName]; + if (ipt.checked) { + var attrValue = document.getElementById( + attrName + "Value" + editorId + ); + if (attrValue) { + if (/input/gi.test(attrValue.tagName)) { + opt[attrName] = attrValue.value; + } else { + var iptChilds = attrValue.getElementsByTagName("input"); + for ( + var j = iptChilds.length - 1, iptchild; + (iptchild = iptChilds[j--]); + ) { + if (iptchild.checked) { + opt[attrName] = iptchild.value; + break; + } + } + } + } else { + opt[attrName] = true; + } + } else { + opt[attrName] = false; + } } else { - radios[i].checked = false; + opt[ipt.getAttribute("value")] = ipt.checked; } - } - } - // 点击radio,选中对应的checkbox - if ( - target.name == "imageBlockLineValue" + editorId || - target.name == "textAlignValue" + editorId || - target.name == "bdc" - ) { - var checkboxs = target.parentNode.previousSibling.getElementsByTagName( - "input" - ); - checkboxs && (checkboxs[0].checked = true); } - getPara(popupUI); - } - }); + var selects = domUtils.getElementsByTagName(cont, "select"); + for (var i = 0, si; (si = selects[i++]);) { + var attr = si.getAttribute("name"); + opt[attr] = opt[attr] ? si.value : ""; + } - flag = 1; - }); - this.initSplitButton(); - } - }; - utils.inherits(AutoTypeSetButton, SplitButton); -})(); + utils.extend(me.editor.options.autotypeset, opt); + + me.editor.setPreferences("autotypeset", opt); + } + + AutoTypeSetButton.prototype = { + initAutoTypeSetButton: function () { + var me = this; + this.popup = new Popup({ + //传入配置参数 + content: new AutoTypeSetPicker({editor: me.editor}), + editor: me.editor, + hide: function () { + if (!this._hidden && this.getDom()) { + getPara(this); + this.getDom().style.display = "none"; + this._hidden = true; + this.fireEvent("hide"); + } + } + }); + var flag = 0; + this.popup.addListener("postRenderAfter", function () { + var popupUI = this; + if (flag) return; + var cont = this.getDom(), + btn = cont.getElementsByTagName("button")[0]; + + btn.onclick = function () { + getPara(popupUI); + me.editor.execCommand("autotypeset"); + popupUI.hide(); + }; + + domUtils.on(cont, "click", function (e) { + var target = e.target || e.srcElement, + editorId = me.editor.uid; + if (target && target.tagName == "INPUT") { + // 点击图片浮动的checkbox,去除对应的radio + if ( + target.name == "imageBlockLine" || + target.name == "textAlign" || + target.name == "symbolConver" + ) { + var checked = target.checked, + radioTd = document.getElementById( + target.name + "Value" + editorId + ), + radios = radioTd.getElementsByTagName("input"), + defalutSelect = { + imageBlockLine: "none", + textAlign: "left", + symbolConver: "tobdc" + }; + + for (var i = 0; i < radios.length; i++) { + if (checked) { + if (radios[i].value == defalutSelect[target.name]) { + radios[i].checked = "checked"; + } + } else { + radios[i].checked = false; + } + } + } + // 点击radio,选中对应的checkbox + if ( + target.name == "imageBlockLineValue" + editorId || + target.name == "textAlignValue" + editorId || + target.name == "bdc" + ) { + var checkboxs = target.parentNode.previousSibling.getElementsByTagName( + "input" + ); + checkboxs && (checkboxs[0].checked = true); + } + + getPara(popupUI); + } + }); + + flag = 1; + }); + this.initSplitButton(); + } + }; + utils.inherits(AutoTypeSetButton, SplitButton); + })(); // ui/cellalignpicker.js ///import core ///import uicore -(function() { - var utils = baidu.editor.utils, - Popup = baidu.editor.ui.Popup, - Stateful = baidu.editor.ui.Stateful, - UIBase = baidu.editor.ui.UIBase; + (function () { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + Stateful = baidu.editor.ui.Stateful, + UIBase = baidu.editor.ui.UIBase; - /** - * 该参数将新增一个参数: selected, 参数类型为一个Object, 形如{ 'align': 'center', 'valign': 'top' }, 表示单元格的初始 - * 对齐状态为: 竖直居上,水平居中; 其中 align的取值为:'center', 'left', 'right'; valign的取值为: 'top', 'middle', 'bottom' - * @update 2013/4/2 hancong03@baidu.com - */ - var CellAlignPicker = (baidu.editor.ui.CellAlignPicker = function(options) { - this.initOptions(options); - this.initSelected(); - this.initCellAlignPicker(); - }); - CellAlignPicker.prototype = { - //初始化选中状态, 该方法将根据传递进来的参数获取到应该选中的对齐方式图标的索引 - initSelected: function() { - var status = { - valign: { - top: 0, - middle: 1, - bottom: 2 - }, - align: { - left: 0, - center: 1, - right: 2 - }, - count: 3 - }, - result = -1; + /** + * 该参数将新增一个参数: selected, 参数类型为一个Object, 形如{ 'align': 'center', 'valign': 'top' }, 表示单元格的初始 + * 对齐状态为: 竖直居上,水平居中; 其中 align的取值为:'center', 'left', 'right'; valign的取值为: 'top', 'middle', 'bottom' + * @update 2013/4/2 hancong03@baidu.com + */ + var CellAlignPicker = (baidu.editor.ui.CellAlignPicker = function (options) { + this.initOptions(options); + this.initSelected(); + this.initCellAlignPicker(); + }); + CellAlignPicker.prototype = { + //初始化选中状态, 该方法将根据传递进来的参数获取到应该选中的对齐方式图标的索引 + initSelected: function () { + var status = { + valign: { + top: 0, + middle: 1, + bottom: 2 + }, + align: { + left: 0, + center: 1, + right: 2 + }, + count: 3 + }, + result = -1; - if (this.selected) { - this.selectedIndex = - status.valign[this.selected.valign] * status.count + - status.align[this.selected.align]; - } - }, - initCellAlignPicker: function() { - this.initUIBase(); - this.Stateful_init(); - }, - getHtmlTpl: function() { - var alignType = ["left", "center", "right"], - COUNT = 9, - tempClassName = null, - tempIndex = -1, - tmpl = []; + if (this.selected) { + this.selectedIndex = + status.valign[this.selected.valign] * status.count + + status.align[this.selected.align]; + } + }, + initCellAlignPicker: function () { + this.initUIBase(); + this.Stateful_init(); + }, + getHtmlTpl: function () { + var alignType = ["left", "center", "right"], + COUNT = 9, + tempClassName = null, + tempIndex = -1, + tmpl = []; - for (var i = 0; i < COUNT; i++) { - tempClassName = this.selectedIndex === i - ? ' class="edui-cellalign-selected" ' - : ""; - tempIndex = i % 3; + for (var i = 0; i < COUNT; i++) { + tempClassName = this.selectedIndex === i + ? ' class="edui-cellalign-selected" ' + : ""; + tempIndex = i % 3; - tempIndex === 0 && tmpl.push("
  • ' + - tmpl.join("") + - "
    " + - "" + - "" - ); - }, - getStateDom: function() { - return this.target; - }, - _onClick: function(evt) { - var target = evt.target || evt.srcElement; - if (/icon/.test(target.className)) { - this.items[target.parentNode.getAttribute("index")].onclick(); - Popup.postHide(evt); - } - }, - _UIBase_render: UIBase.prototype.render - }; - utils.inherits(CellAlignPicker, UIBase); - utils.extend(CellAlignPicker.prototype, Stateful, true); -})(); + return ( + '
    ' + + '
    ' + + '' + + tmpl.join("") + + "
    " + + "
    " + + "
    " + ); + }, + getStateDom: function () { + return this.target; + }, + _onClick: function (evt) { + var target = evt.target || evt.srcElement; + if (/icon/.test(target.className)) { + this.items[target.parentNode.getAttribute("index")].onclick(); + Popup.postHide(evt); + } + }, + _UIBase_render: UIBase.prototype.render + }; + utils.inherits(CellAlignPicker, UIBase); + utils.extend(CellAlignPicker.prototype, Stateful, true); + })(); // ui/pastepicker.js ///import core ///import uicore -(function() { - var utils = baidu.editor.utils, - Stateful = baidu.editor.ui.Stateful, - uiUtils = baidu.editor.ui.uiUtils, - UIBase = baidu.editor.ui.UIBase; + (function () { + var utils = baidu.editor.utils, + Stateful = baidu.editor.ui.Stateful, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase; - var PastePicker = (baidu.editor.ui.PastePicker = function(options) { - this.initOptions(options); - this.initPastePicker(); - }); - PastePicker.prototype = { - initPastePicker: function() { - this.initUIBase(); - this.Stateful_init(); - }, - getHtmlTpl: function() { - return ( - '
    ' + - '
    ' + - '
    ' + - this.editor.getLang("pasteOpt") + - "
    " + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - "
    " + - "
    " + - "" - ); - }, - getStateDom: function() { - return this.target; - }, - format: function(param) { - this.editor.ui._isTransfer = true; - this.editor.fireEvent("pasteTransfer", param); - }, - _onClick: function(cur) { - var node = domUtils.getNextDomNode(cur), - screenHt = uiUtils.getViewportRect().height, - subPop = uiUtils.getClientRect(node); + var PastePicker = (baidu.editor.ui.PastePicker = function (options) { + this.initOptions(options); + this.initPastePicker(); + }); + PastePicker.prototype = { + initPastePicker: function () { + this.initUIBase(); + this.Stateful_init(); + }, + getHtmlTpl: function () { + return ( + '
    ' + + '
    ' + + '
    ' + + this.editor.getLang("pasteOpt") + + "
    " + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + "
    " + + "
    " + + "" + ); + }, + getStateDom: function () { + return this.target; + }, + format: function (param) { + this.editor.ui._isTransfer = true; + this.editor.fireEvent("pasteTransfer", param); + }, + _onClick: function (cur) { + var node = domUtils.getNextDomNode(cur), + screenHt = uiUtils.getViewportRect().height, + subPop = uiUtils.getClientRect(node); - if (subPop.top + subPop.height > screenHt) - node.style.top = -subPop.height - cur.offsetHeight + "px"; - else node.style.top = ""; + if (subPop.top + subPop.height > screenHt) + node.style.top = -subPop.height - cur.offsetHeight + "px"; + else node.style.top = ""; - if (/hidden/gi.test(domUtils.getComputedStyle(node, "visibility"))) { - node.style.visibility = "visible"; - domUtils.addClass(cur, "edui-state-opened"); - } else { - node.style.visibility = "hidden"; - domUtils.removeClasses(cur, "edui-state-opened"); - } - }, - _UIBase_render: UIBase.prototype.render - }; - utils.inherits(PastePicker, UIBase); - utils.extend(PastePicker.prototype, Stateful, true); -})(); + if (/hidden/gi.test(domUtils.getComputedStyle(node, "visibility"))) { + node.style.visibility = "visible"; + domUtils.addClass(cur, "edui-state-opened"); + } else { + node.style.visibility = "hidden"; + domUtils.removeClasses(cur, "edui-state-opened"); + } + }, + _UIBase_render: UIBase.prototype.render + }; + utils.inherits(PastePicker, UIBase); + utils.extend(PastePicker.prototype, Stateful, true); + })(); // ui/toolbar.js -(function() { - var utils = baidu.editor.utils, - uiUtils = baidu.editor.ui.uiUtils, - UIBase = baidu.editor.ui.UIBase, - Toolbar = (baidu.editor.ui.Toolbar = function(options) { - this.initOptions(options); - this.initToolbar(); - }); - Toolbar.prototype = { - items: null, - initToolbar: function() { - this.items = this.items || []; - this.initUIBase(); - }, - add: function(item, index) { - if (index === undefined) { - this.items.push(item); - } else { - this.items.splice(index, 0, item); - } - }, - getHtmlTpl: function() { - var buff = []; - for (var i = 0; i < this.items.length; i++) { - buff[i] = this.items[i].renderHtml(); - } - return ( - '
    ' + - buff.join("") + - "
    " - ); - }, - postRender: function() { - var box = this.getDom(); - for (var i = 0; i < this.items.length; i++) { - this.items[i].postRender(); - } - uiUtils.makeUnselectable(box); - }, - _onMouseDown: function(e) { - var target = e.target || e.srcElement, - tagName = target && target.tagName && target.tagName.toLowerCase(); - if (tagName == "input" || tagName == "object" || tagName == "object") { - return false; - } - } - }; - utils.inherits(Toolbar, UIBase); -})(); + (function () { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + Toolbar = (baidu.editor.ui.Toolbar = function (options) { + this.initOptions(options); + this.initToolbar(); + }); + Toolbar.prototype = { + items: null, + initToolbar: function () { + this.items = this.items || []; + this.initUIBase(); + }, + add: function (item, index) { + if (index === undefined) { + this.items.push(item); + } else { + this.items.splice(index, 0, item); + } + }, + getHtmlTpl: function () { + var buff = []; + for (var i = 0; i < this.items.length; i++) { + buff[i] = this.items[i].renderHtml(); + } + return ( + '
    ' + + buff.join("") + + "
    " + ); + }, + postRender: function () { + var box = this.getDom(); + for (var i = 0; i < this.items.length; i++) { + this.items[i].postRender(); + } + uiUtils.makeUnselectable(box); + }, + _onMouseDown: function (e) { + var target = e.target || e.srcElement, + tagName = target && target.tagName && target.tagName.toLowerCase(); + if (tagName == "input" || tagName == "object" || tagName == "object") { + return false; + } + } + }; + utils.inherits(Toolbar, UIBase); + })(); // ui/quick-operate.js @@ -29470,295 +32903,295 @@ UE.ui = baidu.editor.ui = {}; ///import uicore ///import ui\popup.js ///import ui\stateful.js -(function () { - var utils = baidu.editor.utils, - domUtils = baidu.editor.dom.domUtils, - uiUtils = baidu.editor.ui.uiUtils, - UIBase = baidu.editor.ui.UIBase, - Popup = baidu.editor.ui.Popup, - Stateful = baidu.editor.ui.Stateful, - CellAlignPicker = baidu.editor.ui.CellAlignPicker, - QuickOperate = (baidu.editor.ui.QuickOperate = function (options) { - this.initOptions(options); - // this.initMenu(); - }); + (function () { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + Popup = baidu.editor.ui.Popup, + Stateful = baidu.editor.ui.Stateful, + CellAlignPicker = baidu.editor.ui.CellAlignPicker, + QuickOperate = (baidu.editor.ui.QuickOperate = function (options) { + this.initOptions(options); + // this.initMenu(); + }); - // var menuSeparator = { - // renderHtml: function() { - // return '
    '; - // }, - // postRender: function() {}, - // queryAutoHide: function() { - // return true; - // } - // }; - QuickOperate.prototype = { - // items: null, - uiName: "quick-operate", - // initMenu: function() { - // this.items = this.items || []; - // this.initPopup(); - // this.initItems(); - // }, - // initItems: function() { - // for (var i = 0; i < this.items.length; i++) { - // var item = this.items[i]; - // if (item == "-") { - // this.items[i] = this.getSeparator(); - // } else if (!(item instanceof MenuItem)) { - // item.editor = this.editor; - // item.theme = this.editor.options.theme; - // this.items[i] = this.createItem(item); - // } - // } - // }, - // getSeparator: function() { - // return menuSeparator; - // }, - // createItem: function(item) { - // //新增一个参数menu, 该参数存储了menuItem所对应的menu引用 - // item.menu = this; - // return new MenuItem(item); - // }, - _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, - getContentHtmlTpl: function () { - // if (this.items.length == 0) { - // return this._Popup_getContentHtmlTpl(); - // } - // var buff = []; - // for (var i = 0; i < this.items.length; i++) { - // var item = this.items[i]; - // buff[i] = item.renderHtml(); - // } - // return '
    ' + buff.join("") + "
    "; - return [ - '
    ', - '
    ', - '
    ', - '
    ', - '
    ', - '
    ', - '
    删除
    ', - '
    左对齐
    ', - '
    右对齐
    ', - '
    ', - '
    ', - ].join('') - }, - // _Popup_postRender: Popup.prototype.postRender, - // postRender: function() { - // var me = this; - // for (var i = 0; i < this.items.length; i++) { - // var item = this.items[i]; - // item.ownerMenu = this; - // item.postRender(); - // } - // domUtils.on(this.getDom(), "mouseover", function(evt) { - // evt = evt || event; - // var rel = evt.relatedTarget || evt.fromElement; - // var el = me.getDom(); - // if (!uiUtils.contains(el, rel) && el !== rel) { - // me.fireEvent("over"); - // } - // }); - // this._Popup_postRender(); - // }, - // queryAutoHide: function(el) { - // if (el) { - // if (uiUtils.contains(this.getDom(), el)) { - // return false; - // } - // for (var i = 0; i < this.items.length; i++) { - // var item = this.items[i]; - // if (item.queryAutoHide(el) === false) { - // return false; - // } - // } - // } - // }, - // clearItems: function() { - // for (var i = 0; i < this.items.length; i++) { - // var item = this.items[i]; - // clearTimeout(item._showingTimer); - // clearTimeout(item._closingTimer); - // if (item.subMenu) { - // item.subMenu.destroy(); - // } - // } - // this.items = []; - // }, - destroy: function () { - if (this.getDom()) { - domUtils.remove(this.getDom()); - } - // this.clearItems(); - }, - dispose: function () { - this.destroy(); - } - }; - utils.inherits(QuickOperate, Popup); - // - // /** - // * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用 - // * @type {Function} - // */ - // var MenuItem = (baidu.editor.ui.MenuItem = function(options) { - // this.initOptions(options); - // this.initUIBase(); - // this.Stateful_init(); - // if (this.subMenu && !(this.subMenu instanceof QuickOperate)) { - // if (options.className && options.className.indexOf("aligntd") != -1) { - // var me = this; - // - // //获取单元格对齐初始状态 - // this.subMenu.selected = this.editor.queryCommandValue("cellalignment"); - // - // this.subMenu = new Popup({ - // content: new CellAlignPicker(this.subMenu), - // parentMenu: me, - // editor: me.editor, - // destroy: function() { - // if (this.getDom()) { - // domUtils.remove(this.getDom()); - // } - // } - // }); - // this.subMenu.addListener("postRenderAfter", function() { - // domUtils.on(this.getDom(), "mouseover", function() { - // me.addState("opened"); - // }); - // }); - // } else { - // this.subMenu = new QuickOperate(this.subMenu); - // } - // } - // }); - // MenuItem.prototype = { - // label: "", - // subMenu: null, - // ownerMenu: null, - // uiName: "menuitem", - // alwalysHoverable: true, - // getHtmlTpl: function() { - // return ( - // '
    ' + - // '
    ' + - // this.renderLabelHtml() + - // "
    " + - // "
    " - // ); - // }, - // postRender: function() { - // var me = this; - // this.addListener("over", function() { - // me.ownerMenu.fireEvent("submenuover", me); - // if (me.subMenu) { - // me.delayShowSubMenu(); - // } - // }); - // if (this.subMenu) { - // this.getDom().className += " edui-hassubmenu"; - // this.subMenu.render(); - // this.addListener("out", function() { - // me.delayHideSubMenu(); - // }); - // this.subMenu.addListener("over", function() { - // clearTimeout(me._closingTimer); - // me._closingTimer = null; - // me.addState("opened"); - // }); - // this.ownerMenu.addListener("hide", function() { - // me.hideSubMenu(); - // }); - // this.ownerMenu.addListener("submenuover", function(t, subMenu) { - // if (subMenu !== me) { - // me.delayHideSubMenu(); - // } - // }); - // this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; - // this.subMenu.queryAutoHide = function(el) { - // if (el && uiUtils.contains(me.getDom(), el)) { - // return false; - // } - // return this._bakQueryAutoHide(el); - // }; - // } - // this.getDom().style.tabIndex = "-1"; - // uiUtils.makeUnselectable(this.getDom()); - // this.Stateful_postRender(); - // }, - // delayShowSubMenu: function() { - // var me = this; - // if (!me.isDisabled()) { - // me.addState("opened"); - // clearTimeout(me._showingTimer); - // clearTimeout(me._closingTimer); - // me._closingTimer = null; - // me._showingTimer = setTimeout(function() { - // me.showSubMenu(); - // }, 250); - // } - // }, - // delayHideSubMenu: function() { - // var me = this; - // if (!me.isDisabled()) { - // me.removeState("opened"); - // clearTimeout(me._showingTimer); - // if (!me._closingTimer) { - // me._closingTimer = setTimeout(function() { - // if (!me.hasState("opened")) { - // me.hideSubMenu(); - // } - // me._closingTimer = null; - // }, 400); - // } - // } - // }, - // renderLabelHtml: function() { - // return ( - // '
    ' + - // '
    ' + - // '
    ' + - // (this.label || "") + - // "
    " - // ); - // }, - // getStateDom: function() { - // return this.getDom(); - // }, - // queryAutoHide: function(el) { - // if (this.subMenu && this.hasState("opened")) { - // return this.subMenu.queryAutoHide(el); - // } - // }, - // _onClick: function(event, this_) { - // if (this.hasState("disabled")) return; - // if (this.fireEvent("click", event, this_) !== false) { - // if (this.subMenu) { - // this.showSubMenu(); - // } else { - // Popup.postHide(event); - // } - // } - // }, - // showSubMenu: function() { - // var rect = uiUtils.getClientRect(this.getDom()); - // rect.right -= 5; - // rect.left += 2; - // rect.width -= 7; - // rect.top -= 4; - // rect.bottom += 4; - // rect.height += 8; - // this.subMenu.showAnchorRect(rect, true, true); - // }, - // hideSubMenu: function() { - // this.subMenu.hide(); - // } - // }; - // utils.inherits(MenuItem, UIBase); - // utils.extend(MenuItem.prototype, Stateful, true); -})(); + // var menuSeparator = { + // renderHtml: function() { + // return '
    '; + // }, + // postRender: function() {}, + // queryAutoHide: function() { + // return true; + // } + // }; + QuickOperate.prototype = { + // items: null, + uiName: "quick-operate", + // initMenu: function() { + // this.items = this.items || []; + // this.initPopup(); + // this.initItems(); + // }, + // initItems: function() { + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // if (item == "-") { + // this.items[i] = this.getSeparator(); + // } else if (!(item instanceof MenuItem)) { + // item.editor = this.editor; + // item.theme = this.editor.options.theme; + // this.items[i] = this.createItem(item); + // } + // } + // }, + // getSeparator: function() { + // return menuSeparator; + // }, + // createItem: function(item) { + // //新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + // item.menu = this; + // return new MenuItem(item); + // }, + _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, + getContentHtmlTpl: function () { + // if (this.items.length == 0) { + // return this._Popup_getContentHtmlTpl(); + // } + // var buff = []; + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // buff[i] = item.renderHtml(); + // } + // return '
    ' + buff.join("") + "
    "; + return [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    删除
    ', + '
    左对齐
    ', + '
    右对齐
    ', + '
    ', + '
    ', + ].join('') + }, + // _Popup_postRender: Popup.prototype.postRender, + // postRender: function() { + // var me = this; + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // item.ownerMenu = this; + // item.postRender(); + // } + // domUtils.on(this.getDom(), "mouseover", function(evt) { + // evt = evt || event; + // var rel = evt.relatedTarget || evt.fromElement; + // var el = me.getDom(); + // if (!uiUtils.contains(el, rel) && el !== rel) { + // me.fireEvent("over"); + // } + // }); + // this._Popup_postRender(); + // }, + // queryAutoHide: function(el) { + // if (el) { + // if (uiUtils.contains(this.getDom(), el)) { + // return false; + // } + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // if (item.queryAutoHide(el) === false) { + // return false; + // } + // } + // } + // }, + // clearItems: function() { + // for (var i = 0; i < this.items.length; i++) { + // var item = this.items[i]; + // clearTimeout(item._showingTimer); + // clearTimeout(item._closingTimer); + // if (item.subMenu) { + // item.subMenu.destroy(); + // } + // } + // this.items = []; + // }, + destroy: function () { + if (this.getDom()) { + domUtils.remove(this.getDom()); + } + // this.clearItems(); + }, + dispose: function () { + this.destroy(); + } + }; + utils.inherits(QuickOperate, Popup); + // + // /** + // * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + // * @type {Function} + // */ + // var MenuItem = (baidu.editor.ui.MenuItem = function(options) { + // this.initOptions(options); + // this.initUIBase(); + // this.Stateful_init(); + // if (this.subMenu && !(this.subMenu instanceof QuickOperate)) { + // if (options.className && options.className.indexOf("aligntd") != -1) { + // var me = this; + // + // //获取单元格对齐初始状态 + // this.subMenu.selected = this.editor.queryCommandValue("cellalignment"); + // + // this.subMenu = new Popup({ + // content: new CellAlignPicker(this.subMenu), + // parentMenu: me, + // editor: me.editor, + // destroy: function() { + // if (this.getDom()) { + // domUtils.remove(this.getDom()); + // } + // } + // }); + // this.subMenu.addListener("postRenderAfter", function() { + // domUtils.on(this.getDom(), "mouseover", function() { + // me.addState("opened"); + // }); + // }); + // } else { + // this.subMenu = new QuickOperate(this.subMenu); + // } + // } + // }); + // MenuItem.prototype = { + // label: "", + // subMenu: null, + // ownerMenu: null, + // uiName: "menuitem", + // alwalysHoverable: true, + // getHtmlTpl: function() { + // return ( + // '
    ' + + // '
    ' + + // this.renderLabelHtml() + + // "
    " + + // "
    " + // ); + // }, + // postRender: function() { + // var me = this; + // this.addListener("over", function() { + // me.ownerMenu.fireEvent("submenuover", me); + // if (me.subMenu) { + // me.delayShowSubMenu(); + // } + // }); + // if (this.subMenu) { + // this.getDom().className += " edui-hassubmenu"; + // this.subMenu.render(); + // this.addListener("out", function() { + // me.delayHideSubMenu(); + // }); + // this.subMenu.addListener("over", function() { + // clearTimeout(me._closingTimer); + // me._closingTimer = null; + // me.addState("opened"); + // }); + // this.ownerMenu.addListener("hide", function() { + // me.hideSubMenu(); + // }); + // this.ownerMenu.addListener("submenuover", function(t, subMenu) { + // if (subMenu !== me) { + // me.delayHideSubMenu(); + // } + // }); + // this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; + // this.subMenu.queryAutoHide = function(el) { + // if (el && uiUtils.contains(me.getDom(), el)) { + // return false; + // } + // return this._bakQueryAutoHide(el); + // }; + // } + // this.getDom().style.tabIndex = "-1"; + // uiUtils.makeUnselectable(this.getDom()); + // this.Stateful_postRender(); + // }, + // delayShowSubMenu: function() { + // var me = this; + // if (!me.isDisabled()) { + // me.addState("opened"); + // clearTimeout(me._showingTimer); + // clearTimeout(me._closingTimer); + // me._closingTimer = null; + // me._showingTimer = setTimeout(function() { + // me.showSubMenu(); + // }, 250); + // } + // }, + // delayHideSubMenu: function() { + // var me = this; + // if (!me.isDisabled()) { + // me.removeState("opened"); + // clearTimeout(me._showingTimer); + // if (!me._closingTimer) { + // me._closingTimer = setTimeout(function() { + // if (!me.hasState("opened")) { + // me.hideSubMenu(); + // } + // me._closingTimer = null; + // }, 400); + // } + // } + // }, + // renderLabelHtml: function() { + // return ( + // '
    ' + + // '
    ' + + // '
    ' + + // (this.label || "") + + // "
    " + // ); + // }, + // getStateDom: function() { + // return this.getDom(); + // }, + // queryAutoHide: function(el) { + // if (this.subMenu && this.hasState("opened")) { + // return this.subMenu.queryAutoHide(el); + // } + // }, + // _onClick: function(event, this_) { + // if (this.hasState("disabled")) return; + // if (this.fireEvent("click", event, this_) !== false) { + // if (this.subMenu) { + // this.showSubMenu(); + // } else { + // Popup.postHide(event); + // } + // } + // }, + // showSubMenu: function() { + // var rect = uiUtils.getClientRect(this.getDom()); + // rect.right -= 5; + // rect.left += 2; + // rect.width -= 7; + // rect.top -= 4; + // rect.bottom += 4; + // rect.height += 8; + // this.subMenu.showAnchorRect(rect, true, true); + // }, + // hideSubMenu: function() { + // this.subMenu.hide(); + // } + // }; + // utils.inherits(MenuItem, UIBase); + // utils.extend(MenuItem.prototype, Stateful, true); + })(); // ui/menu.js @@ -29766,282 +33199,283 @@ UE.ui = baidu.editor.ui = {}; ///import uicore ///import ui\popup.js ///import ui\stateful.js -(function() { - var utils = baidu.editor.utils, - domUtils = baidu.editor.dom.domUtils, - uiUtils = baidu.editor.ui.uiUtils, - UIBase = baidu.editor.ui.UIBase, - Popup = baidu.editor.ui.Popup, - Stateful = baidu.editor.ui.Stateful, - CellAlignPicker = baidu.editor.ui.CellAlignPicker, - Menu = (baidu.editor.ui.Menu = function(options) { - this.initOptions(options); - this.initMenu(); - }); + (function () { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + Popup = baidu.editor.ui.Popup, + Stateful = baidu.editor.ui.Stateful, + CellAlignPicker = baidu.editor.ui.CellAlignPicker, + Menu = (baidu.editor.ui.Menu = function (options) { + this.initOptions(options); + this.initMenu(); + }); - var menuSeparator = { - renderHtml: function() { - return '
    '; - }, - postRender: function() {}, - queryAutoHide: function() { - return true; - } - }; - Menu.prototype = { - items: null, - uiName: "menu", - initMenu: function() { - this.items = this.items || []; - this.initPopup(); - this.initItems(); - }, - initItems: function() { - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - if (item == "-") { - this.items[i] = this.getSeparator(); - } else if (!(item instanceof MenuItem)) { - item.editor = this.editor; - item.theme = this.editor.options.theme; - this.items[i] = this.createItem(item); - } - } - }, - getSeparator: function() { - return menuSeparator; - }, - createItem: function(item) { - //新增一个参数menu, 该参数存储了menuItem所对应的menu引用 - item.menu = this; - return new MenuItem(item); - }, - _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, - getContentHtmlTpl: function() { - if (this.items.length == 0) { - return this._Popup_getContentHtmlTpl(); - } - var buff = []; - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - buff[i] = item.renderHtml(); - } - return '
    ' + buff.join("") + "
    "; - }, - _Popup_postRender: Popup.prototype.postRender, - postRender: function() { - var me = this; - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - item.ownerMenu = this; - item.postRender(); - } - domUtils.on(this.getDom(), "mouseover", function(evt) { - evt = evt || event; - var rel = evt.relatedTarget || evt.fromElement; - var el = me.getDom(); - if (!uiUtils.contains(el, rel) && el !== rel) { - me.fireEvent("over"); - } - }); - this._Popup_postRender(); - }, - queryAutoHide: function(el) { - if (el) { - if (uiUtils.contains(this.getDom(), el)) { - return false; - } - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - if (item.queryAutoHide(el) === false) { - return false; - } - } - } - }, - clearItems: function() { - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - clearTimeout(item._showingTimer); - clearTimeout(item._closingTimer); - if (item.subMenu) { - item.subMenu.destroy(); - } - } - this.items = []; - }, - destroy: function() { - if (this.getDom()) { - domUtils.remove(this.getDom()); - } - this.clearItems(); - }, - dispose: function() { - this.destroy(); - } - }; - utils.inherits(Menu, Popup); - - /** - * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用 - * @type {Function} - */ - var MenuItem = (baidu.editor.ui.MenuItem = function(options) { - this.initOptions(options); - this.initUIBase(); - this.Stateful_init(); - if (this.subMenu && !(this.subMenu instanceof Menu)) { - if (options.className && options.className.indexOf("aligntd") != -1) { - var me = this; - - //获取单元格对齐初始状态 - this.subMenu.selected = this.editor.queryCommandValue("cellalignment"); - - this.subMenu = new Popup({ - content: new CellAlignPicker(this.subMenu), - parentMenu: me, - editor: me.editor, - destroy: function() { - if (this.getDom()) { - domUtils.remove(this.getDom()); + var menuSeparator = { + renderHtml: function () { + return '
    '; + }, + postRender: function () { + }, + queryAutoHide: function () { + return true; } - } - }); - this.subMenu.addListener("postRenderAfter", function() { - domUtils.on(this.getDom(), "mouseover", function() { - me.addState("opened"); - }); - }); - } else { - this.subMenu = new Menu(this.subMenu); - } - } - }); - MenuItem.prototype = { - label: "", - subMenu: null, - ownerMenu: null, - uiName: "menuitem", - alwalysHoverable: true, - getHtmlTpl: function() { - return ( - '
    ' + - '
    ' + - this.renderLabelHtml() + - "
    " + - "
    " - ); - }, - postRender: function() { - var me = this; - this.addListener("over", function() { - me.ownerMenu.fireEvent("submenuover", me); - if (me.subMenu) { - me.delayShowSubMenu(); - } - }); - if (this.subMenu) { - this.getDom().className += " edui-hassubmenu"; - this.subMenu.render(); - this.addListener("out", function() { - me.delayHideSubMenu(); - }); - this.subMenu.addListener("over", function() { - clearTimeout(me._closingTimer); - me._closingTimer = null; - me.addState("opened"); - }); - this.ownerMenu.addListener("hide", function() { - me.hideSubMenu(); - }); - this.ownerMenu.addListener("submenuover", function(t, subMenu) { - if (subMenu !== me) { - me.delayHideSubMenu(); - } - }); - this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; - this.subMenu.queryAutoHide = function(el) { - if (el && uiUtils.contains(me.getDom(), el)) { - return false; - } - return this._bakQueryAutoHide(el); }; - } - this.getDom().style.tabIndex = "-1"; - uiUtils.makeUnselectable(this.getDom()); - this.Stateful_postRender(); - }, - delayShowSubMenu: function() { - var me = this; - if (!me.isDisabled()) { - me.addState("opened"); - clearTimeout(me._showingTimer); - clearTimeout(me._closingTimer); - me._closingTimer = null; - me._showingTimer = setTimeout(function() { - me.showSubMenu(); - }, 250); - } - }, - delayHideSubMenu: function() { - var me = this; - if (!me.isDisabled()) { - me.removeState("opened"); - clearTimeout(me._showingTimer); - if (!me._closingTimer) { - me._closingTimer = setTimeout(function() { - if (!me.hasState("opened")) { - me.hideSubMenu(); + Menu.prototype = { + items: null, + uiName: "menu", + initMenu: function () { + this.items = this.items || []; + this.initPopup(); + this.initItems(); + }, + initItems: function () { + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item == "-") { + this.items[i] = this.getSeparator(); + } else if (!(item instanceof MenuItem)) { + item.editor = this.editor; + item.theme = this.editor.options.theme; + this.items[i] = this.createItem(item); + } + } + }, + getSeparator: function () { + return menuSeparator; + }, + createItem: function (item) { + //新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + item.menu = this; + return new MenuItem(item); + }, + _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl, + getContentHtmlTpl: function () { + if (this.items.length == 0) { + return this._Popup_getContentHtmlTpl(); + } + var buff = []; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + buff[i] = item.renderHtml(); + } + return '
    ' + buff.join("") + "
    "; + }, + _Popup_postRender: Popup.prototype.postRender, + postRender: function () { + var me = this; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + item.ownerMenu = this; + item.postRender(); + } + domUtils.on(this.getDom(), "mouseover", function (evt) { + evt = evt || event; + var rel = evt.relatedTarget || evt.fromElement; + var el = me.getDom(); + if (!uiUtils.contains(el, rel) && el !== rel) { + me.fireEvent("over"); + } + }); + this._Popup_postRender(); + }, + queryAutoHide: function (el) { + if (el) { + if (uiUtils.contains(this.getDom(), el)) { + return false; + } + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item.queryAutoHide(el) === false) { + return false; + } + } + } + }, + clearItems: function () { + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + clearTimeout(item._showingTimer); + clearTimeout(item._closingTimer); + if (item.subMenu) { + item.subMenu.destroy(); + } + } + this.items = []; + }, + destroy: function () { + if (this.getDom()) { + domUtils.remove(this.getDom()); + } + this.clearItems(); + }, + dispose: function () { + this.destroy(); } - me._closingTimer = null; - }, 400); - } - } - }, - renderLabelHtml: function() { - return ( - '
    ' + - '
    ' + - '
    ' + - (this.label || "") + - "
    " - ); - }, - getStateDom: function() { - return this.getDom(); - }, - queryAutoHide: function(el) { - if (this.subMenu && this.hasState("opened")) { - return this.subMenu.queryAutoHide(el); - } - }, - _onClick: function(event, this_) { - if (this.hasState("disabled")) return; - if (this.fireEvent("click", event, this_) !== false) { - if (this.subMenu) { - this.showSubMenu(); - } else { - Popup.postHide(event); - } - } - }, - showSubMenu: function() { - var rect = uiUtils.getClientRect(this.getDom()); - rect.right -= 5; - rect.left += 2; - rect.width -= 7; - rect.top -= 4; - rect.bottom += 4; - rect.height += 8; - this.subMenu.showAnchorRect(rect, true, true); - }, - hideSubMenu: function() { - this.subMenu.hide(); - } - }; - utils.inherits(MenuItem, UIBase); - utils.extend(MenuItem.prototype, Stateful, true); -})(); + }; + utils.inherits(Menu, Popup); + + /** + * @update 2013/04/03 hancong03 新增一个参数menu, 该参数存储了menuItem所对应的menu引用 + * @type {Function} + */ + var MenuItem = (baidu.editor.ui.MenuItem = function (options) { + this.initOptions(options); + this.initUIBase(); + this.Stateful_init(); + if (this.subMenu && !(this.subMenu instanceof Menu)) { + if (options.className && options.className.indexOf("aligntd") != -1) { + var me = this; + + //获取单元格对齐初始状态 + this.subMenu.selected = this.editor.queryCommandValue("cellalignment"); + + this.subMenu = new Popup({ + content: new CellAlignPicker(this.subMenu), + parentMenu: me, + editor: me.editor, + destroy: function () { + if (this.getDom()) { + domUtils.remove(this.getDom()); + } + } + }); + this.subMenu.addListener("postRenderAfter", function () { + domUtils.on(this.getDom(), "mouseover", function () { + me.addState("opened"); + }); + }); + } else { + this.subMenu = new Menu(this.subMenu); + } + } + }); + MenuItem.prototype = { + label: "", + subMenu: null, + ownerMenu: null, + uiName: "menuitem", + alwalysHoverable: true, + getHtmlTpl: function () { + return ( + '
    ' + + '
    ' + + this.renderLabelHtml() + + "
    " + + "
    " + ); + }, + postRender: function () { + var me = this; + this.addListener("over", function () { + me.ownerMenu.fireEvent("submenuover", me); + if (me.subMenu) { + me.delayShowSubMenu(); + } + }); + if (this.subMenu) { + this.getDom().className += " edui-hassubmenu"; + this.subMenu.render(); + this.addListener("out", function () { + me.delayHideSubMenu(); + }); + this.subMenu.addListener("over", function () { + clearTimeout(me._closingTimer); + me._closingTimer = null; + me.addState("opened"); + }); + this.ownerMenu.addListener("hide", function () { + me.hideSubMenu(); + }); + this.ownerMenu.addListener("submenuover", function (t, subMenu) { + if (subMenu !== me) { + me.delayHideSubMenu(); + } + }); + this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; + this.subMenu.queryAutoHide = function (el) { + if (el && uiUtils.contains(me.getDom(), el)) { + return false; + } + return this._bakQueryAutoHide(el); + }; + } + this.getDom().style.tabIndex = "-1"; + uiUtils.makeUnselectable(this.getDom()); + this.Stateful_postRender(); + }, + delayShowSubMenu: function () { + var me = this; + if (!me.isDisabled()) { + me.addState("opened"); + clearTimeout(me._showingTimer); + clearTimeout(me._closingTimer); + me._closingTimer = null; + me._showingTimer = setTimeout(function () { + me.showSubMenu(); + }, 250); + } + }, + delayHideSubMenu: function () { + var me = this; + if (!me.isDisabled()) { + me.removeState("opened"); + clearTimeout(me._showingTimer); + if (!me._closingTimer) { + me._closingTimer = setTimeout(function () { + if (!me.hasState("opened")) { + me.hideSubMenu(); + } + me._closingTimer = null; + }, 400); + } + } + }, + renderLabelHtml: function () { + return ( + '
    ' + + '
    ' + + '
    ' + + (this.label || "") + + "
    " + ); + }, + getStateDom: function () { + return this.getDom(); + }, + queryAutoHide: function (el) { + if (this.subMenu && this.hasState("opened")) { + return this.subMenu.queryAutoHide(el); + } + }, + _onClick: function (event, this_) { + if (this.hasState("disabled")) return; + if (this.fireEvent("click", event, this_) !== false) { + if (this.subMenu) { + this.showSubMenu(); + } else { + Popup.postHide(event); + } + } + }, + showSubMenu: function () { + var rect = uiUtils.getClientRect(this.getDom()); + rect.right -= 5; + rect.left += 2; + rect.width -= 7; + rect.top -= 4; + rect.bottom += 4; + rect.height += 8; + this.subMenu.showAnchorRect(rect, true, true); + }, + hideSubMenu: function () { + this.subMenu.hide(); + } + }; + utils.inherits(MenuItem, UIBase); + utils.extend(MenuItem.prototype, Stateful, true); + })(); // ui/combox.js @@ -30049,101 +33483,101 @@ UE.ui = baidu.editor.ui = {}; ///import uicore ///import ui/menu.js ///import ui/splitbutton.js -(function() { - // todo: menu和item提成通用list - var utils = baidu.editor.utils, - uiUtils = baidu.editor.ui.uiUtils, - Menu = baidu.editor.ui.Menu, - SplitButton = baidu.editor.ui.SplitButton, - Combox = (baidu.editor.ui.Combox = function(options) { - this.initOptions(options); - this.initCombox(); - }); - Combox.prototype = { - uiName: "combox", - onbuttonclick: function() { - this.showPopup(); - }, - initCombox: function() { - var me = this; - this.items = this.items || []; - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - item.uiName = "listitem"; - item.index = i; - item.onclick = function() { - me.selectByIndex(this.index); - }; - } - this.popup = new Menu({ - items: this.items, - uiName: "list", - editor: this.editor, - captureWheel: true, - combox: this - }); + (function () { + // todo: menu和item提成通用list + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + Menu = baidu.editor.ui.Menu, + SplitButton = baidu.editor.ui.SplitButton, + Combox = (baidu.editor.ui.Combox = function (options) { + this.initOptions(options); + this.initCombox(); + }); + Combox.prototype = { + uiName: "combox", + onbuttonclick: function () { + this.showPopup(); + }, + initCombox: function () { + var me = this; + this.items = this.items || []; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + item.uiName = "listitem"; + item.index = i; + item.onclick = function () { + me.selectByIndex(this.index); + }; + } + this.popup = new Menu({ + items: this.items, + uiName: "list", + editor: this.editor, + captureWheel: true, + combox: this + }); - this.initSplitButton(); - }, - _SplitButton_postRender: SplitButton.prototype.postRender, - postRender: function() { - this._SplitButton_postRender(); - this.setLabel(this.label || ""); - this.setValue(this.initValue || ""); - }, - showPopup: function() { - var rect = uiUtils.getClientRect(this.getDom()); - rect.top += 1; - rect.bottom -= 1; - rect.height -= 2; - this.popup.showAnchorRect(rect); - }, - getValue: function() { - return this.value; - }, - setValue: function(value) { - var index = this.indexByValue(value); - if (index != -1) { - this.selectedIndex = index; - this.setLabel(this.items[index].label); - this.value = this.items[index].value; - } else { - this.selectedIndex = -1; - this.setLabel(this.getLabelForUnknowValue(value)); - this.value = value; - } - }, - setLabel: function(label) { - this.getDom("button_body").innerHTML = label; - this.label = label; - }, - getLabelForUnknowValue: function(value) { - return value; - }, - indexByValue: function(value) { - for (var i = 0; i < this.items.length; i++) { - if (value == this.items[i].value) { - return i; - } - } - return -1; - }, - getItem: function(index) { - return this.items[index]; - }, - selectByIndex: function(index) { - if ( - index < this.items.length && - this.fireEvent("select", index) !== false - ) { - this.selectedIndex = index; - this.value = this.items[index].value; - this.setLabel(this.items[index].label); - } - } - }; - utils.inherits(Combox, SplitButton); -})(); + this.initSplitButton(); + }, + _SplitButton_postRender: SplitButton.prototype.postRender, + postRender: function () { + this._SplitButton_postRender(); + this.setLabel(this.label || ""); + this.setValue(this.initValue || ""); + }, + showPopup: function () { + var rect = uiUtils.getClientRect(this.getDom()); + rect.top += 1; + rect.bottom -= 1; + rect.height -= 2; + this.popup.showAnchorRect(rect); + }, + getValue: function () { + return this.value; + }, + setValue: function (value) { + var index = this.indexByValue(value); + if (index != -1) { + this.selectedIndex = index; + this.setLabel(this.items[index].label); + this.value = this.items[index].value; + } else { + this.selectedIndex = -1; + this.setLabel(this.getLabelForUnknowValue(value)); + this.value = value; + } + }, + setLabel: function (label) { + this.getDom("button_body").innerHTML = label; + this.label = label; + }, + getLabelForUnknowValue: function (value) { + return value; + }, + indexByValue: function (value) { + for (var i = 0; i < this.items.length; i++) { + if (value == this.items[i].value) { + return i; + } + } + return -1; + }, + getItem: function (index) { + return this.items[index]; + }, + selectByIndex: function (index) { + if ( + index < this.items.length && + this.fireEvent("select", index) !== false + ) { + this.selectedIndex = index; + this.value = this.items[index].value; + this.setLabel(this.items[index].label); + } + } + }; + utils.inherits(Combox, SplitButton); + })(); // ui/dialog.js @@ -30151,124 +33585,223 @@ UE.ui = baidu.editor.ui = {}; ///import uicore ///import ui/mask.js ///import ui/button.js -(function () { - var utils = baidu.editor.utils, - domUtils = baidu.editor.dom.domUtils, - uiUtils = baidu.editor.ui.uiUtils, - Mask = baidu.editor.ui.Mask, - UIBase = baidu.editor.ui.UIBase, - Button = baidu.editor.ui.Button, - Dialog = (baidu.editor.ui.Dialog = function (options) { - if (options.name) { - var name = options.name; - var cssRules = options.cssRules; - if (!options.className) { - options.className = "edui-for-" + name; + (function () { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + uiUtils = baidu.editor.ui.uiUtils, + Mask = baidu.editor.ui.Mask, + UIBase = baidu.editor.ui.UIBase, + Button = baidu.editor.ui.Button, + Dialog = (baidu.editor.ui.Dialog = function (options) { + if (options.name) { + var name = options.name; + var cssRules = options.cssRules; + if (!options.className) { + options.className = "edui-for-" + name; + } + if (cssRules) { + options.cssRules = + ".edui-for-" + name + " .edui-dialog-content {" + cssRules + "}"; + } } - if (cssRules) { - options.cssRules = - ".edui-for-" + name + " .edui-dialog-content {" + cssRules + "}"; + this.initOptions( + utils.extend( + { + autoReset: true, + draggable: true, + onok: function () { + }, + oncancel: function () { + }, + onclose: function (t, ok) { + return ok ? this.onok() : this.oncancel(); + }, + //是否控制dialog中的scroll事件, 默认为不阻止 + holdScroll: false + }, + options + ) + ); + this.initDialog(); + }); + var modalMask; + var dragMask; + var activeDialog; + Dialog.prototype = { + draggable: false, + uiName: "dialog", + initDialog: function () { + var me = this, + theme = this.editor.options.theme; + if (this.cssRules) { + this.cssRules = ".edui-" + theme + " " + this.cssRules; + utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules); } - } - this.initOptions( - utils.extend( - { - autoReset: true, - draggable: true, - onok: function () { - }, - oncancel: function () { - }, - onclose: function (t, ok) { - return ok ? this.onok() : this.oncancel(); - }, - //是否控制dialog中的scroll事件, 默认为不阻止 - holdScroll: false - }, - options - ) - ); - this.initDialog(); - }); - var modalMask; - var dragMask; - var activeDialog; - Dialog.prototype = { - draggable: false, - uiName: "dialog", - initDialog: function () { - var me = this, - theme = this.editor.options.theme; - if (this.cssRules) { - this.cssRules = ".edui-" + theme + " " + this.cssRules; - utils.cssRule("edui-customize-" + this.name + "-style", this.cssRules); - } - this.initUIBase(); - this.modalMask = - modalMask || - (modalMask = new Mask({ - className: "edui-dialog-modalmask", + this.initUIBase(); + this.modalMask = + modalMask || + (modalMask = new Mask({ + className: "edui-dialog-modalmask", + theme: theme, + onclick: function () { + activeDialog && activeDialog.close(false); + } + })); + this.dragMask = + dragMask || + (dragMask = new Mask({ + className: "edui-dialog-dragmask", + theme: theme + })); + this.closeButton = new Button({ + className: "edui-dialog-closebutton", + title: me.closeDialog, theme: theme, onclick: function () { - activeDialog && activeDialog.close(false); + me.close(false); } - })); - this.dragMask = - dragMask || - (dragMask = new Mask({ - className: "edui-dialog-dragmask", - theme: theme - })); - this.closeButton = new Button({ - className: "edui-dialog-closebutton", - title: me.closeDialog, - theme: theme, - onclick: function () { - me.close(false); - } - }); + }); - this.fullscreen && this.initResizeEvent(); + this.fullscreen && this.initResizeEvent(); - if (this.buttons) { - for (var i = 0; i < this.buttons.length; i++) { - if (!(this.buttons[i] instanceof Button)) { - this.buttons[i] = new Button( - utils.extend( - this.buttons[i], - { - editor: this.editor - }, - true - ) - ); + if (this.buttons) { + for (var i = 0; i < this.buttons.length; i++) { + if (!(this.buttons[i] instanceof Button)) { + this.buttons[i] = new Button( + utils.extend( + this.buttons[i], + { + editor: this.editor + }, + true + ) + ); + } } } - } - }, - initResizeEvent: function () { - var me = this; + }, + initResizeEvent: function () { + var me = this; - domUtils.on(window, "resize", function () { + domUtils.on(window, "resize", function () { - if (me._hidden || me._hidden === undefined) { - return; + if (me._hidden || me._hidden === undefined) { + return; + } + + if (me.__resizeTimer) { + window.clearTimeout(me.__resizeTimer); + } + + me.__resizeTimer = window.setTimeout(function () { + me.__resizeTimer = null; + + + var dialogWrapNode = me.getDom(), + contentNode = me.getDom("content"), + wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode), + contentRect = UE.ui.uiUtils.getClientRect(contentNode), + vpRect = uiUtils.getViewportRect(); + + contentNode.style.width = + vpRect.width - wrapRect.width + contentRect.width + "px"; + contentNode.style.height = + vpRect.height - wrapRect.height + contentRect.height + "px"; + + dialogWrapNode.style.width = vpRect.width + "px"; + dialogWrapNode.style.height = vpRect.height + "px"; + + me.fireEvent("resize"); + }, 100); + }); + }, + fitSize: function () { + // console.log('fitSize.dialog') + var popBodyEl = this.getDom("body"); + var $foot = popBodyEl.querySelector('.edui-dialog-foot'); + var heightWithoutBody = 70; + if (!$foot) { + heightWithoutBody = 30; } - - if (me.__resizeTimer) { - window.clearTimeout(me.__resizeTimer); + var size = this.mesureSize(); + var winSize = uiUtils.getViewportRect(); + var width = size.width; + var height = size.height - heightWithoutBody; + var maxWidth = winSize.width - 2; + var maxHeight = winSize.height - heightWithoutBody - 2; + if (width > maxWidth) { + height = height * maxWidth / width; + width = maxWidth; } + if (height > maxHeight) { + width = width * maxHeight / height; + height = maxHeight; + } + var scale = (width / size.width); + // console.log('size', {sizeWidth: size.width, sizeHeight: size.height, width, height, scale}); + // console.log('popBodyEl',popBodyEl, popBodyEl.querySelector('.edui-dialog-foot')); + // window._xxx = popBodyEl; + var $content = popBodyEl.querySelector('.edui-dialog-content'); + if (!$content.dataset.dialogScaled) { + $content.dataset.dialogScaled = true + $content.style.width = (width) + 'px'; + $content.style.height = (height) + 'px'; + var $iframe = popBodyEl.querySelector('.edui-dialog-content iframe'); + $iframe.style.width = (size.width) + 'px'; + $iframe.style.height = (size.height - heightWithoutBody) + 'px'; + $iframe.style.transformOrigin = '0 0'; + $iframe.style.transform = 'scale(' + scale + ')'; + size.width = width + size.height = height + heightWithoutBody + } + popBodyEl.style.width = size.width + "px"; + popBodyEl.style.height = size.height + "px"; + return size; + }, + safeSetOffset: function (offset) { + var me = this; + var el = me.getDom(); + var vpRect = uiUtils.getViewportRect(); + var rect = uiUtils.getClientRect(el); + var left = offset.left; + if (left + rect.width > vpRect.right) { + left = vpRect.right - rect.width; + } + var top = offset.top; + if (top + rect.height > vpRect.bottom) { + top = vpRect.bottom - rect.height; + } + el.style.left = Math.max(left, 0) + "px"; + el.style.top = Math.max(top, 0) + "px"; + }, + showAtCenter: function () { + var vpRect = uiUtils.getViewportRect(); - me.__resizeTimer = window.setTimeout(function () { - me.__resizeTimer = null; + if (!this.fullscreen) { + this.getDom().style.display = ""; + var popSize = this.fitSize(); + var titleHeight = this.getDom("titlebar").offsetHeight | 0; + var left = vpRect.width / 2 - popSize.width / 2; + var top = + vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight; + var popEl = this.getDom(); + this.safeSetOffset({ + left: Math.max(left | 0, 0), + top: Math.max(top | 0, 0) + }); + if (!domUtils.hasClass(popEl, "edui-state-centered")) { + popEl.className += " edui-state-centered"; + } + } else { + var dialogWrapNode = this.getDom(), + contentNode = this.getDom("content"); + dialogWrapNode.style.display = "block"; - var dialogWrapNode = me.getDom(), - contentNode = me.getDom("content"), - wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode), - contentRect = UE.ui.uiUtils.getClientRect(contentNode), - vpRect = uiUtils.getViewportRect(); + var wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode), + contentRect = UE.ui.uiUtils.getClientRect(contentNode); + dialogWrapNode.style.left = "-100000px"; contentNode.style.width = vpRect.width - wrapRect.width + contentRect.width + "px"; @@ -30277,364 +33810,265 @@ UE.ui = baidu.editor.ui = {}; dialogWrapNode.style.width = vpRect.width + "px"; dialogWrapNode.style.height = vpRect.height + "px"; + dialogWrapNode.style.left = 0; - me.fireEvent("resize"); - }, 100); - }); - }, - fitSize: function () { - // console.log('fitSize.dialog') - var popBodyEl = this.getDom("body"); - var $foot = popBodyEl.querySelector('.edui-dialog-foot'); - var heightWithoutBody = 70; - if (!$foot) { - heightWithoutBody = 30; - } - var size = this.mesureSize(); - var winSize = uiUtils.getViewportRect(); - var width = size.width; - var height = size.height - heightWithoutBody; - var maxWidth = winSize.width - 2; - var maxHeight = winSize.height - heightWithoutBody - 2; - if (width > maxWidth) { - height = height * maxWidth / width; - width = maxWidth; - } - if (height > maxHeight) { - width = width * maxHeight / height; - height = maxHeight; - } - var scale = (width / size.width); - // console.log('size', {sizeWidth: size.width, sizeHeight: size.height, width, height, scale}); - // console.log('popBodyEl',popBodyEl, popBodyEl.querySelector('.edui-dialog-foot')); - // window._xxx = popBodyEl; - var $content = popBodyEl.querySelector('.edui-dialog-content'); - if (!$content.dataset.dialogScaled) { - $content.dataset.dialogScaled = true - $content.style.width = (width) + 'px'; - $content.style.height = (height) + 'px'; - var $iframe = popBodyEl.querySelector('.edui-dialog-content iframe'); - $iframe.style.width = (size.width) + 'px'; - $iframe.style.height = (size.height - heightWithoutBody) + 'px'; - $iframe.style.transformOrigin = '0 0'; - $iframe.style.transform = 'scale(' + scale + ')'; - size.width = width - size.height = height + heightWithoutBody - } - popBodyEl.style.width = size.width + "px"; - popBodyEl.style.height = size.height + "px"; - return size; - }, - safeSetOffset: function (offset) { - var me = this; - var el = me.getDom(); - var vpRect = uiUtils.getViewportRect(); - var rect = uiUtils.getClientRect(el); - var left = offset.left; - if (left + rect.width > vpRect.right) { - left = vpRect.right - rect.width; - } - var top = offset.top; - if (top + rect.height > vpRect.bottom) { - top = vpRect.bottom - rect.height; - } - el.style.left = Math.max(left, 0) + "px"; - el.style.top = Math.max(top, 0) + "px"; - }, - showAtCenter: function () { - var vpRect = uiUtils.getViewportRect(); + //保存环境的overflow值 + this._originalContext = { + html: { + overflowX: document.documentElement.style.overflowX, + overflowY: document.documentElement.style.overflowY + }, + body: { + overflowX: document.body.style.overflowX, + overflowY: document.body.style.overflowY + } + }; - if (!this.fullscreen) { - this.getDom().style.display = ""; - var popSize = this.fitSize(); - var titleHeight = this.getDom("titlebar").offsetHeight | 0; - var left = vpRect.width / 2 - popSize.width / 2; - var top = - vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight; - var popEl = this.getDom(); - this.safeSetOffset({ - left: Math.max(left | 0, 0), - top: Math.max(top | 0, 0) - }); - if (!domUtils.hasClass(popEl, "edui-state-centered")) { - popEl.className += " edui-state-centered"; + document.documentElement.style.overflowX = "hidden"; + document.documentElement.style.overflowY = "hidden"; + document.body.style.overflowX = "hidden"; + document.body.style.overflowY = "hidden"; } - } else { - var dialogWrapNode = this.getDom(), - contentNode = this.getDom("content"); - dialogWrapNode.style.display = "block"; + this._show(); + }, + getContentHtml: function () { + var contentHtml = ""; + if (typeof this.content == "string") { + contentHtml = this.content; + } else if (this.iframeUrl) { + contentHtml = + ''; + } + return contentHtml; + }, + getHtmlTpl: function () { + var footHtml = ""; - var wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode), - contentRect = UE.ui.uiUtils.getClientRect(contentNode); - dialogWrapNode.style.left = "-100000px"; - - contentNode.style.width = - vpRect.width - wrapRect.width + contentRect.width + "px"; - contentNode.style.height = - vpRect.height - wrapRect.height + contentRect.height + "px"; - - dialogWrapNode.style.width = vpRect.width + "px"; - dialogWrapNode.style.height = vpRect.height + "px"; - dialogWrapNode.style.left = 0; - - //保存环境的overflow值 - this._originalContext = { - html: { - overflowX: document.documentElement.style.overflowX, - overflowY: document.documentElement.style.overflowY - }, - body: { - overflowX: document.body.style.overflowX, - overflowY: document.body.style.overflowY + if (this.buttons) { + var buff = []; + for (var i = 0; i < this.buttons.length; i++) { + buff[i] = this.buttons[i].renderHtml(); } - }; - - document.documentElement.style.overflowX = "hidden"; - document.documentElement.style.overflowY = "hidden"; - document.body.style.overflowX = "hidden"; - document.body.style.overflowY = "hidden"; - } - - this._show(); - }, - getContentHtml: function () { - var contentHtml = ""; - if (typeof this.content == "string") { - contentHtml = this.content; - } else if (this.iframeUrl) { - contentHtml = - ''; - } - return contentHtml; - }, - getHtmlTpl: function () { - var footHtml = ""; - - if (this.buttons) { - var buff = []; - for (var i = 0; i < this.buttons.length; i++) { - buff[i] = this.buttons[i].renderHtml(); + footHtml = + '
    ' + + '
    ' + + buff.join("") + + "
    " + + "
    "; } - footHtml = - '
    ' + - '
    ' + - buff.join("") + + + return ( + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + + (this.title || "") + + "" + "
    " + - "
    "; - } - - return ( - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '' + - (this.title || "") + - "" + - "
    " + - this.closeButton.renderHtml() + - "
    " + - '
    ' + - (this.autoReset ? "" : this.getContentHtml()) + - "
    " + - footHtml + - "
    " - ); - }, - postRender: function () { - // todo: 保持居中/记住上次关闭位置选项 - if (!this.modalMask.getDom()) { - this.modalMask.render(); - this.modalMask.hide(); - } - if (!this.dragMask.getDom()) { - this.dragMask.render(); - this.dragMask.hide(); - } - var me = this; - this.addListener("show", function () { - me.modalMask.show(this.getDom().style.zIndex - 2); - }); - this.addListener("hide", function () { - me.modalMask.hide(); - }); - if (this.buttons) { - for (var i = 0; i < this.buttons.length; i++) { - this.buttons[i].postRender(); + this.closeButton.renderHtml() + + "
    " + + '
    ' + + (this.autoReset ? "" : this.getContentHtml()) + + "
    " + + footHtml + + "
    " + ); + }, + postRender: function () { + // todo: 保持居中/记住上次关闭位置选项 + if (!this.modalMask.getDom()) { + this.modalMask.render(); + this.modalMask.hide(); + } + if (!this.dragMask.getDom()) { + this.dragMask.render(); + this.dragMask.hide(); } - } - domUtils.on(window, "resize", function () { - setTimeout(function () { - if (!me.isHidden()) { - me.safeSetOffset(uiUtils.getClientRect(me.getDom())); - } - }); - }); - - //hold住scroll事件,防止dialog的滚动影响页面 - // if( this.holdScroll ) { - // - // if( !me.iframeUrl ) { - // domUtils.on( document.getElementById( me.id + "_iframe"), !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ - // domUtils.preventDefault(e); - // } ); - // } else { - // me.addListener('dialogafterreset', function(){ - // window.setTimeout(function(){ - // var iframeWindow = document.getElementById( me.id + "_iframe").contentWindow; - // - // if( browser.ie ) { - // - // var timer = window.setInterval(function(){ - // - // if( iframeWindow.document && iframeWindow.document.body ) { - // window.clearInterval( timer ); - // timer = null; - // domUtils.on( iframeWindow.document.body, !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ - // domUtils.preventDefault(e); - // } ); - // } - // - // }, 100); - // - // } else { - // domUtils.on( iframeWindow, !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ - // domUtils.preventDefault(e); - // } ); - // } - // - // }, 1); - // }); - // } - // - // } - this._hide(); - }, - mesureSize: function () { - var body = this.getDom("body"); - var width = uiUtils.getClientRect(this.getDom("content")).width; - var dialogBodyStyle = body.style; - dialogBodyStyle.width = width; - // console.log('getClientRect', body) - return uiUtils.getClientRect(body); - }, - _onTitlebarMouseDown: function (evt, el) { - if (this.draggable) { - var rect; - var vpRect = uiUtils.getViewportRect(); var me = this; - uiUtils.startDrag(evt, { - ondragstart: function () { - rect = uiUtils.getClientRect(me.getDom()); - me.getDom("contmask").style.visibility = "visible"; - me.dragMask.show(me.getDom().style.zIndex - 1); - }, - ondragmove: function (x, y) { - var left = rect.left + x; - var top = rect.top + y; - me.safeSetOffset({ - left: left, - top: top - }); - }, - ondragstop: function () { - me.getDom("contmask").style.visibility = "hidden"; - domUtils.removeClasses(me.getDom(), ["edui-state-centered"]); - me.dragMask.hide(); - } + this.addListener("show", function () { + me.modalMask.show(this.getDom().style.zIndex - 2); + }); + this.addListener("hide", function () { + me.modalMask.hide(); + }); + if (this.buttons) { + for (var i = 0; i < this.buttons.length; i++) { + this.buttons[i].postRender(); + } + } + domUtils.on(window, "resize", function () { + setTimeout(function () { + if (!me.isHidden()) { + me.safeSetOffset(uiUtils.getClientRect(me.getDom())); + } + }); }); - } - }, - reset: function () { - this.getDom("content").innerHTML = this.getContentHtml(); - this.fireEvent("dialogafterreset"); - }, - _show: function () { - if (this._hidden) { - this.getDom().style.display = ""; - //要高过编辑器的zindxe - this.editor.container.style.zIndex && - (this.getDom().style.zIndex = - this.editor.container.style.zIndex * 1 + 10); - this._hidden = false; - this.fireEvent("show"); - baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = - this.getDom().style.zIndex - 4; - } - }, - isHidden: function () { - return this._hidden; - }, - _hide: function () { - if (!this._hidden) { - var wrapNode = this.getDom(); - wrapNode.style.display = "none"; - wrapNode.style.zIndex = ""; - wrapNode.style.width = ""; - wrapNode.style.height = ""; - this._hidden = true; - this.fireEvent("hide"); - } - }, - open: function () { - if (this.autoReset) { - //有可能还没有渲染 - try { - this.reset(); - } catch (e) { - this.render(); - this.open(); - } - } - this.showAtCenter(); - if (this.iframeUrl) { - try { - this.getDom("iframe").focus(); - } catch (ex) { - } - } - activeDialog = this; - }, - _onCloseButtonClick: function (evt, el) { - this.close(false); - }, - close: function (ok) { - if (this.fireEvent("close", ok) !== false) { - //还原环境 - if (this.fullscreen) { - document.documentElement.style.overflowX = this._originalContext.html.overflowX; - document.documentElement.style.overflowY = this._originalContext.html.overflowY; - document.body.style.overflowX = this._originalContext.body.overflowX; - document.body.style.overflowY = this._originalContext.body.overflowY; - delete this._originalContext; - } + //hold住scroll事件,防止dialog的滚动影响页面 + // if( this.holdScroll ) { + // + // if( !me.iframeUrl ) { + // domUtils.on( document.getElementById( me.id + "_iframe"), !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ + // domUtils.preventDefault(e); + // } ); + // } else { + // me.addListener('dialogafterreset', function(){ + // window.setTimeout(function(){ + // var iframeWindow = document.getElementById( me.id + "_iframe").contentWindow; + // + // if( browser.ie ) { + // + // var timer = window.setInterval(function(){ + // + // if( iframeWindow.document && iframeWindow.document.body ) { + // window.clearInterval( timer ); + // timer = null; + // domUtils.on( iframeWindow.document.body, !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ + // domUtils.preventDefault(e); + // } ); + // } + // + // }, 100); + // + // } else { + // domUtils.on( iframeWindow, !browser.gecko ? "mousewheel" : "DOMMouseScroll", function(e){ + // domUtils.preventDefault(e); + // } ); + // } + // + // }, 1); + // }); + // } + // + // } this._hide(); + }, + mesureSize: function () { + var body = this.getDom("body"); + var width = uiUtils.getClientRect(this.getDom("content")).width; + var dialogBodyStyle = body.style; + dialogBodyStyle.width = width; + // console.log('getClientRect', body) + return uiUtils.getClientRect(body); + }, + _onTitlebarMouseDown: function (evt, el) { + if (this.draggable) { + var rect; + var vpRect = uiUtils.getViewportRect(); + var me = this; + uiUtils.startDrag(evt, { + ondragstart: function () { + rect = uiUtils.getClientRect(me.getDom()); + me.getDom("contmask").style.visibility = "visible"; + me.dragMask.show(me.getDom().style.zIndex - 1); + }, + ondragmove: function (x, y) { + var left = rect.left + x; + var top = rect.top + y; + me.safeSetOffset({ + left: left, + top: top + }); + }, + ondragstop: function () { + me.getDom("contmask").style.visibility = "hidden"; + domUtils.removeClasses(me.getDom(), ["edui-state-centered"]); + me.dragMask.hide(); + } + }); + } + }, + reset: function () { + this.getDom("content").innerHTML = this.getContentHtml(); + this.fireEvent("dialogafterreset"); + }, + _show: function () { + if (this._hidden) { + this.getDom().style.display = ""; - //销毁content - var content = this.getDom("content"); - var iframe = this.getDom("iframe"); - if (content && iframe) { - var doc = iframe.contentDocument || iframe.contentWindow.document; - doc && (doc.body.innerHTML = ""); - domUtils.remove(content); + //要高过编辑器的zindxe + this.editor.container.style.zIndex && + (this.getDom().style.zIndex = + this.editor.container.style.zIndex * 1 + 10); + this._hidden = false; + this.fireEvent("show"); + baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = + this.getDom().style.zIndex - 4; + } + }, + isHidden: function () { + return this._hidden; + }, + _hide: function () { + if (!this._hidden) { + var wrapNode = this.getDom(); + wrapNode.style.display = "none"; + wrapNode.style.zIndex = ""; + wrapNode.style.width = ""; + wrapNode.style.height = ""; + this._hidden = true; + this.fireEvent("hide"); + } + }, + open: function () { + if (this.autoReset) { + //有可能还没有渲染 + try { + this.reset(); + } catch (e) { + this.render(); + this.open(); + } + } + this.showAtCenter(); + if (this.iframeUrl) { + try { + this.getDom("iframe").focus(); + } catch (ex) { + } + } + activeDialog = this; + }, + _onCloseButtonClick: function (evt, el) { + this.close(false); + }, + close: function (ok) { + if (this.fireEvent("close", ok) !== false) { + //还原环境 + if (this.fullscreen) { + document.documentElement.style.overflowX = this._originalContext.html.overflowX; + document.documentElement.style.overflowY = this._originalContext.html.overflowY; + document.body.style.overflowX = this._originalContext.body.overflowX; + document.body.style.overflowY = this._originalContext.body.overflowY; + delete this._originalContext; + } + this._hide(); + + //销毁content + var content = this.getDom("content"); + var iframe = this.getDom("iframe"); + if (content && iframe) { + var doc = iframe.contentDocument || iframe.contentWindow.document; + doc && (doc.body.innerHTML = ""); + domUtils.remove(content); + } } } - } - }; - utils.inherits(Dialog, UIBase); -})(); + }; + utils.inherits(Dialog, UIBase); + })(); // ui/menubutton.js @@ -30642,1400 +34076,1493 @@ UE.ui = baidu.editor.ui = {}; ///import uicore ///import ui/menu.js ///import ui/splitbutton.js -(function() { - var utils = baidu.editor.utils, - Menu = baidu.editor.ui.Menu, - SplitButton = baidu.editor.ui.SplitButton, - MenuButton = (baidu.editor.ui.MenuButton = function(options) { - this.initOptions(options); - this.initMenuButton(); - }); - MenuButton.prototype = { - initMenuButton: function() { - var me = this; - this.uiName = "menubutton"; - this.popup = new Menu({ - items: me.items, - className: me.className, - editor: me.editor - }); - this.popup.addListener("show", function() { - var list = this; - for (var i = 0; i < list.items.length; i++) { - list.items[i].removeState("checked"); - if (list.items[i].value == me._value) { - list.items[i].addState("checked"); - this.value = me._value; - } - } - }); - this.initSplitButton(); - }, - setValue: function(value) { - this._value = value; - } - }; - utils.inherits(MenuButton, SplitButton); -})(); + (function () { + var utils = baidu.editor.utils, + Menu = baidu.editor.ui.Menu, + SplitButton = baidu.editor.ui.SplitButton, + MenuButton = (baidu.editor.ui.MenuButton = function (options) { + this.initOptions(options); + this.initMenuButton(); + }); + MenuButton.prototype = { + initMenuButton: function () { + var me = this; + this.uiName = "menubutton"; + this.popup = new Menu({ + items: me.items, + className: me.className, + editor: me.editor + }); + this.popup.addListener("show", function () { + var list = this; + for (var i = 0; i < list.items.length; i++) { + list.items[i].removeState("checked"); + if (list.items[i].value == me._value) { + list.items[i].addState("checked"); + this.value = me._value; + } + } + }); + this.initSplitButton(); + }, + setValue: function (value) { + this._value = value; + } + }; + utils.inherits(MenuButton, SplitButton); + })(); // ui/multiMenu.js ///import core ///import uicore ///commands 表情 -(function() { - var utils = baidu.editor.utils, - Popup = baidu.editor.ui.Popup, - SplitButton = baidu.editor.ui.SplitButton, - MultiMenuPop = (baidu.editor.ui.MultiMenuPop = function(options) { - this.initOptions(options); - this.initMultiMenu(); - }); + (function () { + var utils = baidu.editor.utils, + Popup = baidu.editor.ui.Popup, + SplitButton = baidu.editor.ui.SplitButton, + MultiMenuPop = (baidu.editor.ui.MultiMenuPop = function (options) { + this.initOptions(options); + this.initMultiMenu(); + }); - MultiMenuPop.prototype = { - initMultiMenu: function() { - var me = this; - this.popup = new Popup({ - content: "", - editor: me.editor, - iframe_rendered: false, - onshow: function() { - if (!this.iframe_rendered) { - this.iframe_rendered = true; - this.getDom("content").innerHTML = - ''; - me.editor.container.style.zIndex && - (this.getDom().style.zIndex = - me.editor.container.style.zIndex * 1 + 1); - } - } - // canSideUp:false, - // canSideLeft:false - }); - this.onbuttonclick = function() { - this.showPopup(); - }; - this.initSplitButton(); - } - }; + MultiMenuPop.prototype = { + initMultiMenu: function () { + var me = this; + this.popup = new Popup({ + content: "", + editor: me.editor, + iframe_rendered: false, + onshow: function () { + if (!this.iframe_rendered) { + this.iframe_rendered = true; + this.getDom("content").innerHTML = + ''; + me.editor.container.style.zIndex && + (this.getDom().style.zIndex = + me.editor.container.style.zIndex * 1 + 1); + } + } + // canSideUp:false, + // canSideLeft:false + }); + this.onbuttonclick = function () { + this.showPopup(); + }; + this.initSplitButton(); + } + }; - utils.inherits(MultiMenuPop, SplitButton); -})(); + utils.inherits(MultiMenuPop, SplitButton); + })(); // ui/shortcutmenu.js -(function() { - var UI = baidu.editor.ui, - UIBase = UI.UIBase, - uiUtils = UI.uiUtils, - utils = baidu.editor.utils, - domUtils = baidu.editor.dom.domUtils; + (function () { + var UI = baidu.editor.ui, + UIBase = UI.UIBase, + uiUtils = UI.uiUtils, + utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils; - var allMenus = [], //存储所有快捷菜单 - timeID, - isSubMenuShow = false; //是否有子pop显示 + var allMenus = [], //存储所有快捷菜单 + timeID, + isSubMenuShow = false; //是否有子pop显示 - var ShortCutMenu = (UI.ShortCutMenu = function(options) { - this.initOptions(options); - this.initShortCutMenu(); - }); - - ShortCutMenu.postHide = hideAllMenu; - - ShortCutMenu.prototype = { - isHidden: true, - SPACE: 5, - initShortCutMenu: function() { - this.items = this.items || []; - this.initUIBase(); - this.initItems(); - this.initEvent(); - allMenus.push(this); - }, - initEvent: function() { - var me = this, - doc = me.editor.document; - - /* - domUtils.on(doc, "mousemove", function(e) { - if (me.isHidden === false) { - //有pop显示就不隐藏快捷菜单 - if (me.getSubMenuMark() || me.eventType == "contextmenu") return; - - var flag = true, - el = me.getDom(), - wt = el.offsetWidth, - ht = el.offsetHeight, - distanceX = wt / 2 + me.SPACE, //距离中心X标准 - distanceY = ht / 2, //距离中心Y标准 - x = Math.abs(e.screenX - me.left), //离中心距离横坐标 - y = Math.abs(e.screenY - me.top); //离中心距离纵坐标 - - clearTimeout(timeID); - timeID = setTimeout(function() { - if (y > 0 && y < distanceY) { - me.setOpacity(el, "1"); - } else if (y > distanceY && y < distanceY + 70) { - me.setOpacity(el, "0.5"); - flag = false; - } else if (y > distanceY + 70 && y < distanceY + 140) { - me.hide(); - } - - if (flag && x > 0 && x < distanceX) { - me.setOpacity(el, "1"); - } else if (x > distanceX && x < distanceX + 70) { - me.setOpacity(el, "0.5"); - } else if (x > distanceX + 70 && x < distanceX + 140) { - console.log('hide') - me.hide(); - } - }); - } - }); - */ - //ie\ff下 mouseout不准 - /* - if (browser.chrome) { - domUtils.on(doc, "mouseout", function(e) { - var relatedTgt = e.relatedTarget || e.toElement; - - if (relatedTgt == null || relatedTgt.tagName == "HTML") { - me.hide(); - } + var ShortCutMenu = (UI.ShortCutMenu = function (options) { + this.initOptions(options); + this.initShortCutMenu(); }); - } - */ - me.editor.addListener("afterhidepop", function() { - if (!me.isHidden) { - isSubMenuShow = true; + ShortCutMenu.postHide = hideAllMenu; + + ShortCutMenu.prototype = { + isHidden: true, + SPACE: 5, + initShortCutMenu: function () { + this.items = this.items || []; + this.initUIBase(); + this.initItems(); + this.initEvent(); + allMenus.push(this); + }, + initEvent: function () { + var me = this, + doc = me.editor.document; + + /* + domUtils.on(doc, "mousemove", function(e) { + if (me.isHidden === false) { + //有pop显示就不隐藏快捷菜单 + if (me.getSubMenuMark() || me.eventType == "contextmenu") return; + + var flag = true, + el = me.getDom(), + wt = el.offsetWidth, + ht = el.offsetHeight, + distanceX = wt / 2 + me.SPACE, //距离中心X标准 + distanceY = ht / 2, //距离中心Y标准 + x = Math.abs(e.screenX - me.left), //离中心距离横坐标 + y = Math.abs(e.screenY - me.top); //离中心距离纵坐标 + + clearTimeout(timeID); + timeID = setTimeout(function() { + if (y > 0 && y < distanceY) { + me.setOpacity(el, "1"); + } else if (y > distanceY && y < distanceY + 70) { + me.setOpacity(el, "0.5"); + flag = false; + } else if (y > distanceY + 70 && y < distanceY + 140) { + me.hide(); + } + + if (flag && x > 0 && x < distanceX) { + me.setOpacity(el, "1"); + } else if (x > distanceX && x < distanceX + 70) { + me.setOpacity(el, "0.5"); + } else if (x > distanceX + 70 && x < distanceX + 140) { + console.log('hide') + me.hide(); + } + }); + } + }); + */ + //ie\ff下 mouseout不准 + /* + if (browser.chrome) { + domUtils.on(doc, "mouseout", function(e) { + var relatedTgt = e.relatedTarget || e.toElement; + + if (relatedTgt == null || relatedTgt.tagName == "HTML") { + me.hide(); + } + }); + } + */ + + me.editor.addListener("afterhidepop", function () { + if (!me.isHidden) { + isSubMenuShow = true; + } + }); + }, + initItems: function () { + if (utils.isArray(this.items)) { + for (var i = 0, len = this.items.length; i < len; i++) { + if ('string' !== typeof this.items[i]) { + continue; + } + var item = this.items[i].toLowerCase(); + + if (UI[item]) { + this.items[i] = new UI[item](this.editor); + this.items[i].className += " edui-short-cut-sub-menu "; + } + } + } + }, + setOpacity: function (el, value) { + if (browser.ie && browser.version < 9) { + el.style.filter = "alpha(opacity = " + parseFloat(value) * 100 + ");"; + } else { + el.style.opacity = value; + } + }, + getSubMenuMark: function () { + isSubMenuShow = false; + var layerEle = uiUtils.getFixedLayer(); + var list = domUtils.getElementsByTagName(layerEle, "div", function (node) { + return domUtils.hasClass(node, "edui-short-cut-sub-menu edui-popup"); + }); + + for (var i = 0, node; (node = list[i++]);) { + if (node.style.display !== "none") { + isSubMenuShow = true; + } + } + return isSubMenuShow; + }, + show: function (e, hasContextmenu) { + var me = this, + offset = {}, + el = this.getDom(), + fixedlayer = uiUtils.getFixedLayer(); + + for (let item of this.items) { + if ('shouldUiShow' in item) { + item.uiShow(item.shouldUiShow()); + } + } + + function setPos(offset) { + if (offset.left < 0) { + offset.left = 0; + } + if (offset.top < 0) { + offset.top = 0; + } + el.style.cssText = + "position:absolute;left:" + + offset.left + + "px;top:" + + offset.top + + "px;"; + } + + function setPosByCxtMenu(menu) { + if (!menu.tagName) { + menu = menu.getDom(); + } + offset.left = parseInt(menu.style.left); + offset.top = parseInt(menu.style.top); + offset.top -= el.offsetHeight + 15; + setPos(offset); + } + + me.eventType = e.type; + el.style.cssText = "display:block;left:-9999px"; + + // if (e.type === "contextmenu" && hasContextmenu) { + // var menu = domUtils.getElementsByTagName( + // fixedlayer, + // "div", + // "edui-contextmenu" + // )[0]; + // if (menu) { + // setPosByCxtMenu(menu); + // } else { + // me.editor.addListener("aftershowcontextmenu", function (type, menu) { + // setPosByCxtMenu(menu); + // }); + // } + // } else { + offset = uiUtils.getViewportOffsetByEvent(e); + offset.top -= el.offsetHeight + me.SPACE; + offset.left += me.SPACE + 20; + setPos(offset); + me.setOpacity(el, 1); + // } + + me.isHidden = false; + me.left = e.screenX + el.offsetWidth / 2 - me.SPACE; + me.top = e.screenY - el.offsetHeight / 2 - me.SPACE; + + if (me.editor) { + el.style.zIndex = me.editor.container.style.zIndex * 1 + 10; + fixedlayer.style.zIndex = el.style.zIndex - 1; + } + }, + hide: function () { + if (this.getDom()) { + this.getDom().style.display = "none"; + } + this.isHidden = true; + }, + postRender: function () { + if (utils.isArray(this.items)) { + for (var i = 0, item; (item = this.items[i++]);) { + item.postRender(); + } + } + }, + getHtmlTpl: function () { + var buff; + if (utils.isArray(this.items)) { + buff = []; + for (var i = 0; i < this.items.length; i++) { + buff[i] = this.items[i].renderHtml(); + } + buff = buff.join(""); + } else { + buff = this.items; + } + + return ( + '
    ' + + buff + + "
    " + ); + } + }; + + utils.inherits(ShortCutMenu, UIBase); + + function hideAllMenu(e) { + var tgt = e.target || e.srcElement, + cur = domUtils.findParent( + tgt, + function (node) { + return ( + domUtils.hasClass(node, "edui-shortcutmenu") || + domUtils.hasClass(node, "edui-popup") + ); + }, + true + ); + + if (!cur) { + for (var i = 0, menu; (menu = allMenus[i++]);) { + menu.hide(); + } + } } - }); - }, - initItems: function() { - if (utils.isArray(this.items)) { - for (var i = 0, len = this.items.length; i < len; i++) { - if('string' !== typeof this.items[i]){ - continue; - } - var item = this.items[i].toLowerCase(); - if (UI[item]) { - this.items[i] = new UI[item](this.editor); - this.items[i].className += " edui-shortcutsubmenu "; - } - } - } - }, - setOpacity: function(el, value) { - if (browser.ie && browser.version < 9) { - el.style.filter = "alpha(opacity = " + parseFloat(value) * 100 + ");"; - } else { - el.style.opacity = value; - } - }, - getSubMenuMark: function() { - isSubMenuShow = false; - var layerEle = uiUtils.getFixedLayer(); - var list = domUtils.getElementsByTagName(layerEle, "div", function(node) { - return domUtils.hasClass(node, "edui-shortcutsubmenu edui-popup"); - }); + domUtils.on(document, "mousedown", function (e) { + hideAllMenu(e); + }); - for (var i = 0, node; (node = list[i++]); ) { - if (node.style.display != "none") { - isSubMenuShow = true; - } - } - return isSubMenuShow; - }, - show: function(e, hasContextmenu) { - var me = this, - offset = {}, - el = this.getDom(), - fixedlayer = uiUtils.getFixedLayer(); - - function setPos(offset) { - if (offset.left < 0) { - offset.left = 0; - } - if (offset.top < 0) { - offset.top = 0; - } - el.style.cssText = - "position:absolute;left:" + - offset.left + - "px;top:" + - offset.top + - "px;"; - } - - function setPosByCxtMenu(menu) { - if (!menu.tagName) { - menu = menu.getDom(); - } - offset.left = parseInt(menu.style.left); - offset.top = parseInt(menu.style.top); - offset.top -= el.offsetHeight + 15; - setPos(offset); - } - - me.eventType = e.type; - el.style.cssText = "display:block;left:-9999px"; - - if (e.type == "contextmenu" && hasContextmenu) { - var menu = domUtils.getElementsByTagName( - fixedlayer, - "div", - "edui-contextmenu" - )[0]; - if (menu) { - setPosByCxtMenu(menu); - } else { - me.editor.addListener("aftershowcontextmenu", function(type, menu) { - setPosByCxtMenu(menu); - }); - } - } else { - offset = uiUtils.getViewportOffsetByEvent(e); - offset.top -= el.offsetHeight + me.SPACE; - offset.left += me.SPACE + 20; - setPos(offset); - me.setOpacity(el, 1); - } - - me.isHidden = false; - me.left = e.screenX + el.offsetWidth / 2 - me.SPACE; - me.top = e.screenY - el.offsetHeight / 2 - me.SPACE; - - if (me.editor) { - el.style.zIndex = me.editor.container.style.zIndex * 1 + 10; - fixedlayer.style.zIndex = el.style.zIndex - 1; - } - }, - hide: function() { - if (this.getDom()) { - this.getDom().style.display = "none"; - } - this.isHidden = true; - }, - postRender: function() { - if (utils.isArray(this.items)) { - for (var i = 0, item; (item = this.items[i++]); ) { - item.postRender(); - } - } - }, - getHtmlTpl: function() { - var buff; - if (utils.isArray(this.items)) { - buff = []; - for (var i = 0; i < this.items.length; i++) { - buff[i] = this.items[i].renderHtml(); - } - buff = buff.join(""); - } else { - buff = this.items; - } - - return ( - '
    ' + - buff + - "
    " - ); - } - }; - - utils.inherits(ShortCutMenu, UIBase); - - function hideAllMenu(e) { - var tgt = e.target || e.srcElement, - cur = domUtils.findParent( - tgt, - function(node) { - return ( - domUtils.hasClass(node, "edui-shortcutmenu") || - domUtils.hasClass(node, "edui-popup") - ); - }, - true - ); - - if (!cur) { - for (var i = 0, menu; (menu = allMenus[i++]); ) { - menu.hide(); - } - } - } - - domUtils.on(document, "mousedown", function(e) { - hideAllMenu(e); - }); - - domUtils.on(window, "scroll", function(e) { - hideAllMenu(e); - }); -})(); + domUtils.on(window, "scroll", function (e) { + hideAllMenu(e); + }); + })(); // ui/breakline.js -(function() { - var utils = baidu.editor.utils, - UIBase = baidu.editor.ui.UIBase, - Breakline = (baidu.editor.ui.Breakline = function(options) { - this.initOptions(options); - this.initSeparator(); - }); - Breakline.prototype = { - uiName: "Breakline", - initSeparator: function() { - this.initUIBase(); - }, - getHtmlTpl: function() { - return "
    "; - } - }; - utils.inherits(Breakline, UIBase); -})(); + (function () { + var utils = baidu.editor.utils, + UIBase = baidu.editor.ui.UIBase, + Breakline = (baidu.editor.ui.Breakline = function (options) { + this.initOptions(options); + this.initSeparator(); + }); + Breakline.prototype = { + uiName: "Breakline", + initSeparator: function () { + this.initUIBase(); + }, + getHtmlTpl: function () { + return "
    "; + } + }; + utils.inherits(Breakline, UIBase); + })(); // ui/message.js ///import core ///import uicore -(function() { - var utils = baidu.editor.utils, - domUtils = baidu.editor.dom.domUtils, - UIBase = baidu.editor.ui.UIBase, - Message = (baidu.editor.ui.Message = function(options) { - this.initOptions(options); - this.initMessage(); - }); + (function () { + var utils = baidu.editor.utils, + domUtils = baidu.editor.dom.domUtils, + UIBase = baidu.editor.ui.UIBase, + Message = (baidu.editor.ui.Message = function (options) { + this.initOptions(options); + this.initMessage(); + }); - Message.prototype = { - initMessage: function() { - this.initUIBase(); - }, - getHtmlTpl: function() { - return ( - '
    ' + - '
    ×
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - "
    " + - "
    " + - "
    " - ); - }, - reset: function(opt) { - var me = this; - if (!opt.keepshow) { - clearTimeout(this.timer); - me.timer = setTimeout(function() { - me.hide(); - }, opt.timeout || 4000); - } + Message.prototype = { + initMessage: function () { + this.initUIBase(); + }, + getHtmlTpl: function () { + return ( + '
    ' + + '
    ×
    ' + + '
    ' + + ' ' + + '
    ' + + '
    ' + + "
    " + + "
    " + + "
    " + ); + }, + reset: function (opt) { + var me = this; + if (!opt.keepshow) { + clearTimeout(this.timer); + me.timer = setTimeout(function () { + me.hide(); + }, opt.timeout || 4000); + } - opt.content !== undefined && me.setContent(opt.content); - opt.type !== undefined && me.setType(opt.type); + opt.content !== undefined && me.setContent(opt.content); + opt.type !== undefined && me.setType(opt.type); - me.show(); - }, - postRender: function() { - var me = this, - closer = this.getDom("closer"); - closer && - domUtils.on(closer, "click", function() { - me.hide(); - }); - }, - setContent: function(content) { - this.getDom("content").innerHTML = content; - }, - setType: function(type) { - type = type || "info"; - var body = this.getDom("body"); - body.className = body.className.replace( - /edui-message-type-[\w-]+/, - "edui-message-type-" + type - ); - }, - getContent: function() { - return this.getDom("content").innerHTML; - }, - getType: function() { - var arr = this.getDom("body").match(/edui-message-type-([\w-]+)/); - return arr ? arr[1] : ""; - }, - show: function() { - this.getDom().style.display = "block"; - }, - hide: function() { - var dom = this.getDom(); - if (dom) { - dom.style.display = "none"; - dom.parentNode && dom.parentNode.removeChild(dom); - } - } - }; + me.show(); + }, + postRender: function () { + var me = this, + closer = this.getDom("closer"); + closer && + domUtils.on(closer, "click", function () { + me.hide(); + }); + }, + setContent: function (content) { + this.getDom("content").innerHTML = content; + }, + setType: function (type) { + type = type || "info"; + var body = this.getDom("body"); + body.className = body.className.replace( + /edui-message-type-[\w-]+/, + "edui-message-type-" + type + ); + }, + getContent: function () { + return this.getDom("content").innerHTML; + }, + getType: function () { + var arr = this.getDom("body").match(/edui-message-type-([\w-]+)/); + return arr ? arr[1] : ""; + }, + show: function () { + this.getDom().style.display = "block"; + }, + hide: function () { + var dom = this.getDom(); + if (dom) { + dom.style.display = "none"; + dom.parentNode && dom.parentNode.removeChild(dom); + } + } + }; - utils.inherits(Message, UIBase); -})(); + utils.inherits(Message, UIBase); + })(); // adapter/editorui.js //ui跟编辑器的适配層 //那个按钮弹出是dialog,是下拉筐等都是在这个js中配置 //自己写的ui也要在这里配置,放到baidu.editor.ui下边,当编辑器实例化的时候会根据ueditor.config中的toolbars找到相应的进行实例化 -(function() { - var utils = baidu.editor.utils; - var editorui = baidu.editor.ui; - var _Dialog = editorui.Dialog; - editorui.buttons = {}; + (function () { + var utils = baidu.editor.utils; + var editorui = baidu.editor.ui; + var _Dialog = editorui.Dialog; + editorui.buttons = {}; - editorui.Dialog = function(options) { - var dialog = new _Dialog(options); - dialog.addListener("hide", function() { - if (dialog.editor) { - var editor = dialog.editor; - try { - if (browser.gecko) { - var y = editor.window.scrollY, - x = editor.window.scrollX; - editor.body.focus(); - editor.window.scrollTo(x, y); - } else { - editor.focus(); - } - } catch (ex) {} - } - }); - return dialog; - }; - - var iframeUrlMap = { - anchor: "~/dialogs/anchor/anchor.html?20220503", - insertimage: "~/dialogs/image/image.html?20220503", - link: "~/dialogs/link/link.html?20220503", - spechars: "~/dialogs/spechars/spechars.html?20220503", - searchreplace: "~/dialogs/searchreplace/searchreplace.html?20220503", - insertvideo: "~/dialogs/video/video.html?20220503", - insertaudio: "~/dialogs/audio/audio.html?20220503", - help: "~/dialogs/help/help.html?20220503", - preview: "~/dialogs/preview/preview.html?20220503", - emotion: "~/dialogs/emotion/emotion.html?20220503", - wordimage: "~/dialogs/wordimage/wordimage.html?20220902", - formula: "~/dialogs/formula/formula.html?20230822", - attachment: "~/dialogs/attachment/attachment.html?20220503", - insertframe: "~/dialogs/insertframe/insertframe.html?20220503", - edittip: "~/dialogs/table/edittip.html?20220503", - edittable: "~/dialogs/table/edittable.html?20220503", - edittd: "~/dialogs/table/edittd.html?20220503", - scrawl: "~/dialogs/scrawl/scrawl.html?20220503", - template: "~/dialogs/template/template.html?20220503", - background: "~/dialogs/background/background.html?20220503", - }; - //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起 - var btnCmds = [ - "undo", - "redo", - "formatmatch", - "bold", - "italic", - "underline", - "fontborder", - "touppercase", - "tolowercase", - "strikethrough", - "subscript", - "superscript", - "source", - "indent", - "outdent", - "blockquote", - "pasteplain", - "pagebreak", - "selectall", - "print", - "horizontal", - "removeformat", - "time", - "date", - "unlink", - "insertparagraphbeforetable", - "insertrow", - "insertcol", - "mergeright", - "mergedown", - "deleterow", - "deletecol", - "splittorows", - "splittocols", - "splittocells", - "mergecells", - "deletetable", - ]; - - for (var i = 0, ci; (ci = btnCmds[i++]); ) { - ci = ci.toLowerCase(); - editorui[ci] = (function(cmd) { - return function(editor) { - var ui = new editorui.Button({ - className: "edui-for-" + cmd, - title: - editor.options.labelMap[cmd] || - editor.getLang("labelMap." + cmd) || - "", - onclick: function() { - editor.execCommand(cmd); - }, - theme: editor.options.theme, - showText: false - }); - editorui.buttons[cmd] = ui; - editor.addListener("selectionchange", function( - type, - causeByUi, - uiReady - ) { - var state = editor.queryCommandState(cmd); - // console.log('selectionchange',cmd,uiReady,state); - if (state == -1) { - ui.setDisabled(true); - ui.setChecked(false); - } else { - if (!uiReady) { - ui.setDisabled(false); - ui.setChecked(state); - } - } - }); - return ui; - }; - })(ci); - } - - //清除文档 - editorui.cleardoc = function(editor) { - var ui = new editorui.Button({ - className: "edui-for-cleardoc", - title: - editor.options.labelMap.cleardoc || - editor.getLang("labelMap.cleardoc") || - "", - theme: editor.options.theme, - onclick: function() { - if (confirm(editor.getLang("confirmClear"))) { - editor.execCommand("cleardoc"); - } - } - }); - editorui.buttons["cleardoc"] = ui; - editor.addListener("selectionchange", function() { - ui.setDisabled(editor.queryCommandState("cleardoc") == -1); - }); - return ui; - }; - - //排版,图片排版,文字方向 - var typeset = { - justify: ["left", "right", "center", "justify"], - imagefloat: ["none", "left", "center", "right"], - directionality: ["ltr", "rtl"] - }; - - for (var p in typeset) { - (function(cmd, val) { - for (var i = 0, ci; (ci = val[i++]); ) { - (function(cmd2) { - editorui[cmd.replace("float", "") + cmd2] = function(editor) { - var ui = new editorui.Button({ - className: "edui-for-" + cmd.replace("float", "") + cmd2, - title: - editor.options.labelMap[cmd.replace("float", "") + cmd2] || - editor.getLang( - "labelMap." + cmd.replace("float", "") + cmd2 - ) || - "", - theme: editor.options.theme, - onclick: function() { - editor.execCommand(cmd, cmd2); - } - }); - editorui.buttons[cmd] = ui; - editor.addListener("selectionchange", function( - type, - causeByUi, - uiReady - ) { - ui.setDisabled(editor.queryCommandState(cmd) == -1); - ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady); - }); - return ui; - }; - })(ci); - } - })(p, typeset[p]); - } - - //字体颜色和背景颜色 - for (var i = 0, ci; (ci = ["backcolor", "forecolor"][i++]); ) { - editorui[ci] = (function(cmd) { - return function(editor) { - var ui = new editorui.ColorButton({ - className: "edui-for-" + cmd, - color: "default", - title: - editor.options.labelMap[cmd] || - editor.getLang("labelMap." + cmd) || - "", - editor: editor, - onpickcolor: function(t, color) { - editor.execCommand(cmd, color); - }, - onpicknocolor: function() { - editor.execCommand(cmd, "default"); - this.setColor("transparent"); - this.color = "default"; - }, - onbuttonclick: function() { - editor.execCommand(cmd, this.color); - } - }); - editorui.buttons[cmd] = ui; - editor.addListener("selectionchange", function() { - ui.setDisabled(editor.queryCommandState(cmd) == -1); - }); - return ui; - }; - })(ci); - } - - var dialogBtns = { - noOk: ["searchreplace", "help", "spechars", "preview"], - ok: [ - "attachment", - "anchor", - "link", - "insertimage", - "insertframe", - "wordimage", - "insertvideo", - "insertaudio", - "insertframe", - "edittip", - "edittable", - "edittd", - "scrawl", - "template", - "formula", - "background", - ] - }; - - for (var p in dialogBtns) { - (function(type, vals) { - for (var i = 0, ci; (ci = vals[i++]); ) { - //todo opera下存在问题 - if (browser.opera && ci === "searchreplace") { - continue; - } - (function(cmd) { - editorui[cmd] = function(editor, iframeUrl, title) { - iframeUrl = - iframeUrl || - (editor.options.iframeUrlMap || {})[cmd] || - iframeUrlMap[cmd]; - title = - editor.options.labelMap[cmd] || - editor.getLang("labelMap." + cmd) || - ""; - - var dialog; - //没有iframeUrl不创建dialog - if (iframeUrl) { - dialog = new editorui.Dialog( - utils.extend( - { - iframeUrl: editor.ui.mapUrl(iframeUrl), - editor: editor, - className: "edui-for-" + cmd, - title: title, - holdScroll: cmd === "insertimage", - fullscreen: /preview/.test(cmd), - closeDialog: editor.getLang("closeDialog") - }, - type == "ok" - ? { - buttons: [ - { - className: "edui-okbutton", - label: editor.getLang("ok"), - editor: editor, - onclick: function() { - dialog.close(true); - } - }, - { - className: "edui-cancelbutton", - label: editor.getLang("cancel"), - editor: editor, - onclick: function() { - dialog.close(false); - } - } - ] - } - : {} - ) - ); - - editor.ui._dialogs[cmd + "Dialog"] = dialog; - } - - var ui = new editorui.Button({ - className: "edui-for-" + cmd, - title: title, - onclick: function() { - if(editor.options.toolbarCallback){ - if(true === editor.options.toolbarCallback(cmd,editor)){ - return; + editorui.Dialog = function (options) { + var dialog = new _Dialog(options); + dialog.addListener("hide", function () { + if (dialog.editor) { + var editor = dialog.editor; + try { + if (browser.gecko) { + var y = editor.window.scrollY, + x = editor.window.scrollX; + editor.body.focus(); + editor.window.scrollTo(x, y); + } else { + editor.focus(); + } + } catch (ex) { } } - if (dialog) { - switch (cmd) { - case "wordimage": - var images = editor.execCommand("wordimage"); - if (images && images.length) { - dialog.render(); - dialog.open(); - } - break; - case "scrawl": - if (editor.queryCommandState("scrawl") != -1) { - dialog.render(); - dialog.open(); - } + }); + return dialog; + }; - break; - default: - dialog.render(); - dialog.open(); - } + //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起 + var btnCmds = [ + "undo", + "redo", + "formatmatch", + "bold", + "italic", + "underline", + "fontborder", + "touppercase", + "tolowercase", + "strikethrough", + "subscript", + "superscript", + "source", + "indent", + "outdent", + "blockquote", + "pasteplain", + "pagebreak", + "selectall", + "print", + "horizontal", + "removeformat", + "time", + "date", + "unlink", + "insertparagraphbeforetable", + "insertrow", + "insertcol", + "mergeright", + "mergedown", + "deleterow", + "deletecol", + "splittorows", + "splittocols", + "splittocells", + "mergecells", + "deletetable", + ]; + + for (var i = 0, ci; (ci = btnCmds[i++]);) { + ci = ci.toLowerCase(); + editorui[ci] = (function (cmd) { + return function (editor) { + var ui = new editorui.Button({ + className: "edui-for-" + cmd, + title: + editor.options.labelMap[cmd] || + editor.getLang("labelMap." + cmd) || + "", + onclick: function () { + editor.execCommand(cmd); + }, + theme: editor.options.theme, + showText: false + }); + switch (cmd) { + case 'bold': + case 'italic': + case 'underline': + case 'strikethrough': + case 'fontborder': + ui.shouldUiShow = (function (cmdInternal) { + return function () { + if (!editor.selection.getText()) { + return false; + } + return editor.queryCommandState(cmdInternal) !== UE.constants.STATEFUL.DISABLED; + } + })(cmd); + break; + } + editorui.buttons[cmd] = ui; + editor.addListener("selectionchange", function ( + type, + causeByUi, + uiReady + ) { + var state = editor.queryCommandState(cmd); + if (state === -1) { + ui.setDisabled(true); + ui.setChecked(false); + } else { + if (!uiReady) { + ui.setDisabled(false); + ui.setChecked(state); + } + } + }); + return ui; + }; + })(ci); + } + + //清除文档 + editorui.cleardoc = function (editor) { + var ui = new editorui.Button({ + className: "edui-for-cleardoc", + title: + editor.options.labelMap.cleardoc || + editor.getLang("labelMap.cleardoc") || + "", + theme: editor.options.theme, + onclick: function () { + if (confirm(editor.getLang("confirmClear"))) { + editor.execCommand("cleardoc"); + } } - }, - theme: editor.options.theme, - disabled: - (cmd == "scrawl" && editor.queryCommandState("scrawl") == -1) + }); + editorui.buttons["cleardoc"] = ui; + editor.addListener("selectionchange", function () { + ui.setDisabled(editor.queryCommandState("cleardoc") == -1); + }); + return ui; + }; + + var imageTypeSet = [ + 'none', 'left', 'center', 'right' + ]; + for (let value of imageTypeSet) { + (function (value) { + editorui['image' + value] = function (editor) { + var ui = new editorui.Button({ + className: "edui-for-" + 'image' + value, + title: + editor.options.labelMap['image' + value] || + editor.getLang( + "labelMap." + 'image' + value + ) || + "", + theme: editor.options.theme, + onclick: function () { + editor.execCommand('imagefloat', value); + }, + shouldUiShow: function () { + let closedNode = editor.selection.getRange().getClosedNode(); + if (!closedNode || closedNode.tagName !== "IMG") { + return false; + } + if (domUtils.hasClass(closedNode, "uep-loading") || domUtils.hasClass(closedNode, "uep-loading-error")) { + return false; + } + return editor.queryCommandState('imagefloat') !== UE.constants.STATEFUL.DISABLED; + } + }); + editorui.buttons['image' + value] = ui; + editor.addListener("selectionchange", function ( + type, + causeByUi, + uiReady + ) { + ui.setDisabled(editor.queryCommandState('imagefloat') === UE.constants.STATEFUL.DISABLED); + ui.setChecked(editor.queryCommandValue('imagefloat') === value && !uiReady); + }); + return ui; + }; + })(value); + } + + //排版,图片排版,文字方向 + var typeset = { + justify: ["left", "right", "center", "justify"], + directionality: ["ltr", "rtl"] + }; + for (var p in typeset) { + (function (cmd, val) { + for (var i = 0, ci; (ci = val[i++]);) { + (function (cmd2) { + editorui[cmd.replace("float", "") + cmd2] = function (editor) { + var ui = new editorui.Button({ + className: "edui-for-" + cmd.replace("float", "") + cmd2, + title: + editor.options.labelMap[cmd.replace("float", "") + cmd2] || + editor.getLang( + "labelMap." + cmd.replace("float", "") + cmd2 + ) || + "", + theme: editor.options.theme, + onclick: function () { + editor.execCommand(cmd, cmd2); + } + }); + editorui.buttons[cmd] = ui; + editor.addListener("selectionchange", function ( + type, + causeByUi, + uiReady + ) { + ui.setDisabled(editor.queryCommandState(cmd) == -1); + ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady); + }); + return ui; + }; + })(ci); + } + })(p, typeset[p]); + } + + //字体颜色和背景颜色 + for (var i = 0, ci; (ci = ["backcolor", "forecolor"][i++]);) { + editorui[ci] = (function (cmd) { + return function (editor) { + var ui = new editorui.ColorButton({ + className: "edui-for-" + cmd, + color: "default", + title: + editor.options.labelMap[cmd] || + editor.getLang("labelMap." + cmd) || + "", + editor: editor, + onpickcolor: function (t, color) { + editor.execCommand(cmd, color); + }, + onpicknocolor: function () { + editor.execCommand(cmd, "default"); + this.setColor("transparent"); + this.color = "default"; + }, + onbuttonclick: function () { + editor.execCommand(cmd, this.color); + }, + shouldUiShow: function () { + if (!editor.selection.getText()) { + return false; + } + return editor.queryCommandState(cmd) !== UE.constants.STATEFUL.DISABLED; + } + }); + + editorui.buttons[cmd] = ui; + editor.addListener("selectionchange", function () { + ui.setDisabled(editor.queryCommandState(cmd) == -1); + }); + return ui; + }; + })(ci); + } + + var dialogIframeUrlMap = { + anchor: "~/dialogs/anchor/anchor.html?2f10d082", + insertimage: "~/dialogs/image/image.html?4bce17a0", + link: "~/dialogs/link/link.html?ccbfcf18", + spechars: "~/dialogs/spechars/spechars.html?3bbeb696", + searchreplace: "~/dialogs/searchreplace/searchreplace.html?2cb782d2", + insertvideo: "~/dialogs/video/video.html?7fde01cd", + insertaudio: "~/dialogs/audio/audio.html?d264cea1", + help: "~/dialogs/help/help.html?05c0c8bf", + preview: "~/dialogs/preview/preview.html?5d9a0847", + emotion: "~/dialogs/emotion/emotion.html?a7bc0989", + wordimage: "~/dialogs/wordimage/wordimage.html?11da452e", + formula: "~/dialogs/formula/formula.html?9a5a1511", + attachment: "~/dialogs/attachment/attachment.html?d632fa7c", + insertframe: "~/dialogs/insertframe/insertframe.html?807119a5", + edittip: "~/dialogs/table/edittip.html?fa0ea189", + edittable: "~/dialogs/table/edittable.html?134e2f06", + edittd: "~/dialogs/table/edittd.html?9fe1a06e", + scrawl: "~/dialogs/scrawl/scrawl.html?c8323e43", + template: "~/dialogs/template/template.html?3c8090b7", + background: "~/dialogs/background/background.html?c2bb8b05", + contentimport: "~/dialogs/contentimport/contentimport.html?e298f77b", + }; + var dialogBtns = { + noOk: ["searchreplace", "help", "spechars", "preview"], + ok: [ + "attachment", + "anchor", + "link", + "insertimage", + "insertframe", + "wordimage", + "insertvideo", + "insertaudio", + "edittip", + "edittable", + "edittd", + "scrawl", + "template", + "formula", + "background", + "contentimport", + ] + }; + for (var p in dialogBtns) { + (function (type, vals) { + for (var i = 0, ci; (ci = vals[i++]);) { + //todo opera下存在问题 + if (browser.opera && ci === "searchreplace") { + continue; + } + (function (cmd) { + editorui[cmd] = function (editor, iframeUrl, title) { + iframeUrl = + iframeUrl || + (editor.options.dialogIframeUrlMap || {})[cmd] || + dialogIframeUrlMap[cmd]; + title = + editor.options.labelMap[cmd] || + editor.getLang("labelMap." + cmd) || + ""; + + var dialog; + //没有iframeUrl不创建dialog + if (iframeUrl) { + dialog = new editorui.Dialog( + utils.extend( + { + iframeUrl: editor.ui.mapUrl(iframeUrl), + editor: editor, + className: "edui-for-" + cmd, + title: title, + holdScroll: cmd === "insertimage", + fullscreen: /preview/.test(cmd), + closeDialog: editor.getLang("closeDialog") + }, + type === "ok" + ? { + buttons: [ + { + className: "edui-okbutton", + label: editor.getLang("ok"), + editor: editor, + onclick: function () { + dialog.close(true); + } + }, + { + className: "edui-cancelbutton", + label: editor.getLang("cancel"), + editor: editor, + onclick: function () { + dialog.close(false); + } + } + ] + } + : {} + ) + ); + + editor.ui._dialogs[cmd + "Dialog"] = dialog; + } + + var ui = new editorui.Button({ + className: "edui-for-" + cmd, + title: title, + onclick: function () { + if (editor.options.toolbarCallback) { + if (true === editor.options.toolbarCallback(cmd, editor)) { + return; + } + } + if (dialog) { + switch (cmd) { + case "wordimage": + var images = editor.execCommand("wordimage"); + if (images && images.length) { + dialog.render(); + dialog.open(); + } + break; + case "scrawl": + if (editor.queryCommandState("scrawl") !== -1) { + dialog.render(); + dialog.open(); + } + break; + default: + dialog.render(); + dialog.open(); + } + } + }, + theme: editor.options.theme, + disabled: (cmd === "scrawl" && editor.queryCommandState("scrawl") === -1) + }); + switch (cmd) { + case 'insertimage': + case 'formula': + ui.shouldUiShow = (function (cmd) { + return function () { + let closedNode = editor.selection.getRange().getClosedNode(); + if (!closedNode || closedNode.tagName !== "IMG") { + return false; + } + if ('formula' === cmd && closedNode.getAttribute('data-formula-image') !== null) { + return true; + } + if ('insertimage' === cmd) { + return true; + } + return false; + }; + })(cmd); + break; + } + editorui.buttons[cmd] = ui; + editor.addListener("selectionchange", function () { + //只存在于右键菜单而无工具栏按钮的ui不需要检测状态 + var unNeedCheckState = {edittable: 1}; + if (cmd in unNeedCheckState) return; + + var state = editor.queryCommandState(cmd); + if (ui.getDom()) { + ui.setDisabled(state === -1); + ui.setChecked(state); + } + }); + + return ui; + }; + })(ci.toLowerCase()); + } + })(p, dialogBtns[p]); + } + + editorui.insertcode = function (editor, list, title) { + list = editor.options["insertcode"] || []; + title = + editor.options.labelMap["insertcode"] || + editor.getLang("labelMap.insertcode") || + ""; + // if (!list.length) return; + var items = []; + utils.each(list, function (key, val) { + items.push({ + label: key, + value: val, + theme: editor.options.theme, + renderLabelHtml: function () { + return ( + '
    ' + (this.label || "") + "
    " + ); + } + }); + }); + + var ui = new editorui.Combox({ + editor: editor, + items: items, + onselect: function (t, index) { + editor.execCommand("insertcode", this.items[index].value); + }, + onbuttonclick: function () { + this.showPopup(); + }, + title: title, + initValue: title, + className: "edui-for-insertcode", + indexByValue: function (value) { + if (value) { + for (var i = 0, ci; (ci = this.items[i]); i++) { + if (ci.value.indexOf(value) != -1) return i; + } + } + + return -1; + } + }); + editorui.buttons["insertcode"] = ui; + editor.addListener("selectionchange", function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState("insertcode"); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue("insertcode"); + if (!value) { + ui.setValue(title); + return; + } + //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号 + value && (value = value.replace(/['"]/g, "").split(",")[0]); + ui.setValue(value); + } + } + }); + return ui; + }; + + editorui.fontfamily = function (editor, list, title) { + list = editor.options["fontfamily"] || []; + title = + editor.options.labelMap["fontfamily"] || + editor.getLang("labelMap.fontfamily") || + ""; + if (!list.length) return; + for (var i = 0, ci, items = []; (ci = list[i]); i++) { + var langLabel = editor.getLang("fontfamily")[ci.name] || ""; + (function (key, val) { + items.push({ + label: key, + value: val, + theme: editor.options.theme, + renderLabelHtml: function () { + return ( + '
    ' + + (this.label || "") + + "
    " + ); + } + }); + })(ci.label || langLabel, ci.val); + } + var ui = new editorui.Combox({ + editor: editor, + items: items, + onselect: function (t, index) { + editor.execCommand("FontFamily", this.items[index].value); + }, + onbuttonclick: function () { + this.showPopup(); + }, + title: title, + initValue: title, + className: "edui-for-fontfamily", + indexByValue: function (value) { + if (value) { + for (var i = 0, ci; (ci = this.items[i]); i++) { + if (ci.value.indexOf(value) != -1) return i; + } + } + return -1; + } + }); + editorui.buttons["fontfamily"] = ui; + editor.addListener("selectionchange", function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState("FontFamily"); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue("FontFamily"); + //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号 + value && (value = value.replace(/['"]/g, "").split(",")[0]); + ui.setValue(value); + } + } + }); + return ui; + }; + + editorui.fontsize = function (editor, list, title) { + title = + editor.options.labelMap["fontsize"] || + editor.getLang("labelMap.fontsize") || + ""; + list = list || editor.options["fontsize"] || []; + if (!list.length) return; + var items = []; + for (var i = 0; i < list.length; i++) { + var size = list[i] + "px"; + items.push({ + label: size, + value: size, + theme: editor.options.theme, + renderLabelHtml: function () { + return ( + '
    ' + + (this.label || "") + + "
    " + ); + } + }); + } + var ui = new editorui.Combox({ + editor: editor, + items: items, + title: title, + initValue: title, + onselect: function (t, index) { + editor.execCommand("FontSize", this.items[index].value); + }, + onbuttonclick: function () { + this.showPopup(); + }, + className: "edui-for-fontsize" + }); + editorui.buttons["fontsize"] = ui; + editor.addListener("selectionchange", function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState("FontSize"); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + ui.setValue(editor.queryCommandValue("FontSize")); + } + } + }); + return ui; + }; + + editorui.paragraph = function (editor, list, title) { + title = + editor.options.labelMap["paragraph"] || + editor.getLang("labelMap.paragraph") || + ""; + list = editor.options["paragraph"] || []; + if (utils.isEmptyObject(list)) return; + var items = []; + for (var i in list) { + items.push({ + value: i, + label: list[i] || editor.getLang("paragraph")[i], + theme: editor.options.theme, + renderLabelHtml: function () { + return ( + '
    ' + + (this.label || "") + + "
    " + ); + } + }); + } + var ui = new editorui.Combox({ + editor: editor, + items: items, + title: title, + initValue: title, + className: "edui-for-paragraph", + onselect: function (t, index) { + editor.execCommand("Paragraph", this.items[index].value); + }, + onbuttonclick: function () { + this.showPopup(); + } + }); + editorui.buttons["paragraph"] = ui; + editor.addListener("selectionchange", function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState("Paragraph"); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue("Paragraph"); + var index = ui.indexByValue(value); + if (index != -1) { + ui.setValue(value); + } else { + ui.setValue(ui.initValue); + } + } + } + }); + return ui; + }; + + //自定义标题 + editorui.customstyle = function (editor) { + var list = editor.options["customstyle"] || [], + title = + editor.options.labelMap["customstyle"] || + editor.getLang("labelMap.customstyle") || + ""; + if (!list.length) return; + var langCs = editor.getLang("customstyle"); + for (var i = 0, items = [], t; (t = list[i++]);) { + (function (t) { + var ck = {}; + ck.label = t.label ? t.label : langCs[t.name]; + ck.style = t.style; + ck.className = t.className; + ck.tag = t.tag; + items.push({ + label: ck.label, + value: ck, + theme: editor.options.theme, + renderLabelHtml: function () { + return ( + '
    ' + + "<" + + ck.tag + + " " + + (ck.className ? ' class="' + ck.className + '"' : "") + + (ck.style ? ' style="' + ck.style + '"' : "") + + ">" + + ck.label + + "" + + "
    " + ); + } + }); + })(t); + } + + var ui = new editorui.Combox({ + editor: editor, + items: items, + title: title, + initValue: title, + className: "edui-for-customstyle", + onselect: function (t, index) { + editor.execCommand("customstyle", this.items[index].value); + }, + onbuttonclick: function () { + this.showPopup(); + }, + indexByValue: function (value) { + for (var i = 0, ti; (ti = this.items[i++]);) { + if (ti.label == value) { + return i - 1; + } + } + return -1; + } + }); + editorui.buttons["customstyle"] = ui; + editor.addListener("selectionchange", function (type, causeByUi, uiReady) { + if (!uiReady) { + var state = editor.queryCommandState("customstyle"); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue("customstyle"); + var index = ui.indexByValue(value); + if (index != -1) { + ui.setValue(value); + } else { + ui.setValue(ui.initValue); + } + } + } + }); + return ui; + }; + + editorui.inserttable = function (editor, iframeUrl, title) { + title = + editor.options.labelMap["inserttable"] || + editor.getLang("labelMap.inserttable") || + ""; + var ui = new editorui.TableButton({ + editor: editor, + title: title, + className: "edui-for-inserttable", + onpicktable: function (t, numCols, numRows) { + editor.execCommand("InsertTable", { + numRows: numRows, + numCols: numCols, + border: 1 + }); + }, + onbuttonclick: function () { + this.showPopup(); + } + }); + editorui.buttons["inserttable"] = ui; + editor.addListener("selectionchange", function () { + ui.setDisabled(editor.queryCommandState("inserttable") == -1); + }); + return ui; + }; + + editorui.lineheight = function (editor) { + var val = editor.options.lineheight || []; + if (!val.length) return; + for (var i = 0, ci, items = []; (ci = val[i++]);) { + items.push({ + //todo:写死了 + label: ci, + value: ci, + theme: editor.options.theme, + onclick: function () { + editor.execCommand("lineheight", this.value); + } + }); + } + var ui = new editorui.MenuButton({ + editor: editor, + className: "edui-for-lineheight", + title: + editor.options.labelMap["lineheight"] || + editor.getLang("labelMap.lineheight") || + "", + items: items, + onbuttonclick: function () { + var value = editor.queryCommandValue("LineHeight") || this.value; + editor.execCommand("LineHeight", value); + } + }); + editorui.buttons["lineheight"] = ui; + editor.addListener("selectionchange", function () { + var state = editor.queryCommandState("LineHeight"); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue("LineHeight"); + value && ui.setValue((value + "").replace(/cm/, "")); + ui.setChecked(state); + } + }); + return ui; + }; + + var rowspacings = ["top", "bottom"]; + for (var r = 0, ri; (ri = rowspacings[r++]);) { + (function (cmd) { + editorui["rowspacing" + cmd] = function (editor) { + var val = editor.options["rowspacing" + cmd] || []; + if (!val.length) return null; + for (var i = 0, ci, items = []; (ci = val[i++]);) { + items.push({ + label: ci, + value: ci, + theme: editor.options.theme, + onclick: function () { + editor.execCommand("rowspacing", this.value, cmd); + } + }); + } + var ui = new editorui.MenuButton({ + editor: editor, + className: "edui-for-rowspacing" + cmd, + title: + editor.options.labelMap["rowspacing" + cmd] || + editor.getLang("labelMap.rowspacing" + cmd) || + "", + items: items, + onbuttonclick: function () { + var value = + editor.queryCommandValue("rowspacing", cmd) || this.value; + editor.execCommand("rowspacing", value, cmd); + } + }); + editorui.buttons[cmd] = ui; + editor.addListener("selectionchange", function () { + var state = editor.queryCommandState("rowspacing", cmd); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue("rowspacing", cmd); + value && ui.setValue((value + "").replace(/%/, "")); + ui.setChecked(state); + } + }); + return ui; + }; + })(ri); + } + + //有序,无序列表 + var lists = ["insertorderedlist", "insertunorderedlist"]; + for (var l = 0, cl; (cl = lists[l++]);) { + (function (cmd) { + editorui[cmd] = function (editor) { + var vals = editor.options[cmd], + _onMenuClick = function () { + editor.execCommand(cmd, this.value); + }, + items = []; + for (var i in vals) { + items.push({ + label: vals[i] || editor.getLang()[cmd][i] || "", + value: i, + theme: editor.options.theme, + onclick: _onMenuClick + }); + } + var ui = new editorui.MenuButton({ + editor: editor, + className: "edui-for-" + cmd, + title: editor.getLang("labelMap." + cmd) || "", + items: items, + onbuttonclick: function () { + var value = editor.queryCommandValue(cmd) || this.value; + editor.execCommand(cmd, value); + } + }); + editorui.buttons[cmd] = ui; + editor.addListener("selectionchange", function () { + var state = editor.queryCommandState(cmd); + if (state == -1) { + ui.setDisabled(true); + } else { + ui.setDisabled(false); + var value = editor.queryCommandValue(cmd); + ui.setValue(value); + ui.setChecked(state); + } + }); + return ui; + }; + })(cl); + } + + editorui.fullscreen = function (editor, title) { + title = + editor.options.labelMap["fullscreen"] || + editor.getLang("labelMap.fullscreen") || + ""; + var ui = new editorui.Button({ + className: "edui-for-fullscreen", + title: title, + theme: editor.options.theme, + onclick: function () { + if (editor.ui) { + editor.ui.setFullScreen(!editor.ui.isFullScreen()); + } + this.setChecked(editor.ui.isFullScreen()); + } + }); + editorui.buttons["fullscreen"] = ui; + editor.addListener("selectionchange", function () { + var state = editor.queryCommandState("fullscreen"); + ui.setDisabled(state == -1); + ui.setChecked(editor.ui.isFullScreen()); + }); + return ui; + }; + + // 表情 + editorui['emotion'] = function (editor, iframeUrl) { + var cmd = "emotion"; + var ui = new editorui.MultiMenuPop({ + title: + editor.options.labelMap[cmd] || + editor.getLang("labelMap." + cmd + "") || + "", + editor: editor, + className: "edui-for-" + cmd, + iframeUrl: editor.ui.mapUrl( + iframeUrl || + (editor.options.dialogIframeUrlMap || {})[cmd] || + dialogIframeUrlMap[cmd] + ) }); editorui.buttons[cmd] = ui; - editor.addListener("selectionchange", function() { - //只存在于右键菜单而无工具栏按钮的ui不需要检测状态 - var unNeedCheckState = { edittable: 1 }; - if (cmd in unNeedCheckState) return; - var state = editor.queryCommandState(cmd); - if (ui.getDom()) { - ui.setDisabled(state == -1); - ui.setChecked(state); - } + editor.addListener("selectionchange", function () { + ui.setDisabled(editor.queryCommandState(cmd) == -1); }); - return ui; - }; - })(ci.toLowerCase()); - } - })(p, dialogBtns[p]); - } + }; - editorui.insertcode = function(editor, list, title) { - list = editor.options["insertcode"] || []; - title = - editor.options.labelMap["insertcode"] || - editor.getLang("labelMap.insertcode") || - ""; - // if (!list.length) return; - var items = []; - utils.each(list, function(key, val) { - items.push({ - label: key, - value: val, - theme: editor.options.theme, - renderLabelHtml: function() { - return ( - '
    ' + (this.label || "") + "
    " - ); - } - }); - }); + editorui['autotypeset'] = function (editor) { + var ui = new editorui.AutoTypeSetButton({ + editor: editor, + title: + editor.options.labelMap["autotypeset"] || + editor.getLang("labelMap.autotypeset") || + "", + className: "edui-for-autotypeset", + onbuttonclick: function () { + editor.execCommand("autotypeset"); + } + }); + editorui.buttons["autotypeset"] = ui; + editor.addListener("selectionchange", function () { + ui.setDisabled(editor.queryCommandState("autotypeset") == -1); + }); + return ui; + }; - var ui = new editorui.Combox({ - editor: editor, - items: items, - onselect: function(t, index) { - editor.execCommand("insertcode", this.items[index].value); - }, - onbuttonclick: function() { - this.showPopup(); - }, - title: title, - initValue: title, - className: "edui-for-insertcode", - indexByValue: function(value) { - if (value) { - for (var i = 0, ci; (ci = this.items[i]); i++) { - if (ci.value.indexOf(value) != -1) return i; - } - } + /* 简单上传插件 */ + editorui['simpleupload'] = function (editor) { + var name = "simpleupload", + ui = new editorui.Button({ + className: "edui-for-" + name, + title: + editor.options.labelMap[name] || + editor.getLang("labelMap." + name) || + "", + onclick: function () { + }, + theme: editor.options.theme, + showText: false + }); + editorui.buttons[name] = ui; + editor.addListener("ready", function () { + var b = ui.getDom("body"), + iconSpan = b.children[0]; + editor.fireEvent("simpleuploadbtnready", iconSpan); + }); + editor.addListener("selectionchange", function (type, causeByUi, uiReady) { + var state = editor.queryCommandState(name); + if (state == -1) { + ui.setDisabled(true); + ui.setChecked(false); + } else { + if (!uiReady) { + ui.setDisabled(false); + ui.setChecked(state); + } + } + }); + return ui; + }; - return -1; - } - }); - editorui.buttons["insertcode"] = ui; - editor.addListener("selectionchange", function(type, causeByUi, uiReady) { - if (!uiReady) { - var state = editor.queryCommandState("insertcode"); - if (state == -1) { - ui.setDisabled(true); - } else { - ui.setDisabled(false); - var value = editor.queryCommandValue("insertcode"); - if (!value) { - ui.setValue(title); - return; - } - //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号 - value && (value = value.replace(/['"]/g, "").split(",")[0]); - ui.setValue(value); - } - } - }); - return ui; - }; - editorui.fontfamily = function(editor, list, title) { - list = editor.options["fontfamily"] || []; - title = - editor.options.labelMap["fontfamily"] || - editor.getLang("labelMap.fontfamily") || - ""; - if (!list.length) return; - for (var i = 0, ci, items = []; (ci = list[i]); i++) { - var langLabel = editor.getLang("fontfamily")[ci.name] || ""; - (function(key, val) { - items.push({ - label: key, - value: val, - theme: editor.options.theme, - renderLabelHtml: function() { - return ( - '
    ' + - (this.label || "") + - "
    " - ); - } - }); - })(ci.label || langLabel, ci.val); - } - var ui = new editorui.Combox({ - editor: editor, - items: items, - onselect: function(t, index) { - editor.execCommand("FontFamily", this.items[index].value); - }, - onbuttonclick: function() { - this.showPopup(); - }, - title: title, - initValue: title, - className: "edui-for-fontfamily", - indexByValue: function(value) { - if (value) { - for (var i = 0, ci; (ci = this.items[i]); i++) { - if (ci.value.indexOf(value) != -1) return i; - } - } - return -1; - } - }); - editorui.buttons["fontfamily"] = ui; - editor.addListener("selectionchange", function(type, causeByUi, uiReady) { - if (!uiReady) { - var state = editor.queryCommandState("FontFamily"); - if (state == -1) { - ui.setDisabled(true); - } else { - ui.setDisabled(false); - var value = editor.queryCommandValue("FontFamily"); - //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号 - value && (value = value.replace(/['"]/g, "").split(",")[0]); - ui.setValue(value); - } - } - }); - return ui; - }; - - editorui.fontsize = function(editor, list, title) { - title = - editor.options.labelMap["fontsize"] || - editor.getLang("labelMap.fontsize") || - ""; - list = list || editor.options["fontsize"] || []; - if (!list.length) return; - var items = []; - for (var i = 0; i < list.length; i++) { - var size = list[i] + "px"; - items.push({ - label: size, - value: size, - theme: editor.options.theme, - renderLabelHtml: function() { - return ( - '
    ' + - (this.label || "") + - "
    " - ); - } - }); - } - var ui = new editorui.Combox({ - editor: editor, - items: items, - title: title, - initValue: title, - onselect: function(t, index) { - editor.execCommand("FontSize", this.items[index].value); - }, - onbuttonclick: function() { - this.showPopup(); - }, - className: "edui-for-fontsize" - }); - editorui.buttons["fontsize"] = ui; - editor.addListener("selectionchange", function(type, causeByUi, uiReady) { - if (!uiReady) { - var state = editor.queryCommandState("FontSize"); - if (state == -1) { - ui.setDisabled(true); - } else { - ui.setDisabled(false); - ui.setValue(editor.queryCommandValue("FontSize")); - } - } - }); - return ui; - }; - - editorui.paragraph = function(editor, list, title) { - title = - editor.options.labelMap["paragraph"] || - editor.getLang("labelMap.paragraph") || - ""; - list = editor.options["paragraph"] || []; - if (utils.isEmptyObject(list)) return; - var items = []; - for (var i in list) { - items.push({ - value: i, - label: list[i] || editor.getLang("paragraph")[i], - theme: editor.options.theme, - renderLabelHtml: function() { - return ( - '
    ' + - (this.label || "") + - "
    " - ); - } - }); - } - var ui = new editorui.Combox({ - editor: editor, - items: items, - title: title, - initValue: title, - className: "edui-for-paragraph", - onselect: function(t, index) { - editor.execCommand("Paragraph", this.items[index].value); - }, - onbuttonclick: function() { - this.showPopup(); - } - }); - editorui.buttons["paragraph"] = ui; - editor.addListener("selectionchange", function(type, causeByUi, uiReady) { - if (!uiReady) { - var state = editor.queryCommandState("Paragraph"); - if (state == -1) { - ui.setDisabled(true); - } else { - ui.setDisabled(false); - var value = editor.queryCommandValue("Paragraph"); - var index = ui.indexByValue(value); - if (index != -1) { - ui.setValue(value); - } else { - ui.setValue(ui.initValue); - } - } - } - }); - return ui; - }; - - //自定义标题 - editorui.customstyle = function(editor) { - var list = editor.options["customstyle"] || [], - title = - editor.options.labelMap["customstyle"] || - editor.getLang("labelMap.customstyle") || - ""; - if (!list.length) return; - var langCs = editor.getLang("customstyle"); - for (var i = 0, items = [], t; (t = list[i++]); ) { - (function(t) { - var ck = {}; - ck.label = t.label ? t.label : langCs[t.name]; - ck.style = t.style; - ck.className = t.className; - ck.tag = t.tag; - items.push({ - label: ck.label, - value: ck, - theme: editor.options.theme, - renderLabelHtml: function() { - return ( - '
    ' + - "<" + - ck.tag + - " " + - (ck.className ? ' class="' + ck.className + '"' : "") + - (ck.style ? ' style="' + ck.style + '"' : "") + - ">" + - ck.label + - "" + - "
    " - ); - } - }); - })(t); - } - - var ui = new editorui.Combox({ - editor: editor, - items: items, - title: title, - initValue: title, - className: "edui-for-customstyle", - onselect: function(t, index) { - editor.execCommand("customstyle", this.items[index].value); - }, - onbuttonclick: function() { - this.showPopup(); - }, - indexByValue: function(value) { - for (var i = 0, ti; (ti = this.items[i++]); ) { - if (ti.label == value) { - return i - 1; - } - } - return -1; - } - }); - editorui.buttons["customstyle"] = ui; - editor.addListener("selectionchange", function(type, causeByUi, uiReady) { - if (!uiReady) { - var state = editor.queryCommandState("customstyle"); - if (state == -1) { - ui.setDisabled(true); - } else { - ui.setDisabled(false); - var value = editor.queryCommandValue("customstyle"); - var index = ui.indexByValue(value); - if (index != -1) { - ui.setValue(value); - } else { - ui.setValue(ui.initValue); - } - } - } - }); - return ui; - }; - editorui.inserttable = function(editor, iframeUrl, title) { - title = - editor.options.labelMap["inserttable"] || - editor.getLang("labelMap.inserttable") || - ""; - var ui = new editorui.TableButton({ - editor: editor, - title: title, - className: "edui-for-inserttable", - onpicktable: function(t, numCols, numRows) { - editor.execCommand("InsertTable", { - numRows: numRows, - numCols: numCols, - border: 1 - }); - }, - onbuttonclick: function() { - this.showPopup(); - } - }); - editorui.buttons["inserttable"] = ui; - editor.addListener("selectionchange", function() { - ui.setDisabled(editor.queryCommandState("inserttable") == -1); - }); - return ui; - }; - - editorui.lineheight = function(editor) { - var val = editor.options.lineheight || []; - if (!val.length) return; - for (var i = 0, ci, items = []; (ci = val[i++]); ) { - items.push({ - //todo:写死了 - label: ci, - value: ci, - theme: editor.options.theme, - onclick: function() { - editor.execCommand("lineheight", this.value); - } - }); - } - var ui = new editorui.MenuButton({ - editor: editor, - className: "edui-for-lineheight", - title: - editor.options.labelMap["lineheight"] || - editor.getLang("labelMap.lineheight") || - "", - items: items, - onbuttonclick: function() { - var value = editor.queryCommandValue("LineHeight") || this.value; - editor.execCommand("LineHeight", value); - } - }); - editorui.buttons["lineheight"] = ui; - editor.addListener("selectionchange", function() { - var state = editor.queryCommandState("LineHeight"); - if (state == -1) { - ui.setDisabled(true); - } else { - ui.setDisabled(false); - var value = editor.queryCommandValue("LineHeight"); - value && ui.setValue((value + "").replace(/cm/, "")); - ui.setChecked(state); - } - }); - return ui; - }; - - var rowspacings = ["top", "bottom"]; - for (var r = 0, ri; (ri = rowspacings[r++]); ) { - (function(cmd) { - editorui["rowspacing" + cmd] = function(editor) { - var val = editor.options["rowspacing" + cmd] || []; - if (!val.length) return null; - for (var i = 0, ci, items = []; (ci = val[i++]); ) { - items.push({ - label: ci, - value: ci, - theme: editor.options.theme, - onclick: function() { - editor.execCommand("rowspacing", this.value, cmd); - } - }); - } - var ui = new editorui.MenuButton({ - editor: editor, - className: "edui-for-rowspacing" + cmd, - title: - editor.options.labelMap["rowspacing" + cmd] || - editor.getLang("labelMap.rowspacing" + cmd) || - "", - items: items, - onbuttonclick: function() { - var value = - editor.queryCommandValue("rowspacing", cmd) || this.value; - editor.execCommand("rowspacing", value, cmd); - } - }); - editorui.buttons[cmd] = ui; - editor.addListener("selectionchange", function() { - var state = editor.queryCommandState("rowspacing", cmd); - if (state == -1) { - ui.setDisabled(true); - } else { - ui.setDisabled(false); - var value = editor.queryCommandValue("rowspacing", cmd); - value && ui.setValue((value + "").replace(/%/, "")); - ui.setChecked(state); - } - }); - return ui; - }; - })(ri); - } - //有序,无序列表 - var lists = ["insertorderedlist", "insertunorderedlist"]; - for (var l = 0, cl; (cl = lists[l++]); ) { - (function(cmd) { - editorui[cmd] = function(editor) { - var vals = editor.options[cmd], - _onMenuClick = function() { - editor.execCommand(cmd, this.value); - }, - items = []; - for (var i in vals) { - items.push({ - label: vals[i] || editor.getLang()[cmd][i] || "", - value: i, - theme: editor.options.theme, - onclick: _onMenuClick - }); - } - var ui = new editorui.MenuButton({ - editor: editor, - className: "edui-for-" + cmd, - title: editor.getLang("labelMap." + cmd) || "", - items: items, - onbuttonclick: function() { - var value = editor.queryCommandValue(cmd) || this.value; - editor.execCommand(cmd, value); - } - }); - editorui.buttons[cmd] = ui; - editor.addListener("selectionchange", function() { - var state = editor.queryCommandState(cmd); - if (state == -1) { - ui.setDisabled(true); - } else { - ui.setDisabled(false); - var value = editor.queryCommandValue(cmd); - ui.setValue(value); - ui.setChecked(state); - } - }); - return ui; - }; - })(cl); - } - - editorui.fullscreen = function(editor, title) { - title = - editor.options.labelMap["fullscreen"] || - editor.getLang("labelMap.fullscreen") || - ""; - var ui = new editorui.Button({ - className: "edui-for-fullscreen", - title: title, - theme: editor.options.theme, - onclick: function() { - if (editor.ui) { - editor.ui.setFullScreen(!editor.ui.isFullScreen()); - } - this.setChecked(editor.ui.isFullScreen()); - } - }); - editorui.buttons["fullscreen"] = ui; - editor.addListener("selectionchange", function() { - var state = editor.queryCommandState("fullscreen"); - ui.setDisabled(state == -1); - ui.setChecked(editor.ui.isFullScreen()); - }); - return ui; - }; - - // 表情 - editorui["emotion"] = function(editor, iframeUrl) { - var cmd = "emotion"; - var ui = new editorui.MultiMenuPop({ - title: - editor.options.labelMap[cmd] || - editor.getLang("labelMap." + cmd + "") || - "", - editor: editor, - className: "edui-for-" + cmd, - iframeUrl: editor.ui.mapUrl( - iframeUrl || - (editor.options.iframeUrlMap || {})[cmd] || - iframeUrlMap[cmd] - ) - }); - editorui.buttons[cmd] = ui; - - editor.addListener("selectionchange", function() { - ui.setDisabled(editor.queryCommandState(cmd) == -1); - }); - return ui; - }; - - editorui.autotypeset = function(editor) { - var ui = new editorui.AutoTypeSetButton({ - editor: editor, - title: - editor.options.labelMap["autotypeset"] || - editor.getLang("labelMap.autotypeset") || - "", - className: "edui-for-autotypeset", - onbuttonclick: function() { - editor.execCommand("autotypeset"); - } - }); - editorui.buttons["autotypeset"] = ui; - editor.addListener("selectionchange", function() { - ui.setDisabled(editor.queryCommandState("autotypeset") == -1); - }); - return ui; - }; - - /* 简单上传插件 */ - editorui["simpleupload"] = function(editor) { - var name = "simpleupload", - ui = new editorui.Button({ - className: "edui-for-" + name, - title: - editor.options.labelMap[name] || - editor.getLang("labelMap." + name) || - "", - onclick: function() {}, - theme: editor.options.theme, - showText: false - }); - editorui.buttons[name] = ui; - editor.addListener("ready", function() { - var b = ui.getDom("body"), - iconSpan = b.children[0]; - editor.fireEvent("simpleuploadbtnready", iconSpan); - }); - editor.addListener("selectionchange", function(type, causeByUi, uiReady) { - var state = editor.queryCommandState(name); - if (state == -1) { - ui.setDisabled(true); - ui.setChecked(false); - } else { - if (!uiReady) { - ui.setDisabled(false); - ui.setChecked(state); - } - } - }); - return ui; - }; -})(); + })(); // adapter/editor.js @@ -32043,1079 +35570,1079 @@ UE.ui = baidu.editor.ui = {}; ///commands 全屏 ///commandsName FullScreen ///commandsTitle 全屏 -(function () { - var utils = baidu.editor.utils, - uiUtils = baidu.editor.ui.uiUtils, - UIBase = baidu.editor.ui.UIBase, - domUtils = baidu.editor.dom.domUtils; - var nodeStack = []; + (function () { + var utils = baidu.editor.utils, + uiUtils = baidu.editor.ui.uiUtils, + UIBase = baidu.editor.ui.UIBase, + domUtils = baidu.editor.dom.domUtils; + var nodeStack = []; - function EditorUI(options) { - this.initOptions(options); - this.initEditorUI(); - } - - EditorUI.prototype = { - uiName: "editor", - initEditorUI: function () { - this.editor.ui = this; - this._dialogs = {}; - this.initUIBase(); - this._initToolbars(); - var editor = this.editor, - me = this; - - editor.addListener("ready", function () { - //提供getDialog方法 - editor.getDialog = function (name) { - return editor.ui._dialogs[name + "Dialog"]; - }; - domUtils.on(editor.window, "scroll", function (evt) { - baidu.editor.ui.Popup.postHide(evt); - }); - //提供编辑器实时宽高(全屏时宽高不变化) - editor.ui._actualFrameWidth = editor.options.initialFrameWidth; - - UE.browser.ie && - UE.browser.version === 6 && - editor.container.ownerDocument.execCommand( - "BackgroundImageCache", - false, - true - ); - - //display bottom-bar label based on config - if (editor.options.elementPathEnabled) { - editor.ui.getDom("elementpath").innerHTML = - '
    ' + - editor.getLang("elementPathTip") + - ":
    "; - } - if (editor.options.wordCount) { - function countFn() { - setCount(editor, me); - domUtils.un(editor.document, "click", arguments.callee); - } - - domUtils.on(editor.document, "click", countFn); - editor.ui.getDom("wordcount").innerHTML = editor.getLang( - "wordCountTip" - ); - } - editor.ui._scale(); - if (editor.options.scaleEnabled) { - if (editor.autoHeightEnabled) { - editor.disableAutoHeight(); - } - me.enableScale(); - } else { - me.disableScale(); - } - if ( - !editor.options.elementPathEnabled && - !editor.options.wordCount && - !editor.options.scaleEnabled - ) { - editor.ui.getDom("elementpath").style.display = "none"; - editor.ui.getDom("wordcount").style.display = "none"; - editor.ui.getDom("scale").style.display = "none"; + function EditorUI(options) { + this.initOptions(options); + this.initEditorUI(); } - if (!editor.selection.isFocus()) return; - editor.fireEvent("selectionchange", false, true); - }); + EditorUI.prototype = { + uiName: "editor", + initEditorUI: function () { + this.editor.ui = this; + this._dialogs = {}; + this.initUIBase(); + this._initToolbars(); + var editor = this.editor, + me = this; - editor.addListener("mousedown", function (t, evt) { - var el = evt.target || evt.srcElement; - baidu.editor.ui.Popup.postHide(evt, el); - baidu.editor.ui.ShortCutMenu.postHide(evt); - }); - editor.addListener("delcells", function () { - if (UE.ui["edittip"]) { - new UE.ui["edittip"](editor); - } - editor.getDialog("edittip").open(); - }); - - var pastePop, - isPaste = false, - timer; - editor.addListener("afterpaste", function () { - if (editor.queryCommandState("pasteplain")) return; - if (baidu.editor.ui.PastePicker) { - pastePop = new baidu.editor.ui.Popup({ - content: new baidu.editor.ui.PastePicker({editor: editor}), - editor: editor, - className: "edui-wordpastepop" - }); - pastePop.render(); - } - isPaste = true; - }); - - editor.addListener("afterinserthtml", function () { - clearTimeout(timer); - timer = setTimeout(function () { - if (pastePop && (isPaste || editor.ui._isTransfer)) { - if (pastePop.isHidden()) { - var span = domUtils.createElement(editor.document, "span", { - style: "line-height:0px;", - innerHTML: "\ufeff" - }), - range = editor.selection.getRange(); - range.insertNode(span); - var tmp = getDomNode(span, "firstChild", "previousSibling"); - tmp && - pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp); - domUtils.remove(span); - } else { - pastePop.show(); - } - delete editor.ui._isTransfer; - isPaste = false; - } - }, 200); - }); - editor.addListener("contextmenu", function (t, evt) { - baidu.editor.ui.Popup.postHide(evt); - }); - editor.addListener("keydown", function (t, evt) { - if (pastePop) pastePop.dispose(evt); - var keyCode = evt.keyCode || evt.which; - if (evt.altKey && keyCode == 90) { - UE.ui.buttons["fullscreen"].onclick(); - } - }); - editor.addListener("wordcount", function (type) { - setCount(this, me); - }); - - function setCount(editor, ui) { - editor.setOpt({ - wordCount: true, - maximumWords: 10000, - wordCountMsg: - editor.options.wordCountMsg || editor.getLang("wordCountMsg"), - wordOverFlowMsg: - editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg") - }); - var opt = editor.options, - max = opt.maximumWords, - msg = opt.wordCountMsg, - errMsg = opt.wordOverFlowMsg, - countDom = ui.getDom("wordcount"); - if (!opt.wordCount) { - return; - } - var count = editor.getContentLength(true); - if (count > max) { - countDom.innerHTML = errMsg; - editor.fireEvent("wordcountoverflow"); - } else { - countDom.innerHTML = msg - .replace("{#leave}", max - count) - .replace("{#count}", count); - } - } - - editor.addListener("selectionchange", function () { - if (editor.options.elementPathEnabled) { - me[ - (editor.queryCommandState("elementpath") == -1 ? "dis" : "en") + - "ableElementPath" - ](); - } - if (editor.options.scaleEnabled) { - me[ - (editor.queryCommandState("scale") == -1 ? "dis" : "en") + - "ableScale" - ](); - } - }); - var popup = new baidu.editor.ui.Popup({ - editor: editor, - content: "", - className: "edui-bubble", - _onEditButtonClick: function () { - this.hide(); - editor.ui._dialogs.linkDialog.open(); - }, - _onImgEditButtonClick: function (name) { - this.hide(); - editor.ui._dialogs[name] && editor.ui._dialogs[name].open(); - }, - _onImgSetFloat: function (value) { - this.hide(); - editor.execCommand("imagefloat", value); - }, - _setIframeAlign: function (value) { - var frame = popup.anchorEl; - var newFrame = frame.cloneNode(true); - switch (value) { - case -2: - newFrame.setAttribute("align", ""); - break; - case -1: - newFrame.setAttribute("align", "left"); - break; - case 1: - newFrame.setAttribute("align", "right"); - break; - } - frame.parentNode.insertBefore(newFrame, frame); - domUtils.remove(frame); - popup.anchorEl = newFrame; - popup.showAnchor(popup.anchorEl); - }, - _updateIframe: function () { - var frame = (editor._iframe = popup.anchorEl); - if (domUtils.hasClass(frame, "ueditor_baidumap")) { - editor.selection.getRange().selectNode(frame).select(); - editor.ui._dialogs.mapDialog.open(); - popup.hide(); - } else { - editor.ui._dialogs.insertframeDialog.open(); - popup.hide(); - } - }, - _onRemoveButtonClick: function (cmdName) { - editor.execCommand(cmdName); - this.hide(); - }, - queryAutoHide: function (el) { - if (el && el.ownerDocument == editor.document) { - if ( - el.tagName.toLowerCase() == "img" || - domUtils.findParentByTagName(el, "a", true) - ) { - return el !== popup.anchorEl; - } - } - return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el); - } - }); - popup.render(); - if (editor.options.imagePopup) { - editor.addListener("mouseover", function (t, evt) { - evt = evt || window.event; - var el = evt.target || evt.srcElement; - if ( - editor.ui._dialogs.insertframeDialog && - /iframe/gi.test(el.tagName) - ) { - var html = popup.formatHtml( - "" + - '' + - editor.getLang("default") + - '  ' + - editor.getLang("justifyleft") + - '  ' + - editor.getLang("justifyright") + - "  " + - ' ' + - editor.getLang("modify") + - "" - ); - if (html) { - popup.getDom("content").innerHTML = html; - popup.anchorEl = el; - popup.showAnchor(popup.anchorEl); - } else { - popup.hide(); - } - } - }); - editor.addListener("selectionchange", function (t, causeByUi) { - if (!causeByUi) return; - var html = "", - str = "", - img = editor.selection.getRange().getClosedNode(), - dialogs = editor.ui._dialogs; - if (img && img.tagName == "IMG") { - var dialogName = "insertimageDialog"; - if ( - img.className.indexOf("edui-faked-video") != -1 || - img.className.indexOf("edui-upload-video") != -1 - ) { - dialogName = "insertvideoDialog"; - } - if ( - img.className.indexOf("edui-faked-audio") != -1 || - img.className.indexOf("edui-upload-audio") != -1 - ) { - dialogName = "insertaudioDialog"; - } - if (img.getAttribute("anchorname")) { - dialogName = "anchorDialog"; - html = popup.formatHtml( - "" + - '' + - editor.getLang("modify") + - "  " + - "" + - editor.getLang("delete") + - "" - ); - } - // if (img.getAttribute("data-word-image")) { - // //todo 放到dialog去做查询 - // editor['data-word-image'] = [img.getAttribute("data-word-image")]; - // dialogName = "wordimageDialog"; - // } - if ( - domUtils.hasClass(img, "loadingclass") || - domUtils.hasClass(img, "loaderrorclass") - ) { - dialogName = ""; - } - if (!dialogs[dialogName]) { - return; - } - - var actions = []; - actions.push(''); - actions.push('' + - editor.getLang("default") + - ""); - actions.push('' + - editor.getLang("justifyleft") + - ""); - actions.push('' + - editor.getLang("justifyright") + - ""); - actions.push('' + - editor.getLang("justifycenter") + - ""); - if (img.getAttribute('data-formula-image') !== null) { - actions.push("" + - editor.getLang("formulaedit") + ""); - } - if (img.getAttribute("data-word-image")) { - actions.push("" + - editor.getLang("save") + - ""); - } else { - actions.push("' + - editor.getLang("modify") + - ""); - } - actions.push(""); - - !html && (html = popup.formatHtml(actions.join(""))); - } - if (editor.ui._dialogs.linkDialog) { - var link = editor.queryCommandValue("link"); - var url; - if ( - link && - (url = link.getAttribute("_href") || link.getAttribute("href", 2)) - ) { - var txt = url; - if (url.length > 30) { - txt = url.substring(0, 20) + "..."; - } - if (html) { - html += '
    '; - } - html += popup.formatHtml( - "" + - editor.getLang("anchorMsg") + - ': ' + - txt + - "" + - ' ' + - editor.getLang("modify") + - "" + - ' ' + - editor.getLang("clear") + - "" - ); - popup.showAnchor(link); - } - } - - if (html) { - popup.getDom("content").innerHTML = html; - popup.anchorEl = img || link; - popup.showAnchor(popup.anchorEl); - } else { - popup.hide(); - } - }); - } - }, - _initToolbars: function () { - var editor = this.editor; - var toolbars = this.toolbars || []; - if(toolbars[0]){ - toolbars[0].unshift( - 'message' - ); - } - var toolbarUis = []; - var extraUIs = []; - for (var i = 0; i < toolbars.length; i++) { - var toolbar = toolbars[i]; - var toolbarUi = new baidu.editor.ui.Toolbar({ - theme: editor.options.theme - }); - for (var j = 0; j < toolbar.length; j++) { - var toolbarItem = toolbar[j]; - var toolbarItemUi = null; - if (typeof toolbarItem == "string") { - toolbarItem = toolbarItem.toLowerCase(); - if (toolbarItem === "|") { - toolbarItem = "Separator"; - } - if (toolbarItem === "||") { - toolbarItem = "Breakline"; - } - var ui = baidu.editor.ui[toolbarItem]; - if (ui) { - if (utils.isFunction(ui)) { - toolbarItemUi = new baidu.editor.ui[toolbarItem](editor); - } else { - if (ui.id && ui.id !== editor.key) { - continue; - } - var itemUI = ui.execFn.call(editor, editor, toolbarItem); - if (itemUI) { - if (ui.index === undefined) { - toolbarUi.add(itemUI); - continue; - } else { - extraUIs.push({ - index: ui.index, - itemUI: itemUI + editor.addListener("ready", function () { + //提供getDialog方法 + editor.getDialog = function (name) { + return editor.ui._dialogs[name + "Dialog"]; + }; + domUtils.on(editor.window, "scroll", function (evt) { + baidu.editor.ui.Popup.postHide(evt); }); - } + //提供编辑器实时宽高(全屏时宽高不变化) + editor.ui._actualFrameWidth = editor.options.initialFrameWidth; + + UE.browser.ie && + UE.browser.version === 6 && + editor.container.ownerDocument.execCommand( + "BackgroundImageCache", + false, + true + ); + + //display bottom-bar label based on config + if (editor.options.elementPathEnabled) { + editor.ui.getDom("elementpath").innerHTML = + '
    ' + + editor.getLang("elementPathTip") + + ":
    "; + } + if (editor.options.wordCount) { + function countFn() { + setCount(editor, me); + domUtils.un(editor.document, "click", arguments.callee); + } + + domUtils.on(editor.document, "click", countFn); + editor.ui.getDom("wordcount").innerHTML = editor.getLang( + "wordCountTip" + ); + } + editor.ui._scale(); + if (editor.options.scaleEnabled) { + if (editor.autoHeightEnabled) { + editor.disableAutoHeight(); + } + me.enableScale(); + } else { + me.disableScale(); + } + if ( + !editor.options.elementPathEnabled && + !editor.options.wordCount && + !editor.options.scaleEnabled + ) { + editor.ui.getDom("elementpath").style.display = "none"; + editor.ui.getDom("wordcount").style.display = "none"; + editor.ui.getDom("scale").style.display = "none"; + } + + if (!editor.selection.isFocus()) return; + editor.fireEvent("selectionchange", false, true); + }); + + editor.addListener("mousedown", function (t, evt) { + var el = evt.target || evt.srcElement; + baidu.editor.ui.Popup.postHide(evt, el); + baidu.editor.ui.ShortCutMenu.postHide(evt); + }); + + editor.addListener("delcells", function () { + if (UE.ui["edittip"]) { + new UE.ui["edittip"](editor); + } + editor.getDialog("edittip").open(); + }); + + var pastePop, + isPaste = false, + timer; + editor.addListener("afterpaste", function () { + if (editor.queryCommandState("pasteplain")) return; + if (baidu.editor.ui.PastePicker) { + pastePop = new baidu.editor.ui.Popup({ + content: new baidu.editor.ui.PastePicker({editor: editor}), + editor: editor, + className: "edui-wordpastepop" + }); + pastePop.render(); + } + isPaste = true; + }); + + editor.addListener("afterinserthtml", function () { + clearTimeout(timer); + timer = setTimeout(function () { + if (pastePop && (isPaste || editor.ui._isTransfer)) { + if (pastePop.isHidden()) { + var span = domUtils.createElement(editor.document, "span", { + style: "line-height:0px;", + innerHTML: "\ufeff" + }), + range = editor.selection.getRange(); + range.insertNode(span); + var tmp = getDomNode(span, "firstChild", "previousSibling"); + tmp && + pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp); + domUtils.remove(span); + } else { + pastePop.show(); + } + delete editor.ui._isTransfer; + isPaste = false; + } + }, 200); + }); + editor.addListener("contextmenu", function (t, evt) { + baidu.editor.ui.Popup.postHide(evt); + }); + editor.addListener("keydown", function (t, evt) { + if (pastePop) pastePop.dispose(evt); + var keyCode = evt.keyCode || evt.which; + if (evt.altKey && keyCode == 90) { + UE.ui.buttons["fullscreen"].onclick(); + } + }); + editor.addListener("wordcount", function (type) { + setCount(this, me); + }); + + function setCount(editor, ui) { + editor.setOpt({ + wordCount: true, + maximumWords: 10000, + wordCountMsg: + editor.options.wordCountMsg || editor.getLang("wordCountMsg"), + wordOverFlowMsg: + editor.options.wordOverFlowMsg || editor.getLang("wordOverFlowMsg") + }); + var opt = editor.options, + max = opt.maximumWords, + msg = opt.wordCountMsg, + errMsg = opt.wordOverFlowMsg, + countDom = ui.getDom("wordcount"); + if (!opt.wordCount) { + return; + } + var count = editor.getContentLength(true); + if (count > max) { + countDom.innerHTML = errMsg; + editor.fireEvent("wordcountoverflow"); + } else { + countDom.innerHTML = msg + .replace("{#leave}", max - count) + .replace("{#count}", count); + } + } + + editor.addListener("selectionchange", function () { + if (editor.options.elementPathEnabled) { + me[ + (editor.queryCommandState("elementpath") == -1 ? "dis" : "en") + + "ableElementPath" + ](); + } + if (editor.options.scaleEnabled) { + me[ + (editor.queryCommandState("scale") == -1 ? "dis" : "en") + + "ableScale" + ](); + } + }); + var popup = new baidu.editor.ui.Popup({ + editor: editor, + content: "", + className: "edui-bubble", + _onEditButtonClick: function () { + this.hide(); + editor.ui._dialogs.linkDialog.open(); + }, + _onImgEditButtonClick: function (name) { + this.hide(); + editor.ui._dialogs[name] && editor.ui._dialogs[name].open(); + }, + _onImgSetFloat: function (value) { + this.hide(); + editor.execCommand("imagefloat", value); + }, + _setIframeAlign: function (value) { + var frame = popup.anchorEl; + var newFrame = frame.cloneNode(true); + switch (value) { + case -2: + newFrame.setAttribute("align", ""); + break; + case -1: + newFrame.setAttribute("align", "left"); + break; + case 1: + newFrame.setAttribute("align", "right"); + break; + } + frame.parentNode.insertBefore(newFrame, frame); + domUtils.remove(frame); + popup.anchorEl = newFrame; + popup.showAnchor(popup.anchorEl); + }, + _updateIframe: function () { + var frame = (editor._iframe = popup.anchorEl); + if (domUtils.hasClass(frame, "ueditor_baidumap")) { + editor.selection.getRange().selectNode(frame).select(); + editor.ui._dialogs.mapDialog.open(); + popup.hide(); + } else { + editor.ui._dialogs.insertframeDialog.open(); + popup.hide(); + } + }, + _onRemoveButtonClick: function (cmdName) { + editor.execCommand(cmdName); + this.hide(); + }, + queryAutoHide: function (el) { + if (el && el.ownerDocument == editor.document) { + if ( + el.tagName.toLowerCase() == "img" || + domUtils.findParentByTagName(el, "a", true) + ) { + return el !== popup.anchorEl; + } + } + return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el); + } + }); + popup.render(); + if (editor.options.imagePopup) { + editor.addListener("mouseover", function (t, evt) { + evt = evt || window.event; + var el = evt.target || evt.srcElement; + if ( + editor.ui._dialogs.insertframeDialog && + /iframe/gi.test(el.tagName) + ) { + var html = popup.formatHtml( + "" + + '' + + editor.getLang("default") + + '  ' + + editor.getLang("justifyleft") + + '  ' + + editor.getLang("justifyright") + + "  " + + ' ' + + editor.getLang("modify") + + "" + ); + if (html) { + popup.getDom("content").innerHTML = html; + popup.anchorEl = el; + popup.showAnchor(popup.anchorEl); + } else { + popup.hide(); + } + } + }); + editor.addListener("selectionchange", function (t, causeByUi) { + if (!causeByUi) { + return; + } + var html = "", + str = "", + closedNode = editor.selection.getRange().getClosedNode(), + dialogs = editor.ui._dialogs; + // 图片选中处理 + if (closedNode && closedNode.tagName === "IMG") { + var dialogName = "insertimageDialog"; + if ( + closedNode.className.indexOf("edui-faked-video") !== -1 || + closedNode.className.indexOf("edui-upload-video") !== -1 + ) { + dialogName = "insertvideoDialog"; + } + if ( + closedNode.className.indexOf("edui-faked-audio") !== -1 || + closedNode.className.indexOf("edui-upload-audio") !== -1 + ) { + dialogName = "insertaudioDialog"; + } + if (closedNode.getAttribute("anchorname")) { + dialogName = "anchorDialog"; + html = popup.formatHtml( + "" + + '' + + editor.getLang("modify") + + "  " + + "" + + editor.getLang("delete") + + "" + ); + } + // if (img.getAttribute("data-word-image")) { + // //todo 放到dialog去做查询 + // editor['data-word-image'] = [img.getAttribute("data-word-image")]; + // dialogName = "wordimageDialog"; + // } + if ( + domUtils.hasClass(closedNode, "uep-loading") || + domUtils.hasClass(closedNode, "uep-loading-error") + ) { + dialogName = ""; + } + if (!dialogs[dialogName]) { + return; + } + + var actions = []; + if (closedNode.getAttribute("data-word-image")) { + actions.push("" + + editor.getLang("save") + + ""); + } else { + // actions.push("' + + // editor.getLang("modify") + + // ""); + } + + if (actions.length > 0) { + // wrap with + actions.unshift(''); + actions.push(''); + } + + !html && (html = popup.formatHtml(actions.join(""))); + } + // 链接选中处理 + if (editor.ui._dialogs.linkDialog) { + var link = editor.queryCommandValue("link"); + var url; + if ( + link && + (url = link.getAttribute("_href") || link.getAttribute("href", 2)) + ) { + var txt = url; + if (url.length > 30) { + txt = url.substring(0, 20) + "..."; + } + if (html) { + html += '
    '; + } + html += popup.formatHtml( + "" + + editor.getLang("anchorMsg") + + ': ' + + txt + + "" + + ' ' + + editor.getLang("modify") + + "" + + ' ' + + editor.getLang("clear") + + "" + ); + popup.showAnchor(link); + } + } + + if (html) { + popup.getDom("content").innerHTML = html; + popup.anchorEl = closedNode || link; + popup.showAnchor(popup.anchorEl); + } else { + popup.hide(); + } + }); + } + }, + _initToolbars: function () { + var editor = this.editor; + var toolbars = this.toolbars || []; + if (toolbars[0]) { + toolbars[0].unshift( + 'message' + ); + } + var toolbarUis = []; + var extraUIs = []; + for (var i = 0; i < toolbars.length; i++) { + var toolbar = toolbars[i]; + var toolbarUi = new baidu.editor.ui.Toolbar({ + theme: editor.options.theme + }); + for (var j = 0; j < toolbar.length; j++) { + var toolbarItem = toolbar[j]; + var toolbarItemUi = null; + if (typeof toolbarItem == "string") { + toolbarItem = toolbarItem.toLowerCase(); + if (toolbarItem === "|") { + toolbarItem = "Separator"; + } + if (toolbarItem === "||") { + toolbarItem = "Breakline"; + } + var ui = baidu.editor.ui[toolbarItem]; + if (ui) { + if (utils.isFunction(ui)) { + toolbarItemUi = new baidu.editor.ui[toolbarItem](editor); + } else { + if (ui.id && ui.id !== editor.key) { + continue; + } + var itemUI = ui.execFn.call(editor, editor, toolbarItem); + if (itemUI) { + if (ui.index === undefined) { + toolbarUi.add(itemUI); + continue; + } else { + extraUIs.push({ + index: ui.index, + itemUI: itemUI + }); + } + } + } + } + //fullscreen这里单独处理一下,放到首行去 + if (toolbarItem === "fullscreen") { + if (toolbarUis && toolbarUis[0]) { + toolbarUis[0].items.splice(0, 0, toolbarItemUi); + } else { + toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi); + } + continue; + } + } else { + toolbarItemUi = toolbarItem; + } + if (toolbarItemUi && toolbarItemUi.id) { + toolbarUi.add(toolbarItemUi); + } + } + toolbarUis[i] = toolbarUi; + } + + //接受外部定制的UI + + utils.each(extraUIs, function (obj) { + toolbarUi.add(obj.itemUI, obj.index); + }); + this.toolbars = toolbarUis; + }, + getHtmlTpl: function () { + return ( + '
    ' + + '
    ' + + (this.toolbars.length + ? '
    ' + + this.renderToolbarBoxHtml() + + "
    " + : "") + + '" + + '
    ' + + "
    " + + '
    ' + + "
    " + + //modify wdcount by matao + '
    ' + + '' + + '' + + '' + + "
    " + + '
    ' + + "
    " + ); + }, + showWordImageDialog: function () { + this._dialogs["wordimageDialog"].open(); + }, + renderToolbarBoxHtml: function () { + var buff = []; + for (var i = 0; i < this.toolbars.length; i++) { + buff.push(this.toolbars[i].renderHtml()); + } + return buff.join(""); + }, + setFullScreen: function (fullscreen) { + var editor = this.editor, + container = editor.container.parentNode.parentNode; + if (this._fullscreen != fullscreen) { + this._fullscreen = fullscreen; + this.editor.fireEvent("beforefullscreenchange", fullscreen); + if (baidu.editor.browser.gecko) { + var bk = editor.selection.getRange().createBookmark(); + } + if (fullscreen) { + + // add https://gitee.com/modstart-lib/ueditor-plus/issues/I85R7X + this._bakEditorContaninerWidth = editor.iframe.parentNode.style.width; + + while (container.tagName !== "BODY") { + var position = baidu.editor.dom.domUtils.getComputedStyle( + container, + "position" + ); + nodeStack.push(position); + container.style.position = "static"; + container = container.parentNode; + } + this._bakHtmlOverflow = document.documentElement.style.overflow; + this._bakBodyOverflow = document.body.style.overflow; + this._bakAutoHeight = this.editor.autoHeightEnabled; + this._bakScrollTop = Math.max( + document.documentElement.scrollTop, + document.body.scrollTop + ); + + // delete https://gitee.com/modstart-lib/ueditor-plus/issues/I85R7X + // this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth; + + if (this._bakAutoHeight) { + //当全屏时不能执行自动长高 + editor.autoHeightEnabled = false; + this.editor.disableAutoHeight(); + } + + document.documentElement.style.overflow = "hidden"; + //修复,滚动条不收起的问题 + + window.scrollTo(0, window.scrollY); + this._bakCssText = this.getDom().style.cssText; + this._bakCssText1 = this.getDom("iframeholder").style.cssText; + editor.iframe.parentNode.style.width = ""; + this._updateFullScreen(); + } else { + while (container.tagName !== "BODY") { + container.style.position = nodeStack.shift(); + container = container.parentNode; + } + this.getDom().style.cssText = this._bakCssText; + this.getDom("iframeholder").style.cssText = this._bakCssText1; + if (this._bakAutoHeight) { + editor.autoHeightEnabled = true; + this.editor.enableAutoHeight(); + } + + document.documentElement.style.overflow = this._bakHtmlOverflow; + document.body.style.overflow = this._bakBodyOverflow; + // modify https://gitee.com/modstart-lib/ueditor-plus/issues/I85R7X + editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth + // editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth + "px"; + window.scrollTo(0, this._bakScrollTop); + } + if (browser.gecko && editor.body.contentEditable === "true") { + var input = document.createElement("input"); + document.body.appendChild(input); + editor.body.contentEditable = false; + setTimeout(function () { + input.focus(); + setTimeout(function () { + editor.body.contentEditable = true; + editor.fireEvent("fullscreenchanged", fullscreen); + editor.selection.getRange().moveToBookmark(bk).select(true); + baidu.editor.dom.domUtils.remove(input); + fullscreen && window.scroll(0, 0); + }, 0); + }, 0); + } + + if (editor.body.contentEditable === "true") { + this.editor.fireEvent("fullscreenchanged", fullscreen); + this.triggerLayout(); + } + } + }, + _updateFullScreen: function () { + if (this._fullscreen) { + var vpRect = uiUtils.getViewportRect(); + this.getDom().style.cssText = + "border:0;position:absolute;left:0;top:var(--ueditor-top-offset," + + (this.editor.options.topOffset || 0) + + "px);width:" + + vpRect.width + + "px;height:" + + vpRect.height + + "px;z-index:" + + (this.getDom().style.zIndex * 1 + 100); + uiUtils.setViewportOffset(this.getDom(), { + left: 0, + // top: this.editor.options.topOffset || 0 + }); + this.editor.setHeight( + vpRect.height - + this.getDom("toolbarbox").offsetHeight - + this.getDom("bottombar").offsetHeight - + (this.editor.options.topOffset || 0), + true + ); + //不手动调一下,会导致全屏失效 + if (browser.gecko) { + try { + window.onresize(); + } catch (e) { + } + } + } + }, + _updateElementPath: function () { + var bottom = this.getDom("elementpath"), + list; + if ( + this.elementPathEnabled && + (list = this.editor.queryCommandValue("elementpath")) + ) { + var buff = []; + for (var i = 0, ci; (ci = list[i]); i++) { + buff[i] = this.formatHtml( + '' + + ci + + "" + ); + } + bottom.innerHTML = + '
    ' + + this.editor.getLang("elementPathTip") + + ": " + + buff.join(" > ") + + "
    "; + } else { + bottom.style.display = "none"; + } + }, + disableElementPath: function () { + var bottom = this.getDom("elementpath"); + bottom.innerHTML = ""; + bottom.style.display = "none"; + this.elementPathEnabled = false; + }, + enableElementPath: function () { + var bottom = this.getDom("elementpath"); + bottom.style.display = ""; + this.elementPathEnabled = true; + this._updateElementPath(); + }, + _scale: function () { + var doc = document, + editor = this.editor, + editorHolder = editor.container, + editorDocument = editor.document, + toolbarBox = this.getDom("toolbarbox"), + bottombar = this.getDom("bottombar"), + scale = this.getDom("scale"), + scalelayer = this.getDom("scalelayer"); + + var isMouseMove = false, + position = null, + minEditorHeight = 0, + minEditorWidth = editor.options.minFrameWidth, + pageX = 0, + pageY = 0, + scaleWidth = 0, + scaleHeight = 0; + + function down() { + position = domUtils.getXY(editorHolder); + + if (!minEditorHeight) { + minEditorHeight = + editor.options.minFrameHeight + + toolbarBox.offsetHeight + + bottombar.offsetHeight; + } + + scalelayer.style.cssText = + "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" + + editorHolder.offsetWidth + + "px;height:" + + editorHolder.offsetHeight + + "px;z-index:" + + (editor.options.zIndex + 1); + + domUtils.on(doc, "mousemove", move); + domUtils.on(editorDocument, "mouseup", up); + domUtils.on(doc, "mouseup", up); + } + + var me = this; + //by xuheng 全屏时关掉缩放 + this.editor.addListener("fullscreenchanged", function (e, fullScreen) { + if (fullScreen) { + me.disableScale(); + } else { + if (me.editor.options.scaleEnabled) { + me.enableScale(); + var tmpNode = me.editor.document.createElement("span"); + me.editor.body.appendChild(tmpNode); + me.editor.body.style.height = + Math.max( + domUtils.getXY(tmpNode).y, + me.editor.iframe.offsetHeight - 20 + ) + "px"; + domUtils.remove(tmpNode); + } + } + }); + + function move(event) { + clearSelection(); + var e = event || window.event; + pageX = e.pageX || doc.documentElement.scrollLeft + e.clientX; + pageY = e.pageY || doc.documentElement.scrollTop + e.clientY; + scaleWidth = pageX - position.x; + scaleHeight = pageY - position.y; + + if (scaleWidth >= minEditorWidth) { + isMouseMove = true; + scalelayer.style.width = scaleWidth + "px"; + } + if (scaleHeight >= minEditorHeight) { + isMouseMove = true; + scalelayer.style.height = scaleHeight + "px"; + } + } + + function up() { + if (isMouseMove) { + isMouseMove = false; + editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2; + editorHolder.style.width = editor.ui._actualFrameWidth + "px"; + + editor.setHeight( + scalelayer.offsetHeight - + bottombar.offsetHeight - + toolbarBox.offsetHeight - + 2, + true + ); + } + if (scalelayer) { + scalelayer.style.display = "none"; + } + clearSelection(); + domUtils.un(doc, "mousemove", move); + domUtils.un(editorDocument, "mouseup", up); + domUtils.un(doc, "mouseup", up); + } + + function clearSelection() { + if (browser.ie) doc.selection.clear(); + else window.getSelection().removeAllRanges(); + } + + this.enableScale = function () { + //trace:2868 + if (editor.queryCommandState("source") == 1) return; + scale.style.display = ""; + this.scaleEnabled = true; + domUtils.on(scale, "mousedown", down); + }; + this.disableScale = function () { + scale.style.display = "none"; + this.scaleEnabled = false; + domUtils.un(scale, "mousedown", down); + }; + }, + isFullScreen: function () { + return this._fullscreen; + }, + postRender: function () { + UIBase.prototype.postRender.call(this); + for (var i = 0; i < this.toolbars.length; i++) { + this.toolbars[i].postRender(); + } + var me = this; + var timerId, + domUtils = baidu.editor.dom.domUtils, + updateFullScreenTime = function () { + clearTimeout(timerId); + timerId = setTimeout(function () { + me._updateFullScreen(); + }); + }; + domUtils.on(window, "resize", updateFullScreenTime); + + me.addListener("destroy", function () { + domUtils.un(window, "resize", updateFullScreenTime); + clearTimeout(timerId); + }); + }, + showToolbarMsg: function (msg, flag) { + this.getDom("toolbarmsg_label").innerHTML = msg; + this.getDom("toolbarmsg").style.display = ""; + // + if (!flag) { + var w = this.getDom("upload_dialog"); + w.style.display = "none"; + } + }, + hideToolbarMsg: function () { + this.getDom("toolbarmsg").style.display = "none"; + }, + mapUrl: function (url) { + return url + ? url.replace("~/", this.editor.options.UEDITOR_CORS_URL || "") + : ""; + }, + triggerLayout: function () { + var dom = this.getDom(); + if (dom.style.zoom == "1") { + dom.style.zoom = "100%"; + } else { + dom.style.zoom = "1"; } - } } - //fullscreen这里单独处理一下,放到首行去 - if (toolbarItem === "fullscreen") { - if (toolbarUis && toolbarUis[0]) { - toolbarUis[0].items.splice(0, 0, toolbarItemUi); - } else { - toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi); - } - continue; - } - } else { - toolbarItemUi = toolbarItem; - } - if (toolbarItemUi && toolbarItemUi.id) { - toolbarUi.add(toolbarItemUi); - } - } - toolbarUis[i] = toolbarUi; - } - - //接受外部定制的UI - - utils.each(extraUIs, function (obj) { - toolbarUi.add(obj.itemUI, obj.index); - }); - this.toolbars = toolbarUis; - }, - getHtmlTpl: function () { - return ( - '
    ' + - '
    ' + - (this.toolbars.length - ? '
    ' + - this.renderToolbarBoxHtml() + - "
    " - : "") + - '" + - '
    ' + - "
    " + - '
    ' + - "
    " + - //modify wdcount by matao - '
    ' + - '' + - '' + - '' + - "
    " + - '
    ' + - "
    " - ); - }, - showWordImageDialog: function () { - this._dialogs["wordimageDialog"].open(); - }, - renderToolbarBoxHtml: function () { - var buff = []; - for (var i = 0; i < this.toolbars.length; i++) { - buff.push(this.toolbars[i].renderHtml()); - } - return buff.join(""); - }, - setFullScreen: function (fullscreen) { - var editor = this.editor, - container = editor.container.parentNode.parentNode; - if (this._fullscreen != fullscreen) { - this._fullscreen = fullscreen; - this.editor.fireEvent("beforefullscreenchange", fullscreen); - if (baidu.editor.browser.gecko) { - var bk = editor.selection.getRange().createBookmark(); - } - if (fullscreen) { - while (container.tagName !== "BODY") { - var position = baidu.editor.dom.domUtils.getComputedStyle( - container, - "position" - ); - nodeStack.push(position); - container.style.position = "static"; - container = container.parentNode; - } - this._bakHtmlOverflow = document.documentElement.style.overflow; - this._bakBodyOverflow = document.body.style.overflow; - this._bakAutoHeight = this.editor.autoHeightEnabled; - this._bakScrollTop = Math.max( - document.documentElement.scrollTop, - document.body.scrollTop - ); - - this._bakEditorContaninerWidth = editor.iframe.parentNode.offsetWidth; - if (this._bakAutoHeight) { - //当全屏时不能执行自动长高 - editor.autoHeightEnabled = false; - this.editor.disableAutoHeight(); - } - - document.documentElement.style.overflow = "hidden"; - //修复,滚动条不收起的问题 - - window.scrollTo(0, window.scrollY); - this._bakCssText = this.getDom().style.cssText; - this._bakCssText1 = this.getDom("iframeholder").style.cssText; - editor.iframe.parentNode.style.width = ""; - this._updateFullScreen(); - } else { - while (container.tagName !== "BODY") { - container.style.position = nodeStack.shift(); - container = container.parentNode; - } - this.getDom().style.cssText = this._bakCssText; - this.getDom("iframeholder").style.cssText = this._bakCssText1; - if (this._bakAutoHeight) { - editor.autoHeightEnabled = true; - this.editor.enableAutoHeight(); - } - - document.documentElement.style.overflow = this._bakHtmlOverflow; - document.body.style.overflow = this._bakBodyOverflow; - editor.iframe.parentNode.style.width = - this._bakEditorContaninerWidth + "px"; - window.scrollTo(0, this._bakScrollTop); - } - if (browser.gecko && editor.body.contentEditable === "true") { - var input = document.createElement("input"); - document.body.appendChild(input); - editor.body.contentEditable = false; - setTimeout(function () { - input.focus(); - setTimeout(function () { - editor.body.contentEditable = true; - editor.fireEvent("fullscreenchanged", fullscreen); - editor.selection.getRange().moveToBookmark(bk).select(true); - baidu.editor.dom.domUtils.remove(input); - fullscreen && window.scroll(0, 0); - }, 0); - }, 0); - } - - if (editor.body.contentEditable === "true") { - this.editor.fireEvent("fullscreenchanged", fullscreen); - this.triggerLayout(); - } - } - }, - _updateFullScreen: function () { - if (this._fullscreen) { - var vpRect = uiUtils.getViewportRect(); - this.getDom().style.cssText = - "border:0;position:absolute;left:0;top:var(--ueditor-top-offset," + - (this.editor.options.topOffset || 0) + - "px);width:" + - vpRect.width + - "px;height:" + - vpRect.height + - "px;z-index:" + - (this.getDom().style.zIndex * 1 + 100); - uiUtils.setViewportOffset(this.getDom(), { - left: 0, - // top: this.editor.options.topOffset || 0 - }); - this.editor.setHeight( - vpRect.height - - this.getDom("toolbarbox").offsetHeight - - this.getDom("bottombar").offsetHeight - - (this.editor.options.topOffset || 0), - true - ); - //不手动调一下,会导致全屏失效 - if (browser.gecko) { - try { - window.onresize(); - } catch (e) { - } - } - } - }, - _updateElementPath: function () { - var bottom = this.getDom("elementpath"), - list; - if ( - this.elementPathEnabled && - (list = this.editor.queryCommandValue("elementpath")) - ) { - var buff = []; - for (var i = 0, ci; (ci = list[i]); i++) { - buff[i] = this.formatHtml( - '' + - ci + - "" - ); - } - bottom.innerHTML = - '
    ' + - this.editor.getLang("elementPathTip") + - ": " + - buff.join(" > ") + - "
    "; - } else { - bottom.style.display = "none"; - } - }, - disableElementPath: function () { - var bottom = this.getDom("elementpath"); - bottom.innerHTML = ""; - bottom.style.display = "none"; - this.elementPathEnabled = false; - }, - enableElementPath: function () { - var bottom = this.getDom("elementpath"); - bottom.style.display = ""; - this.elementPathEnabled = true; - this._updateElementPath(); - }, - _scale: function () { - var doc = document, - editor = this.editor, - editorHolder = editor.container, - editorDocument = editor.document, - toolbarBox = this.getDom("toolbarbox"), - bottombar = this.getDom("bottombar"), - scale = this.getDom("scale"), - scalelayer = this.getDom("scalelayer"); - - var isMouseMove = false, - position = null, - minEditorHeight = 0, - minEditorWidth = editor.options.minFrameWidth, - pageX = 0, - pageY = 0, - scaleWidth = 0, - scaleHeight = 0; - - function down() { - position = domUtils.getXY(editorHolder); - - if (!minEditorHeight) { - minEditorHeight = - editor.options.minFrameHeight + - toolbarBox.offsetHeight + - bottombar.offsetHeight; - } - - scalelayer.style.cssText = - "position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:" + - editorHolder.offsetWidth + - "px;height:" + - editorHolder.offsetHeight + - "px;z-index:" + - (editor.options.zIndex + 1); - - domUtils.on(doc, "mousemove", move); - domUtils.on(editorDocument, "mouseup", up); - domUtils.on(doc, "mouseup", up); - } - - var me = this; - //by xuheng 全屏时关掉缩放 - this.editor.addListener("fullscreenchanged", function (e, fullScreen) { - if (fullScreen) { - me.disableScale(); - } else { - if (me.editor.options.scaleEnabled) { - me.enableScale(); - var tmpNode = me.editor.document.createElement("span"); - me.editor.body.appendChild(tmpNode); - me.editor.body.style.height = - Math.max( - domUtils.getXY(tmpNode).y, - me.editor.iframe.offsetHeight - 20 - ) + "px"; - domUtils.remove(tmpNode); - } - } - }); - - function move(event) { - clearSelection(); - var e = event || window.event; - pageX = e.pageX || doc.documentElement.scrollLeft + e.clientX; - pageY = e.pageY || doc.documentElement.scrollTop + e.clientY; - scaleWidth = pageX - position.x; - scaleHeight = pageY - position.y; - - if (scaleWidth >= minEditorWidth) { - isMouseMove = true; - scalelayer.style.width = scaleWidth + "px"; - } - if (scaleHeight >= minEditorHeight) { - isMouseMove = true; - scalelayer.style.height = scaleHeight + "px"; - } - } - - function up() { - if (isMouseMove) { - isMouseMove = false; - editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2; - editorHolder.style.width = editor.ui._actualFrameWidth + "px"; - - editor.setHeight( - scalelayer.offsetHeight - - bottombar.offsetHeight - - toolbarBox.offsetHeight - - 2, - true - ); - } - if (scalelayer) { - scalelayer.style.display = "none"; - } - clearSelection(); - domUtils.un(doc, "mousemove", move); - domUtils.un(editorDocument, "mouseup", up); - domUtils.un(doc, "mouseup", up); - } - - function clearSelection() { - if (browser.ie) doc.selection.clear(); - else window.getSelection().removeAllRanges(); - } - - this.enableScale = function () { - //trace:2868 - if (editor.queryCommandState("source") == 1) return; - scale.style.display = ""; - this.scaleEnabled = true; - domUtils.on(scale, "mousedown", down); - }; - this.disableScale = function () { - scale.style.display = "none"; - this.scaleEnabled = false; - domUtils.un(scale, "mousedown", down); - }; - }, - isFullScreen: function () { - return this._fullscreen; - }, - postRender: function () { - UIBase.prototype.postRender.call(this); - for (var i = 0; i < this.toolbars.length; i++) { - this.toolbars[i].postRender(); - } - var me = this; - var timerId, - domUtils = baidu.editor.dom.domUtils, - updateFullScreenTime = function () { - clearTimeout(timerId); - timerId = setTimeout(function () { - me._updateFullScreen(); - }); }; - domUtils.on(window, "resize", updateFullScreenTime); + utils.inherits(EditorUI, baidu.editor.ui.UIBase); - me.addListener("destroy", function () { - domUtils.un(window, "resize", updateFullScreenTime); - clearTimeout(timerId); - }); - }, - showToolbarMsg: function (msg, flag) { - this.getDom("toolbarmsg_label").innerHTML = msg; - this.getDom("toolbarmsg").style.display = ""; - // - if (!flag) { - var w = this.getDom("upload_dialog"); - w.style.display = "none"; - } - }, - hideToolbarMsg: function () { - this.getDom("toolbarmsg").style.display = "none"; - }, - mapUrl: function (url) { - return url - ? url.replace("~/", this.editor.options.UEDITOR_CORS_URL || "") - : ""; - }, - triggerLayout: function () { - var dom = this.getDom(); - if (dom.style.zoom == "1") { - dom.style.zoom = "100%"; - } else { - dom.style.zoom = "1"; - } - } - }; - utils.inherits(EditorUI, baidu.editor.ui.UIBase); + var instances = {}; - var instances = {}; + UE.ui.Editor = function (options) { + var editor = new UE.Editor(options); + editor.options.editor = editor; + utils.loadFile(document, { + href: + editor.options.themePath + editor.options.theme + "/css/ueditor.css?69e258a4", + tag: "link", + type: "text/css", + rel: "stylesheet" + }); - UE.ui.Editor = function (options) { - var editor = new UE.Editor(options); - editor.options.editor = editor; - utils.loadFile(document, { - href: - editor.options.themePath + editor.options.theme + "/css/ueditor.css?20230921", - tag: "link", - type: "text/css", - rel: "stylesheet" - }); + var oldRender = editor.render; + editor.render = function (holder) { + if (holder.constructor === String) { + editor.key = holder; + instances[holder] = editor; + } + utils.domReady(function () { + editor.langIsReady + ? renderUI() + : editor.addListener("langReady", renderUI); - var oldRender = editor.render; - editor.render = function (holder) { - if (holder.constructor === String) { - editor.key = holder; - instances[holder] = editor; - } - utils.domReady(function () { - editor.langIsReady - ? renderUI() - : editor.addListener("langReady", renderUI); + function renderUI() { + editor.setOpt({ + labelMap: editor.options.labelMap || editor.getLang("labelMap") + }); + new EditorUI(editor.options); + if (holder) { + if (holder.constructor === String) { + holder = document.getElementById(holder); + } + holder && + holder.getAttribute("name") && + (editor.options.textarea = holder.getAttribute("name")); + if (holder && /script|textarea/gi.test(holder.tagName)) { + var newDiv = document.createElement("div"); + holder.parentNode.insertBefore(newDiv, holder); + var cont = holder.value || holder.innerHTML; + editor.options.initialContent = /^[\t\r\n ]*$/.test(cont) + ? editor.options.initialContent + : cont + .replace(/>[\n\r\t]+([ ]{4})+/g, ">") + .replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<"); + holder.className && (newDiv.className = holder.className); + holder.style.cssText && + (newDiv.style.cssText = holder.style.cssText); + if (/textarea/i.test(holder.tagName)) { + editor.textarea = holder; + editor.textarea.style.display = "none"; + } else { + holder.parentNode.removeChild(holder); + } + if (holder.id) { + newDiv.id = holder.id; + domUtils.removeAttributes(holder, "id"); + } + holder = newDiv; + holder.innerHTML = ""; + } + } + domUtils.addClass(holder, "edui-" + editor.options.theme); + editor.ui.render(holder); + var opt = editor.options; + //给实例添加一个编辑器的容器引用 + editor.container = editor.ui.getDom(); + var parents = domUtils.findParents(holder, true); + var displays = []; + for (var i = 0, ci; (ci = parents[i]); i++) { + displays[i] = ci.style.display; + ci.style.display = "block"; + } + if (opt.initialFrameWidth) { + opt.minFrameWidth = opt.initialFrameWidth; + } else { + opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth; + var styleWidth = holder.style.width; + if (/%$/.test(styleWidth)) { + opt.initialFrameWidth = styleWidth; + } + } + if (opt.initialFrameHeight) { + opt.minFrameHeight = opt.initialFrameHeight; + } else { + opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight; + } + for (var i = 0, ci; (ci = parents[i]); i++) { + ci.style.display = displays[i]; + } + //编辑器最外容器设置了高度,会导致,编辑器不占位 + //todo 先去掉,没有找到原因 + if (holder.style.height) { + holder.style.height = ""; + } + editor.container.style.width = + opt.initialFrameWidth + + (/%$/.test(opt.initialFrameWidth) ? "" : "px"); + editor.container.style.zIndex = opt.zIndex; + oldRender.call(editor, editor.ui.getDom("iframeholder")); + editor.fireEvent("afteruiready"); + } + }); + }; + return editor; + }; - function renderUI() { - editor.setOpt({ - labelMap: editor.options.labelMap || editor.getLang("labelMap") - }); - new EditorUI(editor.options); - if (holder) { - if (holder.constructor === String) { - holder = document.getElementById(holder); + /** + * @file + * @name UE + * @short UE + * @desc UEditor的顶部命名空间 + */ + /** + * @name getEditor + * @since 1.2.4+ + * @grammar UE.getEditor(id,[opt]) => Editor实例 + * @desc 提供一个全局的方法得到编辑器实例 + * + * * ''id'' 放置编辑器的容器id, 如果容器下的编辑器已经存在,就直接返回 + * * ''opt'' 编辑器的可选参数 + * @example + * UE.getEditor('containerId',{onready:function(){//创建一个编辑器实例 + * this.setContent('hello') + * }}); + * UE.getEditor('containerId'); //返回刚创建的实例 + * + */ + UE.getEditor = function (id, opt) { + var editor = instances[id]; + if (!editor) { + editor = instances[id] = new UE.ui.Editor(opt); + editor.render(id); } - holder && - holder.getAttribute("name") && - (editor.options.textarea = holder.getAttribute("name")); - if (holder && /script|textarea/gi.test(holder.tagName)) { - var newDiv = document.createElement("div"); - holder.parentNode.insertBefore(newDiv, holder); - var cont = holder.value || holder.innerHTML; - editor.options.initialContent = /^[\t\r\n ]*$/.test(cont) - ? editor.options.initialContent - : cont - .replace(/>[\n\r\t]+([ ]{4})+/g, ">") - .replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<"); - holder.className && (newDiv.className = holder.className); - holder.style.cssText && - (newDiv.style.cssText = holder.style.cssText); - if (/textarea/i.test(holder.tagName)) { - editor.textarea = holder; - editor.textarea.style.display = "none"; - } else { - holder.parentNode.removeChild(holder); - } - if (holder.id) { - newDiv.id = holder.id; - domUtils.removeAttributes(holder, "id"); - } - holder = newDiv; - holder.innerHTML = ""; + return editor; + }; + + UE.delEditor = function (id) { + var editor; + if ((editor = instances[id])) { + editor.key && editor.destroy(); + delete instances[id]; } - } - domUtils.addClass(holder, "edui-" + editor.options.theme); - editor.ui.render(holder); - var opt = editor.options; - //给实例添加一个编辑器的容器引用 - editor.container = editor.ui.getDom(); - var parents = domUtils.findParents(holder, true); - var displays = []; - for (var i = 0, ci; (ci = parents[i]); i++) { - displays[i] = ci.style.display; - ci.style.display = "block"; - } - if (opt.initialFrameWidth) { - opt.minFrameWidth = opt.initialFrameWidth; - } else { - opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth; - var styleWidth = holder.style.width; - if (/%$/.test(styleWidth)) { - opt.initialFrameWidth = styleWidth; - } - } - if (opt.initialFrameHeight) { - opt.minFrameHeight = opt.initialFrameHeight; - } else { - opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight; - } - for (var i = 0, ci; (ci = parents[i]); i++) { - ci.style.display = displays[i]; - } - //编辑器最外容器设置了高度,会导致,编辑器不占位 - //todo 先去掉,没有找到原因 - if (holder.style.height) { - holder.style.height = ""; - } - editor.container.style.width = - opt.initialFrameWidth + - (/%$/.test(opt.initialFrameWidth) ? "" : "px"); - editor.container.style.zIndex = opt.zIndex; - oldRender.call(editor, editor.ui.getDom("iframeholder")); - editor.fireEvent("afteruiready"); - } - }); - }; - return editor; - }; + }; - /** - * @file - * @name UE - * @short UE - * @desc UEditor的顶部命名空间 - */ - /** - * @name getEditor - * @since 1.2.4+ - * @grammar UE.getEditor(id,[opt]) => Editor实例 - * @desc 提供一个全局的方法得到编辑器实例 - * - * * ''id'' 放置编辑器的容器id, 如果容器下的编辑器已经存在,就直接返回 - * * ''opt'' 编辑器的可选参数 - * @example - * UE.getEditor('containerId',{onready:function(){//创建一个编辑器实例 - * this.setContent('hello') - * }}); - * UE.getEditor('containerId'); //返回刚创建的实例 - * - */ - UE.getEditor = function (id, opt) { - var editor = instances[id]; - if (!editor) { - editor = instances[id] = new UE.ui.Editor(opt); - editor.render(id); - } - return editor; - }; - - UE.delEditor = function (id) { - var editor; - if ((editor = instances[id])) { - editor.key && editor.destroy(); - delete instances[id]; - } - }; - - UE.registerUI = function (uiName, fn, index, editorId) { - utils.each(uiName.split(/\s+/), function (name) { - baidu.editor.ui[name] = { - id: editorId, - execFn: fn, - index: index - }; - }); - }; -})(); + UE.registerUI = function (uiName, fn, index, editorId) { + utils.each(uiName.split(/\s+/), function (name) { + baidu.editor.ui[name] = { + id: editorId, + execFn: fn, + index: index + }; + }); + }; + })(); // adapter/message.js -UE.registerUI("message", function(editor) { - var editorui = baidu.editor.ui; - var Message = editorui.Message; - var holder; - var _messageItems = []; - var me = editor; + UE.registerUI("message", function (editor) { + var editorui = baidu.editor.ui; + var Message = editorui.Message; + var holder; + var _messageItems = []; + var me = editor; - me.setOpt("enableMessageShow", true); - if (me.getOpt("enableMessageShow") === false) { - return; - } - - me.addListener("ready", function() { - holder = document.getElementById(me.ui.id + "_message_holder"); - updateHolderPos(); - setTimeout(function() { - updateHolderPos(); - }, 500); - }); - - me.addListener("showmessage", function(type, opt) { - opt = utils.isString(opt) - ? { - content: opt + me.setOpt("enableMessageShow", true); + if (me.getOpt("enableMessageShow") === false) { + return; } - : opt; - var message = new Message({ - timeout: opt.timeout, - type: opt.type, - content: opt.content, - keepshow: opt.keepshow, - editor: me - }), - mid = opt.id || "msg_" + (+new Date()).toString(36); - message.render(holder); - _messageItems[mid] = message; - message.reset(opt); - updateHolderPos(); - return mid; - }); - me.addListener("updatemessage", function(type, id, opt) { - opt = utils.isString(opt) - ? { - content: opt + me.addListener("ready", function () { + holder = document.getElementById(me.ui.id + "_message_holder"); + updateHolderPos(); + setTimeout(function () { + updateHolderPos(); + }, 500); + }); + + me.addListener("showmessage", function (type, opt) { + opt = utils.isString(opt) + ? { + content: opt + } + : opt; + var message = new Message({ + timeout: opt.timeout, + type: opt.type, + content: opt.content, + keepshow: opt.keepshow, + editor: me + }), + mid = opt.id || "msg_" + (+new Date()).toString(36); + message.render(holder); + _messageItems[mid] = message; + message.reset(opt); + updateHolderPos(); + return mid; + }); + + me.addListener("updatemessage", function (type, id, opt) { + opt = utils.isString(opt) + ? { + content: opt + } + : opt; + var message = _messageItems[id]; + message.render(holder); + message && message.reset(opt); + }); + + me.addListener("hidemessage", function (type, id) { + var message = _messageItems[id]; + message && message.hide(); + }); + + function updateHolderPos() { + if (!holder || !me.ui) return; + var toolbarbox = me.ui.getDom("toolbarbox"); + if (toolbarbox) { + holder.style.top = toolbarbox.offsetHeight + 3 + "px"; + } + holder.style.zIndex = + Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1; } - : opt; - var message = _messageItems[id]; - message.render(holder); - message && message.reset(opt); - }); - - me.addListener("hidemessage", function(type, id) { - var message = _messageItems[id]; - message && message.hide(); - }); - - function updateHolderPos() { - if (!holder || !me.ui) return; - var toolbarbox = me.ui.getDom("toolbarbox"); - if (toolbarbox) { - holder.style.top = toolbarbox.offsetHeight + 3 + "px"; - } - holder.style.zIndex = - Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1; - } -}); + }); -})(); +})(); \ No newline at end of file diff --git a/public/static/plugs/ueditor/ueditor.config.js b/public/static/plugs/ueditor/ueditor.config.js index 9b91525..2b4d856 100644 --- a/public/static/plugs/ueditor/ueditor.config.js +++ b/public/static/plugs/ueditor/ueditor.config.js @@ -10,14 +10,8 @@ **************************提示********************************/ (function () { - /** - * 编辑器资源文件根路径。它所表示的含义是:以编辑器实例化页面为当前路径,指向编辑器资源文件(即dialog等文件夹)的路径。 - * 鉴于很多同学在使用编辑器的时候出现的种种路径问题,此处强烈建议大家使用"相对于网站根目录的相对路径"进行配置。 - * "相对于网站根目录的相对路径"也就是以斜杠开头的形如"/myProject/ueditor/"这样的路径。 - * 如果站点中有多个不在同一层级的页面需要实例化编辑器,且引用了同一UEditor的时候,此处的URL可能不适用于每个页面的编辑器。 - * 因此,UEditor提供了针对不同页面的编辑器可单独配置的根路径,具体来说,在需要实例化编辑器的页面最顶部写上如下代码即可。当然,需要令此处的URL等于对应的配置。 - * window.UEDITOR_HOME_URL = "/xxxx/xxxx/"; - */ + // 资源文件根路径,如果你的页面不是放在根目录下,请注意修改这个路径 + // 通常情况下这个可以配置成静态资源CDN的地址 window.UEDITOR_HOME_URL = "/static/plugs/ueditor/"; var URL, CORS_URL; if (window.UEDITOR_HOME_URL) { @@ -29,6 +23,8 @@ } else { URL = getUEBasePath(); } + // 需要能跨域的静态资源请求,主要用户弹窗页面等静态资源 + // 通常情况下这个可以配置成静态资源CDN的地址 if (window.UEDITOR_CORS_URL) { CORS_URL = window.UEDITOR_CORS_URL; } else if (window.__msRoot) { @@ -38,6 +34,7 @@ } else { CORS_URL = getUEBasePath(); } + /** * 配置项主体。注意,此处所有涉及到路径的配置别遗漏URL变量。 */ @@ -53,10 +50,19 @@ // 服务器统一请求接口路径 serverUrl: "/" + (window.CONFIG.ADMIN || 'admin') + "/ajax/uploadUEditor", + + // 从服务器获取配置 + loadConfigFromServer: true, + // 服务器统一请求头信息,会在所有请求中带上该信息 serverHeaders: { // 'Authorization': 'Bearer xxx' }, + // 服务器返回参数统一转换方法,可以在这里统一处理返回参数 + serverResponsePrepare: function (res) { + // console.log('serverResponsePrepare', res); + return res; + }, //工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义 toolbars: [ @@ -114,8 +120,8 @@ "|", "imagenone", // 图片默认 "imageleft", // 图片左浮动 - "imageright", // 图片右浮动 "imagecenter", // 图片居中 + "imageright", // 图片右浮动 "|", "simpleupload", // 单图上传 "insertimage", // 多图上传 @@ -154,12 +160,15 @@ "print", // 打印 "preview", // 预览 "searchreplace", // 查询替换 + "|", + "contentimport", "help", // 帮助 ] ] // 自定义工具栏按钮点击,返回 true 表示已经处理点击,会阻止默认事件 , toolbarCallback: function (cmd, editor) { + // console.log('toolbarCallback',cmd, editor); // switch(cmd){ // case 'insertimage': // editor.execCommand('insertHtml', '

    '); @@ -176,6 +185,33 @@ // } } + // 自定义上传功能 + , uploadServiceEnable: false + // 自定义上传函数,需要在这个函数中实现自定义上传逻辑 + // type 上传类型,image 图片,video 视频,audio 音频,attachment 附件 + // file 文件对象 + // callback 回调函数,需要在上传完成后调用 callback.success、callback.error、callback.progress + // option 上传配置,其他一些未来扩展配置 + , uploadServiceUpload: function(type, file, callback, option ) { + console.log('uploadServiceUpload', type, file, callback, option); + // var i = 0; + // var call = function(){ + // i++; + // if(i > 3){ + // callback.success({ + // "state": "SUCCESS", + // "url": "https://ms-assets.modstart.com/demo/modstart.jpg", + // }) + // return; + // } + // setTimeout(function(){ + // callback.progress(0.3 * i); + // call(); + // },500); + // } + // call(); + } + // 插入图片自定义配置 , imageConfig: { // 禁止本地上传 @@ -316,7 +352,8 @@ // 是否开启初始化时即全屏,默认关闭 , fullscreen: false - //,imagePopup:true //图片操作的浮层开关,默认打开 + // 图片操作的浮层开关,默认打开 + //,imagePopup:true // 自动同步编辑器要提交的数据 //,autoSyncData:true @@ -359,17 +396,8 @@ // 提交到后台的数据是否包含整个html字符串 , allHtmlEnabled: false - //insertorderedlist //有序列表的下拉配置,值留空时支持多语言自动识别,若配置值,则以此值为准 //,'insertorderedlist':{ - // //自定的样式 - // 'num':'1,2,3...', - // 'num1':'1),2),3)...', - // 'num2':'(1),(2),(3)...', - // 'cn':'一,二,三....', - // 'cn1':'一),二),三)....', - // 'cn2':'(一),(二),(三)....', - // //系统自带 // 'decimal' : '' , //'1,2,3...' // 'lower-alpha' : '' , // 'a,b,c...' // 'lower-roman' : '' , //'i,ii,iii...' @@ -380,8 +408,6 @@ //insertunorderedlist //无序列表的下拉配置,值留空时支持多语言自动识别,若配置值,则以此值为准 //,insertunorderedlist : { //自定的样式 - // 'dash' :'— 破折号', //-破折号 - // 'dot':' 。 小圆圈', //系统自带 // 'circle' : '', // '○ 小圆圈' // 'disc' : '', // '● 小圆点' // 'square' : '' //'■ 小方块' @@ -465,6 +491,12 @@ "forecolor", // 字体颜色 // "shadowcolor", // 字体阴影 "backcolor", // 背景色 + "imagenone", + "imageleft", + "imagecenter", + "imageright", + "insertimage", + "formula", // "justifyleft", // 居左对齐 // "justifycenter", // 居中对齐 // "justifyright", // 居右对齐 @@ -513,19 +545,19 @@ // 是否自动长高,默认true , autoHeightEnabled: true - //scaleEnabled - //是否可以拉伸长高,默认true(当开启时,自动长高失效) + // 是否可以拉伸长高,默认true(当开启时,自动长高失效) //,scaleEnabled:false //,minFrameWidth:800 //编辑器拖动时最小宽度,默认800 - //,minFrameHeight:220 //编辑器拖动时最小高度,默认220 - //autoFloatEnabled - //是否保持toolbar的位置不动,默认true - //,autoFloatEnabled:true - //浮动时工具栏距离浏览器顶部的高度,用于某些具有固定头部的页面 - //,topOffset:30 - //编辑器底部距离工具栏高度(如果参数大于等于编辑器高度,则设置无效) - //,toolbarTopOffset:400 + // 编辑器最小高度,默认220 + , minFrameHeight: 220 + + // 是否保持toolbar的位置不动,默认true + , autoFloatEnabled: true + // 浮动时工具栏距离浏览器顶部的高度,用于某些具有固定头部的页面 + , topOffset: 0 + // 编辑器底部距离工具栏高度(如果参数大于等于编辑器高度,则设置无效) + , toolbarTopOffset: 0 //设置远程图片是否抓取到本地保存 , catchRemoteImageEnable: true //设置是否抓取远程图片 @@ -595,7 +627,15 @@ // 允许进入编辑器的 div 标签自动变成 p 标签 , allowDivTransToP: true // 默认产出的数据中的color自动从rgb格式变成16进制格式 - , rgb2Hex: true + , rgb2Hex: true, + + tipError: function (msg, param) { + if (window && window.MS && window.MS.dialog) { + window.MS.dialog.tipError(msg); + } else { + alert(msg); + } + } }; function getUEBasePath(docUrl, confUrl) { @@ -651,4 +691,4 @@ window.UE = { getUEBasePath: getUEBasePath }; -})(); +})(); \ No newline at end of file