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