1 /**
  2  * common utils for kissy editor
  3  * @author yiminghe@gmail.com
  4  */
  5 KISSY.add("editor/core/utils", function (S) {
  6 
  7     var Editor = S.Editor,
  8         TRUE = true,
  9         FALSE = false,
 10         NULL = null,
 11         Node = S.Node,
 12         DOM = S.DOM,
 13         UA = S.UA,
 14 
 15         /**
 16          * @namespace
 17          * Utilities for Editor.
 18          * @name Utils
 19          * @memberOf Editor
 20          */
 21             Utils =
 22         /**
 23          * @lends Editor.Utils
 24          */
 25         {
 26             /**
 27              *
 28              * @param url
 29              * @return {String}
 30              */
 31             debugUrl:function (url) {
 32                 var Config = S.Config;
 33                 if (!Config.debug) {
 34                     url = url.replace(/\.(js|css)/i, "-min.$1");
 35                 }
 36                 if (url.indexOf("?t") == -1) {
 37                     if (url.indexOf("?") != -1) {
 38                         url += "&";
 39                     } else {
 40                         url += "?";
 41                     }
 42                     url += "t=" + encodeURIComponent(Config.tag);
 43                 }
 44                 return Config.base + "editor/" + url;
 45             },
 46 
 47             /**
 48              * 懒惰一下
 49              * @param obj {Object} 包含方法的对象
 50              * @param before {string} 准备方法
 51              * @param after {string} 真正方法
 52              */
 53             lazyRun:function (obj, before, after) {
 54                 var b = obj[before], a = obj[after];
 55                 obj[before] = function () {
 56                     b.apply(this, arguments);
 57                     obj[before] = obj[after];
 58                     return a.apply(this, arguments);
 59                 };
 60             },
 61 
 62             /**
 63              * srcDoc 中的位置在 destDoc 的对应位置
 64              * @param x {number}
 65              * @param y {number}
 66              * @param srcDoc {Document}
 67              * @param destDoc {Document}
 68              * @return 在最终文档中的位置
 69              */
 70             getXY:function (x, y, srcDoc, destDoc) {
 71                 var currentWindow = srcDoc.defaultView || srcDoc.parentWindow;
 72 
 73                 //x,y相对于当前iframe文档,防止当前iframe有滚动条
 74                 x -= DOM.scrollLeft(currentWindow);
 75                 y -= DOM.scrollTop(currentWindow);
 76                 if (destDoc) {
 77                     var refWindow = destDoc.defaultView || destDoc.parentWindow;
 78                     if (currentWindow != refWindow && currentWindow['frameElement']) {
 79                         //note:when iframe is static ,still some mistake
 80                         var iframePosition = DOM.offset(currentWindow['frameElement'], undefined, refWindow);
 81                         x += iframePosition.left;
 82                         y += iframePosition.top;
 83                     }
 84                 }
 85                 return {left:x, top:y};
 86             },
 87 
 88             /**
 89              * 执行一系列函数
 90              * @param var_args {...function()}
 91              * @return {*} 得到成功的返回
 92              */
 93             tryThese:function (var_args) {
 94                 var returnValue;
 95                 for (var i = 0, length = arguments.length; i < length; i++) {
 96                     var lambda = arguments[i];
 97                     try {
 98                         returnValue = lambda();
 99                         break;
100                     }
101                     catch (e) {
102                     }
103                 }
104                 return returnValue;
105             },
106 
107             /**
108              * 是否两个数组完全相同
109              * @param arrayA {Array}
110              * @param arrayB {Array}
111              * @return {Boolean}
112              */
113             arrayCompare:function (arrayA, arrayB) {
114                 if (!arrayA && !arrayB)
115                     return TRUE;
116 
117                 if (!arrayA || !arrayB || arrayA.length != arrayB.length)
118                     return FALSE;
119 
120                 for (var i = 0; i < arrayA.length; i++) {
121                     if (arrayA[ i ] !== arrayB[ i ])
122                         return FALSE;
123                 }
124 
125                 return TRUE;
126             },
127 
128             /**
129              * @param database {Object}
130              */
131             clearAllMarkers:function (database) {
132                 for (var i in database) {
133                     if (database.hasOwnProperty(i)) {
134                         database[i]._4e_clearMarkers(database, TRUE, undefined);
135                     }
136                 }
137             },
138 
139             /**
140              *
141              * @param str {string}
142              * @return {string}
143              */
144             ltrim:function (str) {
145                 return str.replace(/^\s+/, "");
146             },
147 
148             /**
149              *
150              * @param str {string}
151              * @return {string}
152              */
153             rtrim:function (str) {
154                 return str.replace(/\s+$/, "");
155             },
156 
157             /**
158              *
159              */
160             isNumber:function (n) {
161                 return /^\d+(.\d+)?$/.test(S.trim(n));
162             },
163 
164             /**
165              *
166              * @param inputs {Array.<Node>}
167              * @return {Boolean} 是否验证成功
168              */
169             verifyInputs:function (inputs) {
170                 for (var i = 0; i < inputs.length; i++) {
171                     var input = new Node(inputs[i]),
172                         v = S.trim(Utils.valInput(input)),
173                         verify = input.attr("data-verify"),
174                         warning = input.attr("data-warning");
175                     if (verify && !new RegExp(verify).test(v)) {
176                         alert(warning);
177                         return FALSE;
178                     }
179                 }
180                 return TRUE;
181             },
182 
183             /**
184              *
185              * @param editor {KISSY.Editor}
186              * @param plugin {Object}
187              */
188             sourceDisable:function (editor, plugin) {
189                 editor.on("sourceMode", plugin.disable, plugin);
190                 editor.on("wysiwygMode", plugin.enable, plugin);
191             },
192 
193             /**
194              *
195              * @param inp {NodeList}
196              */
197             resetInput:function (inp) {
198                 var placeholder = inp.attr("placeholder");
199                 if (placeholder && UA['ie']) {
200                     inp.addClass("ks-editor-input-tip");
201                     inp.val(placeholder);
202                 } else if (!UA['ie']) {
203                     inp.val("");
204                 }
205             },
206 
207             /**
208              *
209              * @param inp  {NodeList}
210              * @param [val]
211              */
212             valInput:function (inp, val) {
213                 if (val === undefined) {
214                     if (inp.hasClass("ks-editor-input-tip")) {
215                         return "";
216                     } else {
217                         return inp.val();
218                     }
219                 } else {
220                     inp.removeClass("ks-editor-input-tip");
221                     inp.val(val);
222                 }
223             },
224 
225             /**
226              *
227              * @param inp {NodeList}
228              * @param tip {string}
229              */
230             placeholder:function (inp, tip) {
231                 inp.attr("placeholder", tip);
232                 if (!UA['ie']) {
233                     return;
234                 }
235                 inp.on("blur", function () {
236                     if (!S.trim(inp.val())) {
237                         inp.addClass("ks-editor-input-tip");
238                         inp.val(tip);
239                     }
240                 });
241                 inp.on("focus", function () {
242                     inp.removeClass("ks-editor-input-tip");
243                     if (S.trim(inp.val()) == tip) {
244                         inp.val("");
245                     }
246                 });
247             },
248 
249             /**
250              * Convert certain characters (&, <, >, and ') to their HTML character equivalents
251              *  for literal display in web pages.
252              * @param {string} value The string to encode
253              * @return {string} The encoded text
254              */
255             htmlEncode:function (value) {
256                 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
257             },
258 
259             /**
260              *
261              * @param params {Object}
262              * @return {Object}
263              */
264             normParams:function (params) {
265                 params = S.clone(params);
266                 for (var p in params) {
267                     if (params.hasOwnProperty(p)) {
268                         var v = params[p];
269                         if (S.isFunction(v)) {
270                             params[p] = v();
271                         }
272                     }
273                 }
274                 return params;
275             },
276 
277             /**
278              *
279              */
280             map:function (arr, callback) {
281                 for (var i = 0; i < arr.length; i++) {
282                     arr[i] = callback(arr[i]);
283                 }
284                 return arr;
285             },
286 
287             //直接判断引擎,防止兼容性模式影响
288             ieEngine:document['documentMode'] || UA['ie'],
289 
290             /**
291              * 点击 el 或者 el 内的元素,不会使得焦点转移
292              * @param el
293              */
294             preventFocus:function (el) {
295                 if (UA['ie']) {
296                     //ie 点击按钮不丢失焦点
297                     el.unselectable(undefined);
298                 } else {
299                     el.attr("onmousedown", "return false;");
300                 }
301             },
302 
303             /**
304              *
305              */
306             injectDom:function (editorDom) {
307                 S.mix(DOM, editorDom);
308                 for (var dm in editorDom) {
309                     if (editorDom.hasOwnProperty(dm))
310                         (function (dm) {
311                             Node.prototype[dm] = function () {
312                                 var args = [].slice.call(arguments, 0);
313                                 args.unshift(this[0]);
314                                 var ret = editorDom[dm].apply(NULL, args);
315                                 if (ret && (ret.nodeType || S.isWindow(ret))) {
316                                     return new Node(ret);
317                                 } else {
318                                     if (S.isArray(ret)) {
319                                         if (ret.__IS_NODELIST || (ret[0] && ret[0].nodeType)) {
320                                             return new Node(ret);
321                                         }
322                                     }
323                                     return ret;
324                                 }
325                             };
326                         })(dm);
327                 }
328             },
329 
330             /**
331              *
332              */
333             addRes:function () {
334                 this.__res = this.__res || [];
335                 var res = this.__res;
336                 res.push.apply(res, S.makeArray(arguments));
337             },
338 
339             /**
340              *
341              */
342             destroyRes:function () {
343                 var res = this.__res || [];
344                 for (var i = 0; i < res.length; i++) {
345                     var r = res[i];
346                     if (S.isFunction(r)) {
347                         r();
348                     } else {
349                         if (r.destroy) {
350                             r.destroy();
351                         }
352                         else if (r.remove) {
353                             r.remove();
354                         }
355                     }
356                 }
357                 this.__res = [];
358             },
359 
360             /**
361              *
362              */
363             getQueryCmd:function (cmd) {
364                 return "query" + ("-" + cmd).replace(/-(\w)/g, function (m, m1) {
365                     return m1.toUpperCase()
366                 }) + "Value";
367             }
368         };
369 
370     Editor.Utils = Utils;
371 
372     return Utils;
373 }, {
374     requires:['./base']
375 });
376