PageRenderTime 72ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/source/Plug-in/kind/kindeditor.js

http://prosporous.googlecode.com/
JavaScript | 2379 lines | 2370 code | 0 blank | 9 comment | 482 complexity | a95f301b6daa50395b668e3effb92022 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*******************************************************************************
  2. * KindEditor - WYSIWYG HTML Editor for Internet
  3. * Copyright (C) 2006-2011 kindsoft.net
  4. *
  5. * @author Roddy <luolonghao@gmail.com>
  6. * @website http://www.kindsoft.net/
  7. * @licence http://www.kindsoft.net/license.php
  8. * @version 4.0.4 (2011-12-11)
  9. *******************************************************************************/
  10. (function (window, undefined) {
  11. if (window.KindEditor) {
  12. return;
  13. }
  14. if (!window.console) {
  15. window.console = {};
  16. }
  17. if (!console.log) {
  18. console.log = function () {};
  19. }
  20. var _VERSION = '4.0.4 (2011-12-11)',
  21. _ua = navigator.userAgent.toLowerCase(),
  22. _IE = _ua.indexOf('msie') > -1 && _ua.indexOf('opera') == -1,
  23. _GECKO = _ua.indexOf('gecko') > -1 && _ua.indexOf('khtml') == -1,
  24. _WEBKIT = _ua.indexOf('applewebkit') > -1,
  25. _OPERA = _ua.indexOf('opera') > -1,
  26. _MOBILE = _ua.indexOf('mobile') > -1,
  27. _QUIRKS = document.compatMode != 'CSS1Compat',
  28. _matches = /(?:msie|firefox|webkit|opera)[\/:\s](\d+)/.exec(_ua),
  29. _V = _matches ? _matches[1] : '0',
  30. _TIME = new Date().getTime();
  31. function _isArray(val) {
  32. if (!val) {
  33. return false;
  34. }
  35. return Object.prototype.toString.call(val) === '[object Array]';
  36. }
  37. function _isFunction(val) {
  38. if (!val) {
  39. return false;
  40. }
  41. return Object.prototype.toString.call(val) === '[object Function]';
  42. }
  43. function _inArray(val, arr) {
  44. for (var i = 0, len = arr.length; i < len; i++) {
  45. if (val === arr[i]) {
  46. return i;
  47. }
  48. }
  49. return -1;
  50. }
  51. function _each(obj, fn) {
  52. if (_isArray(obj)) {
  53. for (var i = 0, len = obj.length; i < len; i++) {
  54. if (fn.call(obj[i], i, obj[i]) === false) {
  55. break;
  56. }
  57. }
  58. } else {
  59. for (var key in obj) {
  60. if (obj.hasOwnProperty(key)) {
  61. if (fn.call(obj[key], key, obj[key]) === false) {
  62. break;
  63. }
  64. }
  65. }
  66. }
  67. }
  68. function _trim(str) {
  69. return str.replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g, '');
  70. }
  71. function _inString(val, str, delimiter) {
  72. delimiter = delimiter === undefined ? ',' : delimiter;
  73. return (delimiter + str + delimiter).indexOf(delimiter + val + delimiter) >= 0;
  74. }
  75. function _addUnit(val, unit) {
  76. unit = unit || 'px';
  77. return val && /^\d+$/.test(val) ? val + 'px' : val;
  78. }
  79. function _removeUnit(val) {
  80. var match;
  81. return val && (match = /(\d+)/.exec(val)) ? parseInt(match[1], 10) : 0;
  82. }
  83. function _escape(val) {
  84. return val.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  85. }
  86. function _unescape(val) {
  87. return val.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&amp;/g, '&');
  88. }
  89. function _toCamel(str) {
  90. var arr = str.split('-');
  91. str = '';
  92. _each(arr, function(key, val) {
  93. str += (key > 0) ? val.charAt(0).toUpperCase() + val.substr(1) : val;
  94. });
  95. return str;
  96. }
  97. function _toHex(val) {
  98. function hex(d) {
  99. var s = parseInt(d, 10).toString(16).toUpperCase();
  100. return s.length > 1 ? s : '0' + s;
  101. }
  102. return val.replace(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/ig,
  103. function($0, $1, $2, $3) {
  104. return '#' + hex($1) + hex($2) + hex($3);
  105. }
  106. );
  107. }
  108. function _toMap(val, delimiter) {
  109. delimiter = delimiter === undefined ? ',' : delimiter;
  110. var map = {}, arr = _isArray(val) ? val : val.split(delimiter), match;
  111. _each(arr, function(key, val) {
  112. if ((match = /^(\d+)\.\.(\d+)$/.exec(val))) {
  113. for (var i = parseInt(match[1], 10); i <= parseInt(match[2], 10); i++) {
  114. map[i.toString()] = true;
  115. }
  116. } else {
  117. map[val] = true;
  118. }
  119. });
  120. return map;
  121. }
  122. function _toArray(obj, offset) {
  123. return Array.prototype.slice.call(obj, offset || 0);
  124. }
  125. function _undef(val, defaultVal) {
  126. return val === undefined ? defaultVal : val;
  127. }
  128. function _invalidUrl(url) {
  129. return !url || /[<>"]/.test(url);
  130. }
  131. function _addParam(url, param) {
  132. return url.indexOf('?') >= 0 ? url + '&' + param : url + '?' + param;
  133. }
  134. function _extend(child, parent, proto) {
  135. if (!proto) {
  136. proto = parent;
  137. parent = null;
  138. }
  139. var childProto;
  140. if (parent) {
  141. var fn = function () {};
  142. fn.prototype = parent.prototype;
  143. childProto = new fn();
  144. _each(proto, function(key, val) {
  145. childProto[key] = val;
  146. });
  147. } else {
  148. childProto = proto;
  149. }
  150. childProto.constructor = child;
  151. child.prototype = childProto;
  152. child.parent = parent ? parent.prototype : null;
  153. }
  154. function _json(text) {
  155. var match;
  156. if ((match = /\{[\s\S]*\}|\[[\s\S]*\]/.exec(text))) {
  157. text = match[0];
  158. }
  159. var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
  160. cx.lastIndex = 0;
  161. if (cx.test(text)) {
  162. text = text.replace(cx, function (a) {
  163. return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
  164. });
  165. }
  166. if (/^[\],:{}\s]*$/.
  167. test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
  168. replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
  169. replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
  170. return eval('(' + text + ')');
  171. }
  172. throw 'JSON parse error';
  173. }
  174. var _round = Math.round;
  175. var K = {
  176. DEBUG : false,
  177. VERSION : _VERSION,
  178. IE : _IE,
  179. GECKO : _GECKO,
  180. WEBKIT : _WEBKIT,
  181. OPERA : _OPERA,
  182. V : _V,
  183. TIME : _TIME,
  184. each : _each,
  185. isArray : _isArray,
  186. isFunction : _isFunction,
  187. inArray : _inArray,
  188. inString : _inString,
  189. trim : _trim,
  190. addUnit : _addUnit,
  191. removeUnit : _removeUnit,
  192. escape : _escape,
  193. unescape : _unescape,
  194. toCamel : _toCamel,
  195. toHex : _toHex,
  196. toMap : _toMap,
  197. toArray : _toArray,
  198. undef : _undef,
  199. invalidUrl : _invalidUrl,
  200. addParam : _addParam,
  201. extend : _extend,
  202. json : _json
  203. };
  204. var _INLINE_TAG_MAP = _toMap('a,abbr,acronym,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,img,input,ins,kbd,label,map,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'),
  205. _BLOCK_TAG_MAP = _toMap('address,applet,blockquote,body,center,dd,dir,div,dl,dt,fieldset,form,frameset,h1,h2,h3,h4,h5,h6,head,hr,html,iframe,ins,isindex,li,map,menu,meta,noframes,noscript,object,ol,p,pre,script,style,table,tbody,td,tfoot,th,thead,title,tr,ul'),
  206. _SINGLE_TAG_MAP = _toMap('area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed'),
  207. _STYLE_TAG_MAP = _toMap('b,basefont,big,del,em,font,i,s,small,span,strike,strong,sub,sup,u'),
  208. _CONTROL_TAG_MAP = _toMap('img,table,input,textarea,button'),
  209. _PRE_TAG_MAP = _toMap('pre,style,script'),
  210. _NOSPLIT_TAG_MAP = _toMap('html,head,body,td,tr,table,ol,ul,li'),
  211. _AUTOCLOSE_TAG_MAP = _toMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'),
  212. _FILL_ATTR_MAP = _toMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'),
  213. _VALUE_TAG_MAP = _toMap('input,button,textarea,select');
  214. function _getBasePath() {
  215. var els = document.getElementsByTagName('script'), src;
  216. for (var i = 0, len = els.length; i < len; i++) {
  217. src = els[i].src || '';
  218. if (/kindeditor[\w\-\.]*\.js/.test(src)) {
  219. return src.substring(0, src.lastIndexOf('/') + 1);
  220. }
  221. }
  222. return '';
  223. }
  224. K.basePath = _getBasePath();
  225. K.options = {
  226. designMode : true,
  227. fullscreenMode : false,
  228. filterMode : false,
  229. wellFormatMode : true,
  230. shadowMode : true,
  231. loadStyleMode : true,
  232. basePath : K.basePath,
  233. themesPath : K.basePath + 'themes/',
  234. langPath : K.basePath + 'lang/',
  235. pluginsPath : K.basePath + 'plugins/',
  236. themeType : 'default',
  237. langType : 'zh_CN',
  238. urlType : '',
  239. newlineTag : 'p',
  240. resizeType : 2,
  241. syncType : 'form',
  242. pasteType : 2,
  243. dialogAlignType : 'page',
  244. useContextmenu : true,
  245. bodyClass : 'ke-content',
  246. indentChar : '\t',
  247. cssPath : '',
  248. cssData : '',
  249. minWidth : 650,
  250. minHeight : 100,
  251. minChangeSize : 5,
  252. items : [
  253. 'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'cut', 'copy', 'paste',
  254. 'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',
  255. 'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
  256. 'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',
  257. 'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',
  258. 'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image',
  259. 'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'map', 'code', 'pagebreak', 'anchor', 'link', 'unlink', '|', 'about'
  260. ],
  261. noDisableItems : ['source', 'fullscreen'],
  262. colorTable : [
  263. ['#E53333', '#E56600', '#FF9900', '#64451D', '#DFC5A4', '#FFE500'],
  264. ['#009900', '#006600', '#99BB00', '#B8D100', '#60D978', '#00D5FF'],
  265. ['#337FE5', '#003399', '#4C33E5', '#9933E5', '#CC33E5', '#EE33EE'],
  266. ['#FFFFFF', '#CCCCCC', '#999999', '#666666', '#333333', '#000000']
  267. ],
  268. fontSizeTable : ['9px', '10px', '12px', '14px', '16px', '18px', '24px', '32px'],
  269. htmlTags : {
  270. font : ['color', 'size', 'face', '.background-color'],
  271. span : [
  272. '.color', '.background-color', '.font-size', '.font-family', '.background',
  273. '.font-weight', '.font-style', '.text-decoration', '.vertical-align', '.line-height'
  274. ],
  275. div : [
  276. 'align', '.border', '.margin', '.padding', '.text-align', '.color',
  277. '.background-color', '.font-size', '.font-family', '.font-weight', '.background',
  278. '.font-style', '.text-decoration', '.vertical-align', '.margin-left'
  279. ],
  280. table: [
  281. 'border', 'cellspacing', 'cellpadding', 'width', 'height', 'align', 'bordercolor',
  282. '.padding', '.margin', '.border', 'bgcolor', '.text-align', '.color', '.background-color',
  283. '.font-size', '.font-family', '.font-weight', '.font-style', '.text-decoration', '.background',
  284. '.width', '.height', '.border-collapse'
  285. ],
  286. 'td,th': [
  287. 'align', 'valign', 'width', 'height', 'colspan', 'rowspan', 'bgcolor',
  288. '.text-align', '.color', '.background-color', '.font-size', '.font-family', '.font-weight',
  289. '.font-style', '.text-decoration', '.vertical-align', '.background', '.border'
  290. ],
  291. a : ['href', 'target', 'name'],
  292. embed : ['src', 'width', 'height', 'type', 'loop', 'autostart', 'quality', '.width', '.height', 'align', 'allowscriptaccess'],
  293. img : ['src', 'width', 'height', 'border', 'alt', 'title', 'align', '.width', '.height', '.border'],
  294. 'p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6' : [
  295. 'align', '.text-align', '.color', '.background-color', '.font-size', '.font-family', '.background',
  296. '.font-weight', '.font-style', '.text-decoration', '.vertical-align', '.text-indent', '.margin-left'
  297. ],
  298. pre : ['class'],
  299. hr : ['class', '.page-break-after'],
  300. 'br,tbody,tr,strong,b,sub,sup,em,i,u,strike,s,del' : []
  301. },
  302. layout : '<div class="container"><div class="toolbar"></div><div class="edit"></div><div class="statusbar"></div></div>'
  303. };
  304. var _useCapture = false;
  305. var _INPUT_KEY_MAP = _toMap('8,9,13,32,46,48..57,59,61,65..90,106,109..111,188,190..192,219..222');
  306. var _CURSORMOVE_KEY_MAP = _toMap('33..40');
  307. var _CHANGE_KEY_MAP = {};
  308. _each(_INPUT_KEY_MAP, function(key, val) {
  309. _CHANGE_KEY_MAP[key] = val;
  310. });
  311. _each(_CURSORMOVE_KEY_MAP, function(key, val) {
  312. _CHANGE_KEY_MAP[key] = val;
  313. });
  314. function _bindEvent(el, type, fn) {
  315. if (el.addEventListener){
  316. el.addEventListener(type, fn, _useCapture);
  317. } else if (el.attachEvent){
  318. el.attachEvent('on' + type, fn);
  319. }
  320. }
  321. function _unbindEvent(el, type, fn) {
  322. if (el.removeEventListener){
  323. el.removeEventListener(type, fn, _useCapture);
  324. } else if (el.detachEvent){
  325. el.detachEvent('on' + type, fn);
  326. }
  327. }
  328. var _EVENT_PROPS = ('altKey,attrChange,attrName,bubbles,button,cancelable,charCode,clientX,clientY,ctrlKey,currentTarget,' +
  329. 'data,detail,eventPhase,fromElement,handler,keyCode,layerX,layerY,metaKey,newValue,offsetX,offsetY,originalTarget,pageX,' +
  330. 'pageY,prevValue,relatedNode,relatedTarget,screenX,screenY,shiftKey,srcElement,target,toElement,view,wheelDelta,which').split(',');
  331. function KEvent(el, event) {
  332. this.init(el, event);
  333. }
  334. _extend(KEvent, {
  335. init : function(el, event) {
  336. var self = this, doc = el.ownerDocument || el.document || el;
  337. self.event = event;
  338. _each(_EVENT_PROPS, function(key, val) {
  339. self[val] = event[val];
  340. });
  341. if (!self.target) {
  342. self.target = self.srcElement || doc;
  343. }
  344. if (self.target.nodeType === 3) {
  345. self.target = self.target.parentNode;
  346. }
  347. if (!self.relatedTarget && self.fromElement) {
  348. self.relatedTarget = self.fromElement === self.target ? self.toElement : self.fromElement;
  349. }
  350. if (self.pageX == null && self.clientX != null) {
  351. var d = doc.documentElement, body = doc.body;
  352. self.pageX = self.clientX + (d && d.scrollLeft || body && body.scrollLeft || 0) - (d && d.clientLeft || body && body.clientLeft || 0);
  353. self.pageY = self.clientY + (d && d.scrollTop || body && body.scrollTop || 0) - (d && d.clientTop || body && body.clientTop || 0);
  354. }
  355. if (!self.which && ((self.charCode || self.charCode === 0) ? self.charCode : self.keyCode)) {
  356. self.which = self.charCode || self.keyCode;
  357. }
  358. if (!self.metaKey && self.ctrlKey) {
  359. self.metaKey = self.ctrlKey;
  360. }
  361. if (!self.which && self.button !== undefined) {
  362. self.which = (self.button & 1 ? 1 : (self.button & 2 ? 3 : (self.button & 4 ? 2 : 0)));
  363. }
  364. switch (self.which) {
  365. case 186 :
  366. self.which = 59;
  367. break;
  368. case 187 :
  369. case 107 :
  370. case 43 :
  371. self.which = 61;
  372. break;
  373. case 189 :
  374. case 45 :
  375. self.which = 109;
  376. break;
  377. case 42 :
  378. self.which = 106;
  379. break;
  380. case 47 :
  381. self.which = 111;
  382. break;
  383. case 78 :
  384. self.which = 110;
  385. break;
  386. }
  387. if (self.which >= 96 && self.which <= 105) {
  388. self.which -= 48;
  389. }
  390. },
  391. preventDefault : function() {
  392. var ev = this.event;
  393. if (ev.preventDefault) {
  394. ev.preventDefault();
  395. }
  396. ev.returnValue = false;
  397. },
  398. stopPropagation : function() {
  399. var ev = this.event;
  400. if (ev.stopPropagation) {
  401. ev.stopPropagation();
  402. }
  403. ev.cancelBubble = true;
  404. },
  405. stop : function() {
  406. this.preventDefault();
  407. this.stopPropagation();
  408. }
  409. });
  410. var _eventExpendo = 'kindeditor_' + _TIME, _eventId = 0, _eventData = {};
  411. function _getId(el) {
  412. return el[_eventExpendo] || null;
  413. }
  414. function _setId(el) {
  415. el[_eventExpendo] = ++_eventId;
  416. return _eventId;
  417. }
  418. function _removeId(el) {
  419. try {
  420. delete el[_eventExpendo];
  421. } catch(e) {
  422. if (el.removeAttribute) {
  423. el.removeAttribute(_eventExpendo);
  424. }
  425. }
  426. }
  427. function _bind(el, type, fn) {
  428. if (type.indexOf(',') >= 0) {
  429. _each(type.split(','), function() {
  430. _bind(el, this, fn);
  431. });
  432. return;
  433. }
  434. var id = _getId(el);
  435. if (!id) {
  436. id = _setId(el);
  437. }
  438. if (_eventData[id] === undefined) {
  439. _eventData[id] = {};
  440. }
  441. var events = _eventData[id][type];
  442. if (events && events.length > 0) {
  443. _unbindEvent(el, type, events[0]);
  444. } else {
  445. _eventData[id][type] = [];
  446. _eventData[id].el = el;
  447. }
  448. events = _eventData[id][type];
  449. if (events.length === 0) {
  450. events[0] = function(e) {
  451. var kevent = e ? new KEvent(el, e) : undefined;
  452. _each(events, function(i, event) {
  453. if (i > 0 && event) {
  454. event.call(el, kevent);
  455. }
  456. });
  457. };
  458. }
  459. if (_inArray(fn, events) < 0) {
  460. events.push(fn);
  461. }
  462. _bindEvent(el, type, events[0]);
  463. }
  464. function _unbind(el, type, fn) {
  465. if (type && type.indexOf(',') >= 0) {
  466. _each(type.split(','), function() {
  467. _unbind(el, this, fn);
  468. });
  469. return;
  470. }
  471. var id = _getId(el);
  472. if (!id) {
  473. return;
  474. }
  475. if (type === undefined) {
  476. if (id in _eventData) {
  477. _each(_eventData[id], function(key, events) {
  478. if (key != 'el' && events.length > 0) {
  479. _unbindEvent(el, key, events[0]);
  480. }
  481. });
  482. delete _eventData[id];
  483. _removeId(el);
  484. }
  485. return;
  486. }
  487. if (!_eventData[id]) {
  488. return;
  489. }
  490. var events = _eventData[id][type];
  491. if (events && events.length > 0) {
  492. if (fn === undefined) {
  493. _unbindEvent(el, type, events[0]);
  494. delete _eventData[id][type];
  495. } else {
  496. _each(events, function(i, event) {
  497. if (i > 0 && event === fn) {
  498. events.splice(i, 1);
  499. }
  500. });
  501. if (events.length == 1) {
  502. _unbindEvent(el, type, events[0]);
  503. delete _eventData[id][type];
  504. }
  505. }
  506. var count = 0;
  507. _each(_eventData[id], function() {
  508. count++;
  509. });
  510. if (count < 2) {
  511. delete _eventData[id];
  512. _removeId(el);
  513. }
  514. }
  515. }
  516. function _fire(el, type) {
  517. if (type.indexOf(',') >= 0) {
  518. _each(type.split(','), function() {
  519. _fire(el, this);
  520. });
  521. return;
  522. }
  523. var id = _getId(el);
  524. if (!id) {
  525. return;
  526. }
  527. var events = _eventData[id][type];
  528. if (_eventData[id] && events && events.length > 0) {
  529. events[0]();
  530. }
  531. }
  532. function _ctrl(el, key, fn) {
  533. var self = this;
  534. key = /^\d{2,}$/.test(key) ? key : key.toUpperCase().charCodeAt(0);
  535. _bind(el, 'keydown', function(e) {
  536. if (e.ctrlKey && e.which == key && !e.shiftKey && !e.altKey) {
  537. fn.call(el);
  538. e.stop();
  539. }
  540. });
  541. }
  542. function _ready(fn) {
  543. var loaded = false;
  544. function readyFunc() {
  545. if (!loaded) {
  546. loaded = true;
  547. fn(KindEditor);
  548. }
  549. }
  550. function ieReadyFunc() {
  551. if (!loaded) {
  552. try {
  553. document.documentElement.doScroll('left');
  554. } catch(e) {
  555. setTimeout(ieReadyFunc, 100);
  556. return;
  557. }
  558. readyFunc();
  559. }
  560. }
  561. function ieReadyStateFunc() {
  562. if (document.readyState === 'complete') {
  563. readyFunc();
  564. }
  565. }
  566. if (document.addEventListener) {
  567. _bind(document, 'DOMContentLoaded', readyFunc);
  568. } else if (document.attachEvent) {
  569. _bind(document, 'readystatechange', ieReadyStateFunc);
  570. if (document.documentElement.doScroll && window.frameElement === undefined) {
  571. ieReadyFunc();
  572. }
  573. }
  574. _bind(window, 'load', readyFunc);
  575. }
  576. if (_IE) {
  577. window.attachEvent('onunload', function() {
  578. _each(_eventData, function(key, events) {
  579. if (events.el) {
  580. _unbind(events.el);
  581. }
  582. });
  583. });
  584. }
  585. K.ctrl = _ctrl;
  586. K.ready = _ready;
  587. function _getCssList(css) {
  588. var list = {},
  589. reg = /\s*([\w\-]+)\s*:([^;]*)(;|$)/g,
  590. match;
  591. while ((match = reg.exec(css))) {
  592. var key = _trim(match[1].toLowerCase()),
  593. val = _trim(_toHex(match[2]));
  594. list[key] = val;
  595. }
  596. return list;
  597. }
  598. function _getAttrList(tag) {
  599. var list = {},
  600. reg = /\s+(?:([\w\-:]+)|(?:([\w\-:]+)=([^\s"'<>]+))|(?:([\w\-:"]+)="([^"]*)")|(?:([\w\-:"]+)='([^']*)'))(?=(?:\s|\/|>)+)/g,
  601. match;
  602. while ((match = reg.exec(tag))) {
  603. var key = (match[1] || match[2] || match[4] || match[6]).toLowerCase(),
  604. val = (match[2] ? match[3] : (match[4] ? match[5] : match[7])) || '';
  605. list[key] = val;
  606. }
  607. return list;
  608. }
  609. function _addClassToTag(tag, className) {
  610. if (/\s+class\s*=/.test(tag)) {
  611. tag = tag.replace(/(\s+class=["']?)([^"']*)(["']?[\s>])/, function($0, $1, $2, $3) {
  612. if ((' ' + $2 + ' ').indexOf(' ' + className + ' ') < 0) {
  613. return $2 === '' ? $1 + className + $3 : $1 + $2 + ' ' + className + $3;
  614. } else {
  615. return $0;
  616. }
  617. });
  618. } else {
  619. tag = tag.substr(0, tag.length - 1) + ' class="' + className + '">';
  620. }
  621. return tag;
  622. }
  623. function _formatCss(css) {
  624. var str = '';
  625. _each(_getCssList(css), function(key, val) {
  626. str += key + ':' + val + ';';
  627. });
  628. return str;
  629. }
  630. function _formatUrl(url, mode, host, pathname) {
  631. mode = _undef(mode, '').toLowerCase();
  632. if (_inArray(mode, ['absolute', 'relative', 'domain']) < 0) {
  633. return url;
  634. }
  635. host = host || location.protocol + '//' + location.host;
  636. if (pathname === undefined) {
  637. var m = location.pathname.match(/^(\/.*)\//);
  638. pathname = m ? m[1] : '';
  639. }
  640. var match;
  641. if ((match = /^(\w+:\/\/[^\/]*)/.exec(url))) {
  642. if (match[1] !== host) {
  643. return url;
  644. }
  645. } else if (/^\w+:/.test(url)) {
  646. return url;
  647. }
  648. function getRealPath(path) {
  649. var parts = path.split('/'), paths = [];
  650. for (var i = 0, len = parts.length; i < len; i++) {
  651. var part = parts[i];
  652. if (part == '..') {
  653. if (paths.length > 0) {
  654. paths.pop();
  655. }
  656. } else if (part !== '' && part != '.') {
  657. paths.push(part);
  658. }
  659. }
  660. return '/' + paths.join('/');
  661. }
  662. if (/^\//.test(url)) {
  663. url = host + getRealPath(url.substr(1));
  664. } else if (!/^\w+:\/\//.test(url)) {
  665. url = host + getRealPath(pathname + '/' + url);
  666. }
  667. function getRelativePath(path, depth) {
  668. if (url.substr(0, path.length) === path) {
  669. var arr = [];
  670. for (var i = 0; i < depth; i++) {
  671. arr.push('..');
  672. }
  673. var prefix = '.';
  674. if (arr.length > 0) {
  675. prefix += '/' + arr.join('/');
  676. }
  677. if (pathname == '/') {
  678. prefix += '/';
  679. }
  680. return prefix + url.substr(path.length);
  681. } else {
  682. if ((match = /^(.*)\//.exec(path))) {
  683. return getRelativePath(match[1], ++depth);
  684. }
  685. }
  686. }
  687. if (mode === 'relative') {
  688. url = getRelativePath(host + pathname, 0).substr(2);
  689. } else if (mode === 'absolute') {
  690. if (url.substr(0, host.length) === host) {
  691. url = url.substr(host.length);
  692. }
  693. }
  694. return url;
  695. }
  696. function _formatHtml(html, htmlTags, urlType, wellFormatted, indentChar) {
  697. urlType = urlType || '';
  698. wellFormatted = _undef(wellFormatted, false);
  699. indentChar = _undef(indentChar, '\t');
  700. var fontSizeList = 'xx-small,x-small,small,medium,large,x-large,xx-large'.split(',');
  701. html = html.replace(/(<(?:pre|pre\s[^>]*)>)([\s\S]*?)(<\/pre>)/ig, function($0, $1, $2, $3) {
  702. return $1 + $2.replace(/<(?:br|br\s[^>]*)>/ig, '\n') + $3;
  703. });
  704. html = html.replace(/<(?:br|br\s[^>]*)\s*\/?>\s*<\/p>/ig, '</p>');
  705. html = html.replace(/(<(?:p|p\s[^>]*)>)\s*(<\/p>)/ig, '$1<br />$2');
  706. html = html.replace(/\u200B/g, '');
  707. var htmlTagMap = {};
  708. if (htmlTags) {
  709. _each(htmlTags, function(key, val) {
  710. var arr = key.split(',');
  711. for (var i = 0, len = arr.length; i < len; i++) {
  712. htmlTagMap[arr[i]] = _toMap(val);
  713. }
  714. });
  715. if (!htmlTagMap.script) {
  716. html = html.replace(/(<(?:script|script\s[^>]*)>)([\s\S]*?)(<\/script>)/ig, '');
  717. }
  718. if (!htmlTagMap.style) {
  719. html = html.replace(/(<(?:style|style\s[^>]*)>)([\s\S]*?)(<\/style>)/ig, '');
  720. }
  721. }
  722. var re = /(\s*)<(\/)?([\w\-:]+)((?:\s+|(?:\s+[\w\-:]+)|(?:\s+[\w\-:]+=[^\s"'<>]+)|(?:\s+[\w\-:"]+="[^"]*")|(?:\s+[\w\-:"]+='[^']*'))*)(\/)?>(\s*)/g;
  723. var tagStack = [];
  724. html = html.replace(re, function($0, $1, $2, $3, $4, $5, $6) {
  725. var full = $0,
  726. startNewline = $1 || '',
  727. startSlash = $2 || '',
  728. tagName = $3.toLowerCase(),
  729. attr = $4 || '',
  730. endSlash = $5 ? ' ' + $5 : '',
  731. endNewline = $6 || '';
  732. if (htmlTags && !htmlTagMap[tagName]) {
  733. return '';
  734. }
  735. if (endSlash === '' && _SINGLE_TAG_MAP[tagName]) {
  736. endSlash = ' /';
  737. }
  738. if (_INLINE_TAG_MAP[tagName]) {
  739. if (startNewline) {
  740. startNewline = ' ';
  741. }
  742. if (endNewline) {
  743. endNewline = ' ';
  744. }
  745. }
  746. if (_PRE_TAG_MAP[tagName]) {
  747. if (startSlash) {
  748. endNewline = '\n';
  749. } else {
  750. startNewline = '\n';
  751. }
  752. }
  753. if (wellFormatted && tagName == 'br') {
  754. endNewline = '\n';
  755. }
  756. if (_BLOCK_TAG_MAP[tagName] && !_PRE_TAG_MAP[tagName]) {
  757. if (wellFormatted) {
  758. if (startSlash && tagStack.length > 0 && tagStack[tagStack.length - 1] === tagName) {
  759. tagStack.pop();
  760. } else {
  761. tagStack.push(tagName);
  762. }
  763. startNewline = '\n';
  764. endNewline = '\n';
  765. for (var i = 0, len = startSlash ? tagStack.length : tagStack.length - 1; i < len; i++) {
  766. startNewline += indentChar;
  767. if (!startSlash) {
  768. endNewline += indentChar;
  769. }
  770. }
  771. if (endSlash) {
  772. tagStack.pop();
  773. } else if (!startSlash) {
  774. endNewline += indentChar;
  775. }
  776. } else {
  777. startNewline = endNewline = '';
  778. }
  779. }
  780. if (attr !== '') {
  781. var attrMap = _getAttrList(full);
  782. if (tagName === 'font') {
  783. var fontStyleMap = {}, fontStyle = '';
  784. _each(attrMap, function(key, val) {
  785. if (key === 'color') {
  786. fontStyleMap.color = val;
  787. delete attrMap[key];
  788. }
  789. if (key === 'size') {
  790. fontStyleMap['font-size'] = fontSizeList[parseInt(val, 10) - 1] || '';
  791. delete attrMap[key];
  792. }
  793. if (key === 'face') {
  794. fontStyleMap['font-family'] = val;
  795. delete attrMap[key];
  796. }
  797. if (key === 'style') {
  798. fontStyle = val;
  799. }
  800. });
  801. if (fontStyle && !/;$/.test(fontStyle)) {
  802. fontStyle += ';';
  803. }
  804. _each(fontStyleMap, function(key, val) {
  805. if (val === '') {
  806. return;
  807. }
  808. if (/\s/.test(val)) {
  809. val = "'" + val + "'";
  810. }
  811. fontStyle += key + ':' + val + ';';
  812. });
  813. attrMap.style = fontStyle;
  814. }
  815. _each(attrMap, function(key, val) {
  816. if (_FILL_ATTR_MAP[key]) {
  817. attrMap[key] = key;
  818. }
  819. if (_inArray(key, ['src', 'href']) >= 0) {
  820. attrMap[key] = _formatUrl(val, urlType);
  821. }
  822. if (htmlTags && key !== 'style' && !htmlTagMap[tagName]['*'] && !htmlTagMap[tagName][key] ||
  823. tagName === 'body' && key === 'contenteditable' ||
  824. /^kindeditor_\d+$/.test(key)) {
  825. delete attrMap[key];
  826. }
  827. if (key === 'style' && val !== '') {
  828. var styleMap = _getCssList(val);
  829. _each(styleMap, function(k, v) {
  830. if (htmlTags && !htmlTagMap[tagName].style && !htmlTagMap[tagName]['.' + k]) {
  831. delete styleMap[k];
  832. }
  833. });
  834. var style = '';
  835. _each(styleMap, function(k, v) {
  836. style += k + ':' + v + ';';
  837. });
  838. attrMap.style = style;
  839. }
  840. });
  841. attr = '';
  842. _each(attrMap, function(key, val) {
  843. if (key === 'style' && val === '') {
  844. return;
  845. }
  846. val = val.replace(/"/g, '&quot;');
  847. attr += ' ' + key + '="' + val + '"';
  848. });
  849. }
  850. if (tagName === 'font') {
  851. tagName = 'span';
  852. }
  853. return startNewline + '<' + startSlash + tagName + attr + endSlash + '>' + endNewline;
  854. });
  855. html = html.replace(/(<(?:pre|pre\s[^>]*)>)([\s\S]*?)(<\/pre>)/ig, function($0, $1, $2, $3) {
  856. return $1 + $2.replace(/\n/g, '<span id="__kindeditor_pre_newline__">\n') + $3;
  857. });
  858. html = html.replace(/\n\s*\n/g, '\n');
  859. html = html.replace(/<span id="__kindeditor_pre_newline__">\n/g, '\n');
  860. return _trim(html);
  861. }
  862. function _clearMsWord(html, htmlTags) {
  863. html = html.replace(/<meta[\s\S]*?>/ig, '')
  864. .replace(/<![\s\S]*?>/ig, '')
  865. .replace(/<style[^>]*>[\s\S]*?<\/style>/ig, '')
  866. .replace(/<script[^>]*>[\s\S]*?<\/script>/ig, '')
  867. .replace(/<w:[^>]+>[\s\S]*?<\/w:[^>]+>/ig, '')
  868. .replace(/<o:[^>]+>[\s\S]*?<\/o:[^>]+>/ig, '')
  869. .replace(/<xml>[\s\S]*?<\/xml>/ig, '')
  870. .replace(/<(?:table|td)[^>]*>/ig, function(full) {
  871. return full.replace(/border-bottom:([#\w\s]+)/ig, 'border:$1');
  872. });
  873. return _formatHtml(html, htmlTags);
  874. }
  875. function _mediaType(src) {
  876. if (/\.(rm|rmvb)(\?|$)/i.test(src)) {
  877. return 'audio/x-pn-realaudio-plugin';
  878. }
  879. if (/\.(swf|flv)(\?|$)/i.test(src)) {
  880. return 'application/x-shockwave-flash';
  881. }
  882. return 'video/x-ms-asf-plugin';
  883. }
  884. function _mediaClass(type) {
  885. if (/realaudio/i.test(type)) {
  886. return 'ke-rm';
  887. }
  888. if (/flash/i.test(type)) {
  889. return 'ke-flash';
  890. }
  891. return 'ke-media';
  892. }
  893. function _mediaAttrs(srcTag) {
  894. return _getAttrList(unescape(srcTag));
  895. }
  896. function _mediaEmbed(attrs) {
  897. var html = '<embed ';
  898. _each(attrs, function(key, val) {
  899. html += key + '="' + val + '" ';
  900. });
  901. html += '/>';
  902. return html;
  903. }
  904. function _mediaImg(blankPath, attrs) {
  905. var width = attrs.width,
  906. height = attrs.height,
  907. type = attrs.type || _mediaType(attrs.src),
  908. srcTag = _mediaEmbed(attrs),
  909. style = '';
  910. if (width > 0) {
  911. style += 'width:' + width + 'px;';
  912. }
  913. if (height > 0) {
  914. style += 'height:' + height + 'px;';
  915. }
  916. var html = '<img class="' + _mediaClass(type) + '" src="' + blankPath + '" ';
  917. if (style !== '') {
  918. html += 'style="' + style + '" ';
  919. }
  920. html += 'data-ke-tag="' + escape(srcTag) + '" alt="" />';
  921. return html;
  922. }
  923. K.formatUrl = _formatUrl;
  924. K.formatHtml = _formatHtml;
  925. K.getCssList = _getCssList;
  926. K.getAttrList = _getAttrList;
  927. K.mediaType = _mediaType;
  928. K.mediaAttrs = _mediaAttrs;
  929. K.mediaEmbed = _mediaEmbed;
  930. K.mediaImg = _mediaImg;
  931. K.clearMsWord = _clearMsWord;
  932. function _contains(nodeA, nodeB) {
  933. if (nodeA.nodeType == 9 && nodeB.nodeType != 9) {
  934. return true;
  935. }
  936. while ((nodeB = nodeB.parentNode)) {
  937. if (nodeB == nodeA) {
  938. return true;
  939. }
  940. }
  941. return false;
  942. }
  943. function _getAttr(el, key) {
  944. key = key.toLowerCase();
  945. var val = null;
  946. if (_IE && _V < 8 && el.nodeName.toLowerCase() != 'script') {
  947. var div = el.ownerDocument.createElement('div');
  948. div.appendChild(el.cloneNode(false));
  949. var list = _getAttrList(_unescape(div.innerHTML));
  950. if (key in list) {
  951. val = list[key];
  952. }
  953. } else {
  954. try {
  955. val = el.getAttribute(key, 2);
  956. } catch(e) {
  957. val = el.getAttribute(key, 1);
  958. }
  959. }
  960. if (key === 'style' && val !== null) {
  961. val = _formatCss(val);
  962. }
  963. return val;
  964. }
  965. function _queryAll(expr, root) {
  966. var exprList = expr.split(',');
  967. if (exprList.length > 1) {
  968. var mergedResults = [];
  969. _each(exprList, function() {
  970. _each(_queryAll(this, root), function() {
  971. if (_inArray(this, mergedResults) < 0) {
  972. mergedResults.push(this);
  973. }
  974. });
  975. });
  976. return mergedResults;
  977. }
  978. root = root || document;
  979. function escape(str) {
  980. if (typeof str != 'string') {
  981. return str;
  982. }
  983. return str.replace(/([^\w\-])/g, '\\$1');
  984. }
  985. function stripslashes(str) {
  986. return str.replace(/\\/g, '');
  987. }
  988. function cmpTag(tagA, tagB) {
  989. return tagA === '*' || tagA.toLowerCase() === escape(tagB.toLowerCase());
  990. }
  991. function byId(id, tag, root) {
  992. var arr = [],
  993. doc = root.ownerDocument || root,
  994. el = doc.getElementById(stripslashes(id));
  995. if (el) {
  996. if (cmpTag(tag, el.nodeName) && _contains(root, el)) {
  997. arr.push(el);
  998. }
  999. }
  1000. return arr;
  1001. }
  1002. function byClass(className, tag, root) {
  1003. var doc = root.ownerDocument || root, arr = [], els, i, len, el;
  1004. if (root.getElementsByClassName) {
  1005. els = root.getElementsByClassName(stripslashes(className));
  1006. for (i = 0, len = els.length; i < len; i++) {
  1007. el = els[i];
  1008. if (cmpTag(tag, el.nodeName)) {
  1009. arr.push(el);
  1010. }
  1011. }
  1012. } else if (doc.querySelectorAll) {
  1013. els = doc.querySelectorAll((root.nodeName !== '#document' ? root.nodeName + ' ' : '') + tag + '.' + className);
  1014. for (i = 0, len = els.length; i < len; i++) {
  1015. el = els[i];
  1016. if (_contains(root, el)) {
  1017. arr.push(el);
  1018. }
  1019. }
  1020. } else {
  1021. els = root.getElementsByTagName(tag);
  1022. className = ' ' + className + ' ';
  1023. for (i = 0, len = els.length; i < len; i++) {
  1024. el = els[i];
  1025. if (el.nodeType == 1) {
  1026. var cls = el.className;
  1027. if (cls && (' ' + cls + ' ').indexOf(className) > -1) {
  1028. arr.push(el);
  1029. }
  1030. }
  1031. }
  1032. }
  1033. return arr;
  1034. }
  1035. function byName(name, tag, root) {
  1036. var arr = [], doc = root.ownerDocument || root,
  1037. els = doc.getElementsByName(stripslashes(name)), el;
  1038. for (var i = 0, len = els.length; i < len; i++) {
  1039. el = els[i];
  1040. if (cmpTag(tag, el.nodeName) && _contains(root, el)) {
  1041. if (el.getAttributeNode('name')) {
  1042. arr.push(el);
  1043. }
  1044. }
  1045. }
  1046. return arr;
  1047. }
  1048. function byAttr(key, val, tag, root) {
  1049. var arr = [], els = root.getElementsByTagName(tag), el;
  1050. for (var i = 0, len = els.length; i < len; i++) {
  1051. el = els[i];
  1052. if (el.nodeType == 1) {
  1053. if (val === null) {
  1054. if (_getAttr(el, key) !== null) {
  1055. arr.push(el);
  1056. }
  1057. } else {
  1058. if (val === escape(_getAttr(el, key))) {
  1059. arr.push(el);
  1060. }
  1061. }
  1062. }
  1063. }
  1064. return arr;
  1065. }
  1066. function select(expr, root) {
  1067. var arr = [], matches;
  1068. matches = /^((?:\\.|[^.#\s\[<>])+)/.exec(expr);
  1069. var tag = matches ? matches[1] : '*';
  1070. if ((matches = /#((?:[\w\-]|\\.)+)$/.exec(expr))) {
  1071. arr = byId(matches[1], tag, root);
  1072. } else if ((matches = /\.((?:[\w\-]|\\.)+)$/.exec(expr))) {
  1073. arr = byClass(matches[1], tag, root);
  1074. } else if ((matches = /\[((?:[\w\-]|\\.)+)\]/.exec(expr))) {
  1075. arr = byAttr(matches[1].toLowerCase(), null, tag, root);
  1076. } else if ((matches = /\[((?:[\w\-]|\\.)+)\s*=\s*['"]?((?:\\.|[^'"]+)+)['"]?\]/.exec(expr))) {
  1077. var key = matches[1].toLowerCase(), val = matches[2];
  1078. if (key === 'id') {
  1079. arr = byId(val, tag, root);
  1080. } else if (key === 'class') {
  1081. arr = byClass(val, tag, root);
  1082. } else if (key === 'name') {
  1083. arr = byName(val, tag, root);
  1084. } else {
  1085. arr = byAttr(key, val, tag, root);
  1086. }
  1087. } else {
  1088. var els = root.getElementsByTagName(tag), el;
  1089. for (var i = 0, len = els.length; i < len; i++) {
  1090. el = els[i];
  1091. if (el.nodeType == 1) {
  1092. arr.push(el);
  1093. }
  1094. }
  1095. }
  1096. return arr;
  1097. }
  1098. var parts = [], arr, re = /((?:\\.|[^\s>])+|[\s>])/g;
  1099. while ((arr = re.exec(expr))) {
  1100. if (arr[1] !== ' ') {
  1101. parts.push(arr[1]);
  1102. }
  1103. }
  1104. var results = [];
  1105. if (parts.length == 1) {
  1106. return select(parts[0], root);
  1107. }
  1108. var isChild = false, part, els, subResults, val, v, i, j, k, length, len, l;
  1109. for (i = 0, lenth = parts.length; i < lenth; i++) {
  1110. part = parts[i];
  1111. if (part === '>') {
  1112. isChild = true;
  1113. continue;
  1114. }
  1115. if (i > 0) {
  1116. els = [];
  1117. for (j = 0, len = results.length; j < len; j++) {
  1118. val = results[j];
  1119. subResults = select(part, val);
  1120. for (k = 0, l = subResults.length; k < l; k++) {
  1121. v = subResults[k];
  1122. if (isChild) {
  1123. if (val === v.parentNode) {
  1124. els.push(v);
  1125. }
  1126. } else {
  1127. els.push(v);
  1128. }
  1129. }
  1130. }
  1131. results = els;
  1132. } else {
  1133. results = select(part, root);
  1134. }
  1135. if (results.length === 0) {
  1136. return [];
  1137. }
  1138. }
  1139. return results;
  1140. }
  1141. function _query(expr, root) {
  1142. var arr = _queryAll(expr, root);
  1143. return arr.length > 0 ? arr[0] : null;
  1144. }
  1145. K.query = _query;
  1146. K.queryAll = _queryAll;
  1147. function _get(val) {
  1148. return K(val)[0];
  1149. }
  1150. function _getDoc(node) {
  1151. if (!node) {
  1152. return document;
  1153. }
  1154. return node.ownerDocument || node.document || node;
  1155. }
  1156. function _getWin(node) {
  1157. if (!node) {
  1158. return window;
  1159. }
  1160. var doc = _getDoc(node);
  1161. return doc.parentWindow || doc.defaultView;
  1162. }
  1163. function _setHtml(el, html) {
  1164. if (el.nodeType != 1) {
  1165. return;
  1166. }
  1167. var doc = _getDoc(el);
  1168. try {
  1169. el.innerHTML = '<img id="__kindeditor_temp_tag__" width="0" height="0" style="display:none;" />' + html;
  1170. var temp = doc.getElementById('__kindeditor_temp_tag__');
  1171. temp.parentNode.removeChild(temp);
  1172. } catch(e) {
  1173. K(el).empty();
  1174. K('@' + html, doc).each(function() {
  1175. el.appendChild(this);
  1176. });
  1177. }
  1178. }
  1179. function _hasClass(el, cls) {
  1180. return _inString(cls, el.className, ' ');
  1181. }
  1182. function _setAttr(el, key, val) {
  1183. if (_IE && _V < 8 && key.toLowerCase() == 'class') {
  1184. key = 'className';
  1185. }
  1186. el.setAttribute(key, '' + val);
  1187. }
  1188. function _removeAttr(el, key) {
  1189. if (_IE && _V < 8 && key.toLowerCase() == 'class') {
  1190. key = 'className';
  1191. }
  1192. _setAttr(el, key, '');
  1193. el.removeAttribute(key);
  1194. }
  1195. function _getNodeName(node) {
  1196. if (!node || !node.nodeName) {
  1197. return '';
  1198. }
  1199. return node.nodeName.toLowerCase();
  1200. }
  1201. function _computedCss(el, key) {
  1202. var self = this, win = _getWin(el), camelKey = _toCamel(key), val = '';
  1203. if (win.getComputedStyle) {
  1204. var style = win.getComputedStyle(el, null);
  1205. val = style[camelKey] || style.getPropertyValue(key) || el.style[camelKey];
  1206. } else if (el.currentStyle) {
  1207. val = el.currentStyle[camelKey] || el.style[camelKey];
  1208. }
  1209. return val;
  1210. }
  1211. function _hasVal(node) {
  1212. return !!_VALUE_TAG_MAP[_getNodeName(node)];
  1213. }
  1214. function _docElement(doc) {
  1215. doc = doc || document;
  1216. return _QUIRKS ? doc.body : doc.documentElement;
  1217. }
  1218. function _docHeight(doc) {
  1219. var el = _docElement(doc);
  1220. return Math.max(el.scrollHeight, el.clientHeight);
  1221. }
  1222. function _docWidth(doc) {
  1223. var el = _docElement(doc);
  1224. return Math.max(el.scrollWidth, el.clientWidth);
  1225. }
  1226. function _getScrollPos(doc) {
  1227. doc = doc || document;
  1228. var x, y;
  1229. if (_IE || _OPERA) {
  1230. x = _docElement(doc).scrollLeft;
  1231. y = _docElement(doc).scrollTop;
  1232. } else {
  1233. x = _getWin(doc).scrollX;
  1234. y = _getWin(doc).scrollY;
  1235. }
  1236. return {x : x, y : y};
  1237. }
  1238. function KNode(node) {
  1239. this.init(node);
  1240. }
  1241. _extend(KNode, {
  1242. init : function(node) {
  1243. var self = this;
  1244. for (var i = 0, len = node.length; i < len; i++) {
  1245. self[i] = node[i].constructor === KNode ? node[i][0] : node[i];
  1246. }
  1247. self.length = node.length;
  1248. self.doc = _getDoc(self[0]);
  1249. self.name = _getNodeName(self[0]);
  1250. self.type = self.length > 0 ? self[0].nodeType : null;
  1251. self.win = _getWin(self[0]);
  1252. self._data = {};
  1253. },
  1254. each : function(fn) {
  1255. var self = this;
  1256. for (var i = 0; i < self.length; i++) {
  1257. if (fn.call(self[i], i, self[i]) === false) {
  1258. return self;
  1259. }
  1260. }
  1261. return self;
  1262. },
  1263. bind : function(type, fn) {
  1264. this.each(function() {
  1265. _bind(this, type, fn);
  1266. });
  1267. return this;
  1268. },
  1269. unbind : function(type, fn) {
  1270. this.each(function() {
  1271. _unbind(this, type, fn);
  1272. });
  1273. return this;
  1274. },
  1275. fire : function(type) {
  1276. if (this.length < 1) {
  1277. return this;
  1278. }
  1279. _fire(this[0], type);
  1280. return this;
  1281. },
  1282. hasAttr : function(key) {
  1283. if (this.length < 1) {
  1284. return false;
  1285. }
  1286. return !!_getAttr(this[0], key);
  1287. },
  1288. attr : function(key, val) {
  1289. var self = this;
  1290. if (key === undefined) {
  1291. return _getAttrList(self.outer());
  1292. }
  1293. if (typeof key === 'object') {
  1294. _each(key, function(k, v) {
  1295. self.attr(k, v);
  1296. });
  1297. return self;
  1298. }
  1299. if (val === undefined) {
  1300. val = self.length < 1 ? null : _getAttr(self[0], key);
  1301. return val === null ? '' : val;
  1302. }
  1303. self.each(function() {
  1304. _setAttr(this, key, val);
  1305. });
  1306. return self;
  1307. },
  1308. removeAttr : function(key) {
  1309. this.each(function() {
  1310. _removeAttr(this, key);
  1311. });
  1312. return this;
  1313. },
  1314. get : function(i) {
  1315. if (this.length < 1) {
  1316. return null;
  1317. }
  1318. return this[i || 0];
  1319. },
  1320. hasClass : function(cls) {
  1321. if (this.length < 1) {
  1322. return false;
  1323. }
  1324. return _hasClass(this[0], cls);
  1325. },
  1326. addClass : function(cls) {
  1327. this.each(function() {
  1328. if (!_hasClass(this, cls)) {
  1329. this.className = _trim(this.className + ' ' + cls);
  1330. }
  1331. });
  1332. return this;
  1333. },
  1334. removeClass : function(cls) {
  1335. this.each(function() {
  1336. if (_hasClass(this, cls)) {
  1337. this.className = _trim(this.className.replace(new RegExp('(^|\\s)' + cls + '(\\s|$)'), ' '));
  1338. }
  1339. });
  1340. return this;
  1341. },
  1342. html : function(val) {
  1343. var self = this;
  1344. if (val === undefined) {
  1345. if (self.length < 1 || self.type != 1) {
  1346. return '';
  1347. }
  1348. return _formatHtml(self[0].innerHTML);
  1349. }
  1350. self.each(function() {
  1351. _setHtml(this, val);
  1352. });
  1353. return self;
  1354. },
  1355. text : function() {
  1356. var self = this;
  1357. if (self.length < 1) {
  1358. return '';
  1359. }
  1360. return _IE ? self[0].innerText : self[0].textContent;
  1361. },
  1362. hasVal : function() {
  1363. if (this.length < 1) {
  1364. return false;
  1365. }
  1366. return _hasVal(this[0]);
  1367. },
  1368. val : function(val) {
  1369. var self = this;
  1370. if (val === undefined) {
  1371. if (self.length < 1) {
  1372. return '';
  1373. }
  1374. return self.hasVal() ? self[0].value : self.attr('value');
  1375. } else {
  1376. self.each(function() {
  1377. if (_hasVal(this)) {
  1378. this.value = val;
  1379. } else {
  1380. _setAttr(this, 'value' , val);
  1381. }
  1382. });
  1383. return self;
  1384. }
  1385. },
  1386. css : function(key, val) {
  1387. var self = this;
  1388. if (key === undefined) {
  1389. return _getCssList(self.attr('style'));
  1390. }
  1391. if (typeof key === 'object') {
  1392. _each(key, function(k, v) {
  1393. self.css(k, v);
  1394. });
  1395. return self;
  1396. }
  1397. if (val === undefined) {
  1398. if (self.length < 1) {
  1399. return '';
  1400. }
  1401. return self[0].style[_toCamel(key)] || _computedCss(self[0], key) || '';
  1402. }
  1403. self.each(function() {
  1404. this.style[_toCamel(key)] = val;
  1405. });
  1406. return self;
  1407. },
  1408. width : function(val) {
  1409. var self = this;
  1410. if (val === undefined) {
  1411. if (self.length < 1) {
  1412. return 0;
  1413. }
  1414. return self[0].offsetWidth;
  1415. }
  1416. return self.css('width', _addUnit(val));
  1417. },
  1418. height : function(val) {
  1419. var self = this;
  1420. if (val === undefined) {
  1421. if (self.length < 1) {
  1422. return 0;
  1423. }
  1424. return self[0].offsetHeight;
  1425. }
  1426. return self.css('height', _addUnit(val));
  1427. },
  1428. opacity : function(val) {
  1429. this.each(function() {
  1430. if (this.style.opacity === undefined) {
  1431. this.style.filter = val == 1 ? '' : 'alpha(opacity=' + (val * 100) + ')';
  1432. } else {
  1433. this.style.opacity = val == 1 ? '' : val;
  1434. }
  1435. });
  1436. return this;
  1437. },
  1438. data : function(key, val) {
  1439. var self = this;
  1440. if (val === undefined) {
  1441. return self._data[key];
  1442. }
  1443. self._data[key] = val;
  1444. return self;
  1445. },
  1446. pos : function() {
  1447. var self = this, node = self[0], x = 0, y = 0;
  1448. if (node) {
  1449. if (node.getBoundingClientRect) {
  1450. var box = node.getBoundingClientRect(),
  1451. pos = _getScrollPos(self.doc);
  1452. x = box.left + pos.x;
  1453. y = box.top + pos.y;
  1454. } else {
  1455. while (node) {
  1456. x += node.offsetLeft;
  1457. y += node.offsetTop;
  1458. node = node.offsetParent;
  1459. }
  1460. }
  1461. }
  1462. return {x : _round(x), y : _round(y)};
  1463. },
  1464. clone : function(bool) {
  1465. if (this.length < 1) {
  1466. return new KNode([]);
  1467. }
  1468. return new KNode([this[0].cloneNode(bool)]);
  1469. },
  1470. append : function(expr) {
  1471. this.each(function() {
  1472. if (this.appendChild) {
  1473. this.appendChild(_get(expr));
  1474. }
  1475. });
  1476. return this;
  1477. },
  1478. appendTo : function(expr) {
  1479. this.each(function() {
  1480. _get(expr).appendChild(this);
  1481. });
  1482. return this;
  1483. },
  1484. before : function(expr) {
  1485. this.each(function() {
  1486. this.parentNode.insertBefore(_get(expr), this);
  1487. });
  1488. return this;
  1489. },
  1490. after : function(expr) {
  1491. this.each(function() {
  1492. if (this.nextSibling) {
  1493. this.parentNode.insertBefore(_get(expr), this.nextSibling);
  1494. } else {
  1495. this.parentNode.appendChild(_get(expr));
  1496. }
  1497. });
  1498. return this;
  1499. },
  1500. replaceWith : function(expr) {
  1501. var nodes = [];
  1502. this.each(function(i, node) {
  1503. _unbind(node);
  1504. var newNode = _get(expr);
  1505. node.parentNode.replaceChild(newNode, node);
  1506. nodes.push(newNode);
  1507. });
  1508. return K(nodes);
  1509. },
  1510. empty : function() {
  1511. var self = this;
  1512. self.each(function(i, node) {
  1513. var child = node.firstChild;
  1514. while (child) {
  1515. if (!node.parentNode) {
  1516. return;
  1517. }
  1518. var next = child.nextSibling;
  1519. child.parentNode.removeChild(child);
  1520. child = next;
  1521. }
  1522. });
  1523. return self;
  1524. },
  1525. remove : function(keepChilds) {
  1526. var self = this;
  1527. self.each(function(i, node) {
  1528. if (!node.parentNode) {
  1529. return;
  1530. }
  1531. _unbind(node);
  1532. if (keepChilds) {
  1533. var child = node.firstChild;
  1534. while (child) {
  1535. var next = child.nextSibling;
  1536. node.parentNode.insertBefore(child, node);
  1537. child = next;
  1538. }
  1539. }
  1540. node.parentNode.removeChild(node);
  1541. delete self[i];
  1542. });
  1543. self.length = 0;
  1544. self._data = {};
  1545. return self;
  1546. },
  1547. show : function(val) {
  1548. return this.css('display', val === undefined ? 'block' : val);
  1549. },
  1550. hide : function() {
  1551. return this.css('display', 'none');
  1552. },
  1553. outer : function() {
  1554. var self = this;
  1555. if (self.length < 1) {
  1556. return '';
  1557. }
  1558. var div = self.doc.createElement('div'), html;
  1559. div.appendChild(self[0].cloneNode(true));
  1560. html = _formatHtml(div.innerHTML);
  1561. div = null;
  1562. return html;
  1563. },
  1564. isSingle : function() {
  1565. return !!_SINGLE_TAG_MAP[this.name];
  1566. },
  1567. isInline : function() {
  1568. return !!_INLINE_TAG_MAP[this.name];
  1569. },
  1570. isBlock : function() {
  1571. return !!_BLOCK_TAG_MAP[this.name];
  1572. },
  1573. isStyle : function() {
  1574. return !!_STYLE_TAG_MAP[this.name];
  1575. },
  1576. isControl : function() {
  1577. return !!_CONTROL_TAG_MAP[this.name];
  1578. },
  1579. contains : function(otherNode) {
  1580. if (this.length < 1) {
  1581. return false;
  1582. }
  1583. return _contains(this[0], _get(otherNode));
  1584. },
  1585. parent : function() {
  1586. if (this.length < 1) {
  1587. return null;
  1588. }
  1589. var node = this[0].parentNode;
  1590. return node ? new KNode([node]) : null;
  1591. },
  1592. children : function() {
  1593. if (this.length < 1) {
  1594. return [];
  1595. }
  1596. var list = [], child = this[0].firstChild;
  1597. while (child) {
  1598. if (child.nodeType != 3 || _trim(child.nodeValue) !== '') {
  1599. list.push(new KNode([child]));
  1600. }
  1601. child = child.nextSibling;
  1602. }
  1603. return list;
  1604. },
  1605. first : function() {
  1606. var list = this.children();
  1607. return list.length > 0 ? list[0] : null;
  1608. },
  1609. last : function() {
  1610. var list = this.children();
  1611. return list.length > 0 ? list[list.length - 1] : null;
  1612. },
  1613. index : function() {
  1614. if (this.length < 1) {
  1615. return -1;
  1616. }
  1617. var i = -1, sibling = this[0];
  1618. while (sibling) {
  1619. i++;
  1620. sibling = sibling.previousSibling;
  1621. }
  1622. return i;
  1623. },
  1624. prev : function() {
  1625. if (this.length < 1) {
  1626. return null;
  1627. }
  1628. var node = this[0].previousSibling;
  1629. return node ? new KNode([node]) : null;
  1630. },
  1631. next : function() {
  1632. if (this.length < 1) {
  1633. return null;
  1634. }
  1635. var node = this[0].nextSibling;
  1636. return node ? new KNode([node]) : null;
  1637. },
  1638. scan : function(fn, order) {
  1639. if (this.length < 1) {
  1640. return;
  1641. }
  1642. order = (order === undefined) ? true : order;
  1643. function walk(node) {
  1644. var n = order ? node.firstChild : node.lastChild;
  1645. while (n) {
  1646. var next = order ? n.nextSibling : n.previousSibling;
  1647. if (fn(n) === false) {
  1648. return false;
  1649. }
  1650. if (walk(n) === false) {
  1651. return false;
  1652. }
  1653. n = next;
  1654. }
  1655. }
  1656. walk(this[0]);
  1657. return this;
  1658. }
  1659. });
  1660. _each(('blur,focus,focusin,focusout,load,resize,scroll,unload,click,dblclick,' +
  1661. 'mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,' +
  1662. 'change,select,submit,keydown,keypress,keyup,error,contextmenu').split(','), function(i, type) {
  1663. KNode.prototype[type] = function(fn) {
  1664. return fn ? this.bind(type, fn) : this.fire(type);
  1665. };
  1666. });
  1667. var _K = K;
  1668. K = function(expr, root) {
  1669. if (expr === undefined || expr === null) {
  1670. return;
  1671. }
  1672. function newNode(node) {
  1673. if (!node[0]) {
  1674. node = [];
  1675. }
  1676. return new KNode(node);
  1677. }
  1678. if (typeof expr === 'string') {
  1679. if (root) {
  1680. root = _get(root);
  1681. }
  1682. var length = expr.length;
  1683. if (expr.charAt(0) === '@') {
  1684. expr = expr.substr(1);
  1685. }
  1686. if (expr.length !== length || /<.+>/.test(expr)) {
  1687. var doc = root ? root.ownerDocument || root : document,
  1688. div = doc.createElement('div'), list = [];
  1689. div.innerHTML = '<img id="__kindeditor_temp_tag__" width="0" height="0" style="display:none;" />' + expr;
  1690. for (var i = 0, len = div.childNodes.length; i < len; i++) {
  1691. var child = div.childNodes[i];
  1692. if (child.id == '__kindeditor_temp_tag__') {
  1693. continue;
  1694. }
  1695. list.push(child);
  1696. }
  1697. return newNode(list);
  1698. }
  1699. return newNode(_queryAll(expr, root));
  1700. }
  1701. if (expr && expr.constructor === KNode) {
  1702. return expr;
  1703. }
  1704. if (_isArray(expr)) {
  1705. return newNode(expr);
  1706. }
  1707. return newNode(_toArray(arguments));
  1708. };
  1709. _each(_K, function(key, val) {
  1710. K[key] = val;
  1711. });
  1712. window.KindEditor = K;
  1713. var _START_TO_START = 0,
  1714. _START_TO_END = 1,
  1715. _END_TO_END = 2,
  1716. _END_TO_START = 3,
  1717. _BOOKMARK_ID = 0;
  1718. function _updateCollapsed(range) {
  1719. range.collapsed = (range.startContainer === range.endContainer && range.startOffset === range.endOffset);
  1720. return range;
  1721. }
  1722. function _copyAndDelete(range, isCopy, isDelete) {
  1723. var doc = range.doc, nodeList = [];
  1724. function splitTextNode(node, startOffset, endOffset) {
  1725. var length = node.nodeValue.length, centerNode;
  1726. if (isCopy) {
  1727. var cloneNode = node.cloneNode(true);
  1728. if (startOffset > 0) {
  1729. centerNode = cloneNode.splitText(startOffset);
  1730. } else {
  1731. centerNode = cloneNode;
  1732. }
  1733. if (endOffset < length) {
  1734. centerNode.splitText(endOffset - startOffset);
  1735. }
  1736. }
  1737. if (isDelete) {
  1738. var center = node;
  1739. if (startOffset > 0) {
  1740. center = node.splitText(startOffset);
  1741. range.setStart(node, startOffset);
  1742. }
  1743. if (endOffset < length) {
  1744. var right = center.splitText(endOffset - startOffset);
  1745. range.setEnd(right, 0);
  1746. }
  1747. nodeList.push(center);
  1748. }
  1749. return centerNode;
  1750. }
  1751. function removeNodes() {
  1752. if (isDelete) {
  1753. range.up().collapse(true);
  1754. }
  1755. for (var i = 0, len = nodeList.length; i < len; i++) {
  1756. var node = nodeList[i];
  1757. if (node.parentNode) {
  1758. node.parentNode.removeChild(node);
  1759. }
  1760. }
  1761. }
  1762. var copyRange = range.cloneRange().down();
  1763. var start = -1, incStart = -1, incEnd = -1, end = -1,
  1764. ancestor = range.commonAncestor(), frag = doc.createDocumentFragment();
  1765. if (ancestor.nodeType == 3) {
  1766. var textNode = splitTextNode(ancestor, range.startOffset, range.endOffset);
  1767. if (isCopy) {
  1768. frag.appendChild(textNode);
  1769. }
  1770. removeNodes();
  1771. return isCopy ? frag : range;
  1772. }
  1773. function extractNodes(parent, frag) {
  1774. var node = parent.firstChild, nextNode;
  1775. while (node) {
  1776. var testRange = new KRange(doc).selectNode(node);
  1777. start = testRange.compareBoundaryPoints(_START_TO_END, range);
  1778. if (start >= 0 && incStart <= 0) {
  1779. incStart = testRange.compareBoundaryPoints(_START_TO_START, range);
  1780. }
  1781. if (incStart >= 0 && incEnd <= 0) {
  1782. incEnd = testRange.compareBoundaryPoints(_END_TO_END, range);
  1783. }
  1784. if (incEnd >= 0 && end <= 0) {
  1785. end = testRange.compareBoundaryPoints(_END_TO_START, range);
  1786. }
  1787. if (end >= 0) {
  1788. return false;
  1789. }
  1790. nextNode = node.nextSibling;
  1791. if (start > 0) {
  1792. if (node.nodeType == 1) {
  1793. if (incStart >= 0 && incEnd <= 0) {
  1794. if (isCopy) {
  1795. frag.appendChild(node.cloneNode(true));
  1796. }
  1797. if (isDelete) {
  1798. nodeList.push(node);
  1799. }
  1800. } else {
  1801. var childFlag;
  1802. if (isCopy) {
  1803. childFlag = node.cloneNode(false);
  1804. frag.appendChild(childFlag);
  1805. }
  1806. if (extractNodes(node, childFlag) === false) {
  1807. return false;
  1808. }
  1809. }
  1810. } else if (node.nodeType == 3) {
  1811. var textNode;
  1812. if (node == copyRange.startContainer) {
  1813. textNode = splitTextNode(node, copyRange.startOffset, node.nodeValue.length);
  1814. } else if (node == copyRange.endContainer) {
  1815. textNode = splitTextNode(node, 0, copyRange.endOffset);
  1816. } else {
  1817. textNode = splitTextNode(node, 0, node.nodeValue.length);
  1818. }
  1819. if (isCopy) {
  1820. try {
  1821. frag.appendChild(textNode);
  1822. } catch(e) {}
  1823. }
  1824. }
  1825. }
  1826. node = nextNode;
  1827. }
  1828. }
  1829. extractNodes(ancestor, frag);
  1830. if (isDelete) {
  1831. range.up().collapse(true);
  1832. }
  1833. for (var i = 0, len = nodeList.length; i < len; i++) {
  1834. var node = nodeList[i];
  1835. if (node.parentNode) {
  1836. node.parentNode.removeChild(node);
  1837. }
  1838. }
  1839. return isCopy ? frag : range;
  1840. }
  1841. function _moveToElementText(range, el) {
  1842. var node = el;
  1843. while (node) {
  1844. var knode = K(node);
  1845. if (knode.name == 'marquee' || knode.name == 'select') {
  1846. return;
  1847. }
  1848. node = node.parentNode;
  1849. }
  1850. try {
  1851. range.moveToElementText(el);
  1852. } catch(e) {}
  1853. }
  1854. function _getStartEnd(rng, isStart) {
  1855. var doc = rng.parentElement().ownerDocument,
  1856. pointRange = rng.duplicate();
  1857. pointRange.collapse(isStart);
  1858. var parent = pointRange.parentElement(),
  1859. nodes = parent.childNodes;
  1860. if (nodes.length === 0) {
  1861. return {node: parent.parentNode, offset: K(parent).index()};
  1862. }
  1863. var startNode = doc, startPos = 0, cmp = -1;
  1864. var testRange = rng.duplicate();
  1865. _moveToElementText(testRange, parent);
  1866. for (var i = 0, len = nodes.length; i < len; i++) {
  1867. var node = nodes[i];
  1868. cmp = testRange.compareEndPoints('StartToStart', pointRange);
  1869. if (cmp === 0) {
  1870. return {node: node.parentNode, offset: i};
  1871. }
  1872. if (node.nodeType == 1) {
  1873. var nodeRange = rng.duplicate(), dummy, knode = K(node), newNode = node;
  1874. if (knode.isControl()) {
  1875. dummy = doc.createElement('span');
  1876. knode.after(dummy);
  1877. newNode = dummy;
  1878. startPos += knode.text().replace(/\r\n|\n|\r/g, '').length;
  1879. }
  1880. _moveToElementText(nodeRange, newNode);
  1881. testRange.setEndPoint('StartToEnd', nodeRange);
  1882. if (cmp > 0) {
  1883. startPos += nodeRange.text.replace(/\r\n|\n|\r/g, '').length;
  1884. } else {
  1885. startPos = 0;
  1886. }
  1887. if (dummy) {
  1888. K(dummy).remove();
  1889. }
  1890. } else if (node.nodeType == 3) {
  1891. testRange.moveStart('character', node.nodeValue.length);
  1892. startPos += node.nodeValue.length;
  1893. }
  1894. if (cmp < 0) {
  1895. startNode = node;
  1896. }
  1897. }
  1898. if (cmp < 0 && startNode.nodeType == 1) {
  1899. return {node: parent, offset: K(parent.lastChild).index() + 1};
  1900. }
  1901. if (cmp > 0) {
  1902. while (startNode.nextSibling && startNode.nodeType == 1) {
  1903. startNode = startNode.nextSibling;
  1904. }
  1905. }
  1906. testRange = rng.duplicate();
  1907. _moveToElementText(testRange, parent);
  1908. testRange.setEndPoint('StartToEnd', pointRange);
  1909. startPos -= testRange.text.replace(/\r\n|\n|\r/g, '').length;
  1910. if (cmp > 0 && startNode.nodeType == 3) {
  1911. var prevNode = startNode.previousSibling;
  1912. while (prevNode && prevNode.nodeType == 3) {
  1913. startPos -= prevNode.nodeValue.length;
  1914. prevNode = prevNode.previousSibling;
  1915. }
  1916. }
  1917. return {node: startNode, offset: startPos};
  1918. }
  1919. function _getEndRange(node, offset) {
  1920. var doc = node.ownerDocument || node,
  1921. range = doc.body.createTextRange();
  1922. if (doc == node) {
  1923. range.collapse(true);
  1924. return range;
  1925. }
  1926. if (node.nodeType == 1 && node.childNodes.length > 0) {
  1927. var children = node.childNodes, isStart, child;
  1928. if (offset === 0) {
  1929. child = children[0];
  1930. isStart = true;
  1931. } else {
  1932. child = children[offset - 1];
  1933. isStart = false;
  1934. }
  1935. if (!child) {
  1936. return range;
  1937. }
  1938. if (K(child).name === 'head') {
  1939. if (offset === 1) {
  1940. isStart = true;
  1941. }
  1942. if (offset === 2) {
  1943. isStart = false;
  1944. }
  1945. range.collapse(isStart);
  1946. return range;
  1947. }
  1948. if (child.nodeType == 1) {
  1949. var kchild = K(child), span;
  1950. if (kchild.isControl()) {
  1951. span = doc.createElement('span');
  1952. if (isStart) {
  1953. kchild.before(span);
  1954. } else {
  1955. kchild.after(span);
  1956. }
  1957. child = span;
  1958. }
  1959. _moveToElementText(range, child);
  1960. range.collapse(isStart);
  1961. if (span) {
  1962. K(span).remove();
  1963. }
  1964. return range;
  1965. }
  1966. node = child;
  1967. offset = isStart ? 0 : child.nodeValue.length;
  1968. }
  1969. var dummy = doc.createElement('span');
  1970. K(node).before(dummy);
  1971. _moveToElementText(range, dummy);
  1972. range.moveStart('character', offset);
  1973. K(dummy).remove();
  1974. return range;
  1975. }
  1976. function _toRange(rng) {
  1977. var doc, range;
  1978. function tr2td(start) {
  1979. if (K(start.node).name == 'tr') {
  1980. start.node = start.node.cells[start.offset];
  1981. start.offset = 0;
  1982. }
  1983. }
  1984. if (_IE) {
  1985. if (rng.item) {
  1986. doc = _getDoc(rng.item(0));
  1987. range = new KRange(doc);
  1988. range.selectNode(rng.item(0));
  1989. return range;
  1990. }
  1991. doc = rng.parentElement().ownerDocument;
  1992. var start = _getStartEnd(rng, true),
  1993. end = _getStartEnd(rng, false);
  1994. tr2td(start);
  1995. tr2td(end);
  1996. range = new KRange(doc);
  1997. range.setStart(start.node, start.offset);
  1998. range.setEnd(end.node, end.offset);
  1999. return range;
  2000. }
  2001. var startContainer = rng.startContainer;
  2002. doc = startContainer.ownerDocument || startContainer;
  2003. range = new KRange(doc);
  2004. range.setStart(startContainer, rng.startOffset);
  2005. range.setEnd(rng.endContainer, rng.endOffset);
  2006. return range;
  2007. }
  2008. function KRange(doc) {
  2009. this.init(doc);
  2010. }
  2011. _extend(KRange, {
  2012. init : function(doc) {
  2013. var self = this;
  2014. self.startContainer = doc;
  2015. self.startOffset = 0;
  2016. self.endContainer = doc;
  2017. self.endOffset = 0;
  2018. self.collapsed = true;
  2019. self.doc = doc;
  2020. },
  2021. commonAncestor : function() {
  2022. function getParents(node) {
  2023. var parents = [];
  2024. while (node) {
  2025. parents.push(node);
  2026. node = node.parentNode;
  2027. }
  2028. return parents;
  2029. }
  2030. var parentsA = getParents(this.startContainer),
  2031. parentsB = getParents(this.endContainer),
  2032. i = 0, lenA = parentsA.length, lenB = parentsB.length, parentA, parentB;
  2033. while (++i) {
  2034. parentA = parentsA[lenA - i];
  2035. parentB = parentsB[lenB - i];
  2036. if (!parentA || !parentB || parentA !== parentB) {
  2037. break;
  2038. }
  2039. }
  2040. return parentsA[lenA - i + 1];
  2041. },
  2042. setStart : function(node, offset) {
  2043. var self = this, doc = self.doc;
  2044. self.startContainer = node;
  2045. self.startOffset = offset;
  2046. if (self.endContainer === doc) {
  2047. self.endContainer = node;
  2048. self.endOffset = offset;
  2049. }
  2050. return _updateCollapsed(this);
  2051. },
  2052. setEnd : function(node, offset) {
  2053. var self = this, doc = self.doc;
  2054. self.endContainer = node;
  2055. self.endOffset = offset;
  2056. if (self.startContainer === doc) {
  2057. self.startContainer = node;
  2058. self.startOffset = offset;
  2059. }
  2060. return _updateCollapsed(this);
  2061. },
  2062. setStartBefore : function(node) {
  2063. return this.setStart(node.parentNode || this.doc, K(node).index());
  2064. },
  2065. setStartAfter : function(node) {
  2066. return this.setStart(node.parentNode || this.doc, K(node).index() + 1);
  2067. },
  2068. setEndBefore : function(node) {
  2069. return this.setEnd(node.parentNode || this.doc, K(node).index());
  2070. },
  2071. setEndAfter : function(node) {
  2072. return this.setEnd(node.parentNode || this.doc, K(node).index() + 1);
  2073. },
  2074. selectNode : function(node) {
  2075. return this.setStartBefore(node).setEndAfter(node);
  2076. },
  2077. selectNodeContents : function(node) {
  2078. var knode = K(node);
  2079. if (knode.type == 3 || knode.isSingle()) {
  2080. return this.selectNode(node);
  2081. }
  2082. var children = knode.children();
  2083. if (children.length > 0) {
  2084. return this.setStartBefore(children[0][0]).setEndAfter(children[children.length - 1][0]);
  2085. }
  2086. return this.setStart(node, 0).setEnd(node, 0);
  2087. },
  2088. collapse : function(toStart) {
  2089. if (toStart) {
  2090. return this.setEnd(this.startContainer, this.startOffset);
  2091. }
  2092. return this.setStart(this.endContainer, this.endOffset);
  2093. },
  2094. compareBoundaryPoints : function(how, range) {
  2095. var rangeA = this.get(), rangeB = range.get();
  2096. if (_IE) {
  2097. var arr = {};
  2098. arr[_START_TO_START] = 'StartToStart';
  2099. arr[_START_TO_END] = 'EndToStart';
  2100. arr[_END_TO_END] = 'EndToEnd';
  2101. arr[_END_TO_START] = 'StartToEnd';
  2102. var cmp = rangeA.compareEndPoints(arr[how], rangeB);
  2103. if (cmp !== 0) {
  2104. return cmp;
  2105. }
  2106. var nodeA, nodeB, nodeC, posA, posB;
  2107. if (how === _START_TO_START || how === _END_TO_START) {
  2108. nodeA = this.startContainer;
  2109. posA = this.startOffset;
  2110. }
  2111. if (how === _START_TO_END || how === _END_TO_END) {
  2112. nodeA = this.endContainer;
  2113. posA = this.endOffset;
  2114. }
  2115. if (how === _START_TO_START || how === _START_TO_END) {
  2116. nodeB = range.startContainer;
  2117. posB = range.startOffset;
  2118. }
  2119. if (how === _END_TO_END || how === _END_TO_START) {
  2120. nodeB = range.endContainer;
  2121. posB = range.endOffset;
  2122. }
  2123. if (nodeA === nodeB) {
  2124. var diff = posA - posB;
  2125. return diff > 0 ? 1 : (diff < 0 ? -1 : 0);
  2126. }
  2127. nodeC = nodeB;
  2128. while (nodeC && nodeC.parentNode !== nodeA) {
  2129. nodeC = nodeC.parentNode;
  2130. }
  2131. if (nodeC) {
  2132. return K(nodeC).index() >= posA ? -1 : 1;
  2133. }
  2134. nodeC = nodeA;
  2135. while (nodeC && nodeC.parentNode !== nodeB) {
  2136. nodeC = nodeC.parentNode;
  2137. }
  2138. if (nodeC) {
  2139. return K(nodeC).index() >= posB ? 1 : -1;
  2140. }
  2141. nodeC = K(nodeB).next();
  2142. if (nodeC && nodeC.contains(nodeA)) {
  2143. return 1;
  2144. }
  2145. nodeC = K(nodeA).next();
  2146. if (nodeC && nodeC.contains(nodeB)) {
  2147. return -1;
  2148. }
  2149. } else {
  2150. return rangeA.compareBoundaryPoints(how, rangeB);
  2151. }
  2152. },
  2153. cloneRange : function() {
  2154. return new KRange(this.doc).setStart(this.startContainer, this.startOffset).setEnd(this.endContainer, this.endOffset);
  2155. },
  2156. toString : function() {
  2157. var rng = this.get(), str = _IE ? rng.text : rng.toString();
  2158. return str.replace(/\r\n|\n|\r/g, '');
  2159. },
  2160. cloneContents : function() {
  2161. return _copyAndDelete(this, true, false);
  2162. },
  2163. deleteContents : function() {
  2164. return _copyAndDelete(this, false, true);
  2165. },
  2166. extractContents : function() {
  2167. return _copyAndDelete(this, true, true);
  2168. },
  2169. insertNode : function(node) {
  2170. var self = this,
  2171. sc = self.startContainer, so = self.startOffset,
  2172. ec = self.endContainer, eo = self.endOffset,
  2173. firstChild, lastChild, c, nodeCount = 1;
  2174. if (node.nodeName.toLowerCase() === '#document-fragment') {
  2175. firstChild = node.firstChild;
  2176. lastChild = node.lastChild;
  2177. nodeCount = node.childNodes.length;
  2178. }
  2179. if (sc.nodeType == 1) {
  2180. c = sc.childNodes[so];
  2181. if (c) {
  2182. sc.insertBefore(node, c);
  2183. if (sc === ec) {
  2184. eo += nodeCount;
  2185. }
  2186. } else {
  2187. sc.appendChild(node);
  2188. }
  2189. } else if (sc.nodeType == 3) {
  2190. if (so === 0) {
  2191. sc.parentNode.insertBefore(node, sc);
  2192. if (sc.parentNode === ec) {
  2193. eo += nodeCount;
  2194. }
  2195. } else if (so >= sc.nodeValue.length) {
  2196. if (sc.nextSibling) {
  2197. sc.parentNode.insertBefore(node, sc.nextSibling);
  2198. } else {
  2199. sc.parentNode.appendChild(node);
  2200. }
  2201. } else {
  2202. if (so > 0) {
  2203. c = sc.splitText(so);
  2204. } else {
  2205. c = sc;
  2206. }
  2207. sc.parentNode.insertBefore(node, c);
  2208. if (sc === ec) {
  2209. ec = c;
  2210. eo -= so;
  2211. }
  2212. }
  2213. }
  2214. if (firstChild) {
  2215. self.setStartBefore(firstChild).setEndAfter(lastChild);
  2216. } else {
  2217. self.selectNode(node);
  2218. }
  2219. if (self.compareBoundaryPoints(_END_TO_END, self.cloneRange().setEnd(ec, eo)) >= 1) {
  2220. return self;
  2221. }
  2222. return self.setEnd(ec, eo);
  2223. },
  2224. surroundContents : function(node) {
  2225. node.appendChild(this.extractContents());
  2226. return this.insertNode(node).selectNode(node);
  2227. },
  2228. isControl : function() {
  2229. var self = this,
  2230. sc = self.startContainer, so = self.startOffset,
  2231. ec = self.endContainer, eo = self.endOffset, rng;
  2232. return sc.nodeType == 1 && sc === ec && so + 1 === eo && K(sc.childNodes[so]).isControl();
  2233. },
  2234. get : function(hasControlRange) {
  2235. var self = this, doc = self.doc, node, rng;
  2236. if (!_IE) {
  2237. rng = doc.createRange();
  2238. try {
  2239. rng.setStart(self.startContainer, self.startOffset);
  2240. rng.setEnd(self.endContainer, self.endOffset);
  2241. } catch (e) {}
  2242. return rng;
  2243. }
  2244. if (hasControlRange && self.isControl()) {
  2245. rng = doc.body.createControlRange();
  2246. rng.addElement(self.startContainer.childNodes[self.startOffset]);
  2247. return rng;
  2248. }
  2249. var range = self.cloneRange().down();
  2250. rng = doc.body.createTextRange();
  2251. rng.setEndPoint('StartToStart', _getEndRange(range.startContainer, range.startOffset));
  2252. rng.setEndPoint('EndToStart', _getEndRange(range.endContainer, range.endOffset));
  2253. return rng;
  2254. },
  2255. html : function() {
  2256. return K(this.cloneContents()).outer();
  2257. },
  2258. down : function() {
  2259. var self = this;
  2260. function downPos(node, pos, isStart) {
  2261. if (node.nodeType != 1) {
  2262. return;
  2263. }
  2264. var children = K(node).children();
  2265. if (children.length === 0) {
  2266. return;
  2267. }
  2268. var left, right, child, offset;
  2269. if (pos > 0) {
  2270. left = children[pos - 1];
  2271. }
  2272. if (pos < children.length) {
  2273. right = children[pos];
  2274. }
  2275. if (left && left.type == 3) {
  2276. child = left[0];
  2277. offset = child.nodeValue.length;
  2278. }
  2279. if (right && right.type == 3) {
  2280. child = right[0];
  2281. offset = 0;
  2282. }
  2283. if (!child) {
  2284. return;
  2285. }
  2286. if (isStart) {
  2287. self.setStart(child, offset);
  2288. } else {
  2289. self.setEnd(child, offset);
  2290. }
  2291. }
  2292. downPos(self.startContainer, self.startOffset, true);
  2293. downPos(self.endContainer, self.endOffset, false);
  2294. return self;
  2295. },
  2296. up : function() {
  2297. var self = this;
  2298. function upPos(node, pos, isStart) {
  2299. if (node.nodeType != 3) {
  2300. return;
  2301. }
  2302. if (pos === 0) {
  2303. if (isStart) {
  2304. self.setStartBefore(node);
  2305. } else {
  2306. self.setEndBefore(node);
  2307. }
  2308. } else if (pos == node.nodeValue.length) {
  2309. if (isStart) {
  2310. self.setStartAfter(node);
  2311. } else {
  2312. self.setEndAfter(node);
  2313. }
  2314. }
  2315. }
  2316. upPos(self.startContainer, self.startOffset, true);
  2317. upPos(self.endContainer, self.endOffset, false);
  2318. return self;
  2319. },
  2320. enlarge : function(toBlock) {
  2321. var self = this;
  2322. self.up();
  2323. function enlargePos(node, pos, isStart) {
  2324. var knode = K(node), parent;
  2325. if (knode.type == 3 || _NOSPLIT_TAG_MAP[knode.name] || !toBlock && knode.isBlock()) {
  2326. return;
  2327. }
  2328. if (pos === 0) {
  2329. while (!knode.prev()) {
  2330. parent = knode.parent();
  2331. if (!parent || _NOSPLIT_TAG_MAP[parent.name] || !toBlock && parent.isBlock()) {
  2332. break;
  2333. }
  2334. knode = parent;
  2335. }
  2336. if (isStart) {
  2337. self.setStartBefore(knode[0]);
  2338. } else {
  2339. self.setEndBefore(knode[0]);
  2340. }
  2341. } else if (pos == knode.children().length) {
  2342. while (!knode.next()) {
  2343. parent = knode.parent();
  2344. if (!parent || _NOSPLIT_TAG_MAP[parent.name] || !toBlock && parent.isBlock()) {
  2345. break;
  2346. }
  2347. knode = parent;
  2348. }
  2349. if (isStart) {
  2350. self.setStartAfter(knode[0]);
  2351. } else {
  2352. self.setEndAfter(knode[0]);
  2353. }
  2354. }
  2355. }
  2356. enlargePos(self.startContainer, self.startOffset, true);
  2357. enlargePos(self.endContainer, self.endOffset, false);
  2358. return self;
  2359. },
  2360. shrink : function() {
  2361. var self = this, child, collapsed = self.collapsed;
  2362. while (self.startContainer.nodeType == 1 && (child = self.startContainer.childNodes[self.startOffset]) && child.nodeType == 1 && !K(child).isSingle()) {
  2363. self.setStart(child, 0);
  2364. }
  2365. if (collapsed) {
  2366. return self.collapse(collapsed);
  2367. }
  2368. while (self.endContainer.nodeType == 1 && self.endOffset > 0 && (child = self.endContainer.childNodes[self.endOffset - 1]) && child.nodeType == 1 && !K(child).isSingle()) {
  2369. self.setEnd(child, child.childNodes.length);
  2370. }
  2371. return self;
  2372. },
  2373. createBookmark : function(serialize) {
  2374. var self = this, doc = self.doc, endNode,
  2375. startNode = K('<span style="display:none;"></span>', doc)[0];
  2376. startNode.id = '__kindeditor_bookmark_start_' + (_BOOKMARK_ID++) + '__';
  2377. if (!self.collapsed) {
  2378. endNode = startNode.cloneNode(true);
  2379. endNo