fcktools.js
上传用户:ah_jiwei
上传日期:2022-07-24
资源大小:54044k
文件大小:14k
源码类别:

数据库编程

开发平台:

Visual C++

  1. /*
  2.  * FCKeditor - The text editor for Internet - http://www.fckeditor.net
  3.  * Copyright (C) 2003-2007 Frederico Caldeira Knabben
  4.  *
  5.  * == BEGIN LICENSE ==
  6.  *
  7.  * Licensed under the terms of any of the following licenses at your
  8.  * choice:
  9.  *
  10.  *  - GNU General Public License Version 2 or later (the "GPL")
  11.  *    http://www.gnu.org/licenses/gpl.html
  12.  *
  13.  *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
  14.  *    http://www.gnu.org/licenses/lgpl.html
  15.  *
  16.  *  - Mozilla Public License Version 1.1 or later (the "MPL")
  17.  *    http://www.mozilla.org/MPL/MPL-1.1.html
  18.  *
  19.  * == END LICENSE ==
  20.  *
  21.  * Utility functions.
  22.  */
  23. var FCKTools = new Object() ;
  24. FCKTools.CreateBogusBR = function( targetDocument )
  25. {
  26. var eBR = targetDocument.createElement( 'br' ) ;
  27. // eBR.setAttribute( '_moz_editor_bogus_node', 'TRUE' ) ;
  28. eBR.setAttribute( 'type', '_moz' ) ;
  29. return eBR ;
  30. }
  31. // Returns a reference to the appended style sheet or an array with all the appended references
  32. FCKTools.AppendStyleSheet = function( documentElement, cssFileUrlOrArray )
  33. {
  34. if ( typeof( cssFileUrlOrArray ) == 'string' )
  35. return this._AppendStyleSheet( documentElement, cssFileUrlOrArray ) ;
  36. else
  37. {
  38. var aStyleSheeArray = new Array() ;
  39. for ( var i = 0 ; i < cssFileUrlOrArray.length ; i++ )
  40. aStyleSheeArray.push(this._AppendStyleSheet( documentElement, cssFileUrlOrArray[i] ) ) ;
  41. return aStyleSheeArray ;
  42. }
  43. }
  44. FCKTools.AppendStyleString = function ( documentElement, cssStyles )
  45. {
  46. this._AppendStyleString( documentElement, cssStyles ) ;
  47. }
  48. FCKTools.GetElementDocument = function ( element )
  49. {
  50. return element.ownerDocument || element.document ;
  51. }
  52. // Get the window object where the element is placed in.
  53. FCKTools.GetElementWindow = function( element )
  54. {
  55. return this.GetDocumentWindow( this.GetElementDocument( element ) ) ;
  56. }
  57. FCKTools.GetDocumentWindow = function( document )
  58. {
  59. // With Safari, there is not way to retrieve the window from the document, so we must fix it.
  60. if ( FCKBrowserInfo.IsSafari && !document.parentWindow )
  61. this.FixDocumentParentWindow( window.top ) ;
  62. return document.parentWindow || document.defaultView ;
  63. }
  64. /*
  65. This is a Safari specific function that fix the reference to the parent
  66. window from the document object.
  67. */
  68. FCKTools.FixDocumentParentWindow = function( targetWindow )
  69. {
  70. if ( targetWindow.document )
  71. targetWindow.document.parentWindow = targetWindow ;
  72. for ( var i = 0 ; i < targetWindow.frames.length ; i++ )
  73. FCKTools.FixDocumentParentWindow( targetWindow.frames[i] ) ;
  74. }
  75. FCKTools.HTMLEncode = function( text )
  76. {
  77. if ( !text )
  78. return '' ;
  79. text = text.replace( /&/g, '&amp;' ) ;
  80. text = text.replace( /</g, '&lt;' ) ;
  81. text = text.replace( />/g, '&gt;' ) ;
  82. return text ;
  83. }
  84. FCKTools.HTMLDecode = function( text )
  85. {
  86. if ( !text )
  87. return '' ;
  88. text = text.replace( /&gt;/g, '>' ) ;
  89. text = text.replace( /&lt;/g, '<' ) ;
  90. text = text.replace( /&amp;/g, '&' ) ;
  91. return text ;
  92. }
  93. FCKTools._ProcessLineBreaksForPMode = function( oEditor, text, liState, node, strArray )
  94. {
  95. var closeState = 0 ;
  96. var blockStartTag = "<p>" ;
  97. var blockEndTag = "</p>" ;
  98. var lineBreakTag = "<br />" ;
  99. if ( liState )
  100. {
  101. blockStartTag = "<li>" ;
  102. blockEndTag = "</li>" ;
  103. closeState = 1 ;
  104. }
  105. // Are we currently inside a <p> tag now?
  106. // If yes, close it at the next double line break.
  107. while ( node && node != oEditor.FCK.EditorDocument.body )
  108. {
  109. if ( node.tagName.toLowerCase() == 'p' )
  110. {
  111. closeState = 1 ;
  112. break;
  113. }
  114. node = node.parentNode ;
  115. }
  116. for ( var i = 0 ; i < text.length ; i++ )
  117. {
  118. var c = text.charAt( i ) ;
  119. if ( c == 'r' )
  120. continue ;
  121. if ( c != 'n' )
  122. {
  123. strArray.push( c ) ;
  124. continue ;
  125. }
  126. // Now we have encountered a line break.
  127. // Check if the next character is also a line break.
  128. var n = text.charAt( i + 1 ) ;
  129. if ( n == 'r' )
  130. {
  131. i++ ;
  132. n = text.charAt( i + 1 ) ;
  133. }
  134. if ( n == 'n' )
  135. {
  136. i++ ; // ignore next character - we have already processed it.
  137. if ( closeState )
  138. strArray.push( blockEndTag ) ;
  139. strArray.push( blockStartTag ) ;
  140. closeState = 1 ;
  141. }
  142. else
  143. strArray.push( lineBreakTag ) ;
  144. }
  145. }
  146. FCKTools._ProcessLineBreaksForDivMode = function( oEditor, text, liState, node, strArray )
  147. {
  148. var closeState = 0 ;
  149. var blockStartTag = "<div>" ;
  150. var blockEndTag = "</div>" ;
  151. if ( liState )
  152. {
  153. blockStartTag = "<li>" ;
  154. blockEndTag = "</li>" ;
  155. closeState = 1 ;
  156. }
  157. // Are we currently inside a <div> tag now?
  158. // If yes, close it at the next double line break.
  159. while ( node && node != oEditor.FCK.EditorDocument.body )
  160. {
  161. if ( node.tagName.toLowerCase() == 'div' )
  162. {
  163. closeState = 1 ;
  164. break ;
  165. }
  166. node = node.parentNode ;
  167. }
  168. for ( var i = 0 ; i < text.length ; i++ )
  169. {
  170. var c = text.charAt( i ) ;
  171. if ( c == 'r' )
  172. continue ;
  173. if ( c != 'n' )
  174. {
  175. strArray.push( c ) ;
  176. continue ;
  177. }
  178. if ( closeState )
  179. {
  180. if ( strArray[ strArray.length - 1 ] == blockStartTag )
  181. {
  182. // A div tag must have some contents inside for it to be visible.
  183. strArray.push( "&nbsp;" ) ;
  184. }
  185. strArray.push( blockEndTag ) ;
  186. }
  187. strArray.push( blockStartTag ) ;
  188. closeState = 1 ;
  189. }
  190. if ( closeState )
  191. strArray.push( blockEndTag ) ;
  192. }
  193. FCKTools._ProcessLineBreaksForBrMode = function( oEditor, text, liState, node, strArray )
  194. {
  195. var closeState = 0 ;
  196. var blockStartTag = "<br />" ;
  197. var blockEndTag = "" ;
  198. if ( liState )
  199. {
  200. blockStartTag = "<li>" ;
  201. blockEndTag = "</li>" ;
  202. closeState = 1 ;
  203. }
  204. for ( var i = 0 ; i < text.length ; i++ )
  205. {
  206. var c = text.charAt( i ) ;
  207. if ( c == 'r' )
  208. continue ;
  209. if ( c != 'n' )
  210. {
  211. strArray.push( c ) ;
  212. continue ;
  213. }
  214. if ( closeState && blockEndTag.length )
  215. strArray.push ( blockEndTag ) ;
  216. strArray.push( blockStartTag ) ;
  217. closeState = 1 ;
  218. }
  219. }
  220. FCKTools.ProcessLineBreaks = function( oEditor, oConfig, text )
  221. {
  222. var enterMode = oConfig.EnterMode.toLowerCase() ;
  223. var strArray = [] ;
  224. // Is the caret or selection inside an <li> tag now?
  225. var liState = 0 ;
  226. var range = new oEditor.FCKDomRange( oEditor.FCK.EditorWindow ) ;
  227. range.MoveToSelection() ;
  228. var node = range._Range.startContainer ;
  229. while ( node && node.nodeType != 1 )
  230. node = node.parentNode ;
  231. if ( node && node.tagName.toLowerCase() == 'li' )
  232. liState = 1 ;
  233. if ( enterMode == 'p' )
  234. this._ProcessLineBreaksForPMode( oEditor, text, liState, node, strArray ) ;
  235. else if ( enterMode == 'div' )
  236. this._ProcessLineBreaksForDivMode( oEditor, text, liState, node, strArray ) ;
  237. else if ( enterMode == 'br' )
  238. this._ProcessLineBreaksForBrMode( oEditor, text, liState, node, strArray ) ;
  239. return strArray.join( "" ) ;
  240. }
  241. /**
  242.  * Adds an option to a SELECT element.
  243.  */
  244. FCKTools.AddSelectOption = function( selectElement, optionText, optionValue )
  245. {
  246. var oOption = FCKTools.GetElementDocument( selectElement ).createElement( "OPTION" ) ;
  247. oOption.text = optionText ;
  248. oOption.value = optionValue ;
  249. selectElement.options.add(oOption) ;
  250. return oOption ;
  251. }
  252. FCKTools.RunFunction = function( func, thisObject, paramsArray, timerWindow )
  253. {
  254. if ( func )
  255. this.SetTimeout( func, 0, thisObject, paramsArray, timerWindow ) ;
  256. }
  257. FCKTools.SetTimeout = function( func, milliseconds, thisObject, paramsArray, timerWindow )
  258. {
  259. return ( timerWindow || window ).setTimeout(
  260. function()
  261. {
  262. if ( paramsArray )
  263. func.apply( thisObject, [].concat( paramsArray ) ) ;
  264. else
  265. func.apply( thisObject ) ;
  266. },
  267. milliseconds ) ;
  268. }
  269. FCKTools.SetInterval = function( func, milliseconds, thisObject, paramsArray, timerWindow )
  270. {
  271. return ( timerWindow || window ).setInterval(
  272. function()
  273. {
  274. func.apply( thisObject, paramsArray || [] ) ;
  275. },
  276. milliseconds ) ;
  277. }
  278. FCKTools.ConvertStyleSizeToHtml = function( size )
  279. {
  280. return size.EndsWith( '%' ) ? size : parseInt( size, 10 ) ;
  281. }
  282. FCKTools.ConvertHtmlSizeToStyle = function( size )
  283. {
  284. return size.EndsWith( '%' ) ? size : ( size + 'px' ) ;
  285. }
  286. // START iCM MODIFICATIONS
  287. // Amended to accept a list of one or more ascensor tag names
  288. // Amended to check the element itself before working back up through the parent hierarchy
  289. FCKTools.GetElementAscensor = function( element, ascensorTagNames )
  290. {
  291. // var e = element.parentNode ;
  292. var e = element ;
  293. var lstTags = "," + ascensorTagNames.toUpperCase() + "," ;
  294. while ( e )
  295. {
  296. if ( lstTags.indexOf( "," + e.nodeName.toUpperCase() + "," ) != -1 )
  297. return e ;
  298. e = e.parentNode ;
  299. }
  300. return null ;
  301. }
  302. // END iCM MODIFICATIONS
  303. FCKTools.CreateEventListener = function( func, params )
  304. {
  305. var f = function()
  306. {
  307. var aAllParams = [] ;
  308. for ( var i = 0 ; i < arguments.length ; i++ )
  309. aAllParams.push( arguments[i] ) ;
  310. func.apply( this, aAllParams.concat( params ) ) ;
  311. }
  312. return f ;
  313. }
  314. FCKTools.IsStrictMode = function( document )
  315. {
  316. // There is no compatMode in Safari, but it seams that it always behave as
  317. // CSS1Compat, so let's assume it as the default.
  318. return ( 'CSS1Compat' == ( document.compatMode || 'CSS1Compat' ) ) ;
  319. }
  320. // Transforms a "arguments" object to an array.
  321. FCKTools.ArgumentsToArray = function( args, startIndex, maxLength )
  322. {
  323. startIndex = startIndex || 0 ;
  324. maxLength = maxLength || args.length ;
  325. var argsArray = new Array() ;
  326. for ( var i = startIndex ; i < startIndex + maxLength && i < args.length ; i++ )
  327. argsArray.push( args[i] ) ;
  328. return argsArray ;
  329. }
  330. FCKTools.CloneObject = function( sourceObject )
  331. {
  332. var fCloneCreator = function() {} ;
  333. fCloneCreator.prototype = sourceObject ;
  334. return new fCloneCreator ;
  335. }
  336. // Appends a bogus <br> at the end of the element, if not yet available.
  337. FCKTools.AppendBogusBr = function( element )
  338. {
  339. if ( !element )
  340. return ;
  341. var eLastChild = this.GetLastItem( element.getElementsByTagName('br') ) ;
  342. if ( !eLastChild || ( eLastChild.getAttribute( 'type', 2 ) != '_moz' && eLastChild.getAttribute( '_moz_dirty' ) == null ) )
  343. {
  344. var doc = this.GetElementDocument( element ) ;
  345. if ( FCKBrowserInfo.IsOpera )
  346. element.appendChild( doc.createTextNode('') ) ;
  347. else
  348. element.appendChild( this.CreateBogusBR( doc ) ) ;
  349. }
  350. }
  351. FCKTools.GetLastItem = function( list )
  352. {
  353. if ( list.length > 0 )
  354. return list[ list.length - 1 ] ;
  355. return null ;
  356. }
  357. FCKTools.GetDocumentPosition = function( w, node )
  358. {
  359. var x = 0 ;
  360. var y = 0 ;
  361. var curNode = node ;
  362. while ( curNode && curNode != w.document.body )
  363. {
  364. x += curNode.offsetLeft - curNode.scrollLeft ;
  365. y += curNode.offsetTop - curNode.scrollTop ;
  366. curNode = curNode.offsetParent ;
  367. }
  368. return { "x" : x, "y" : y } ;
  369. }
  370. FCKTools.GetWindowPosition = function( w, node )
  371. {
  372. var pos = this.GetDocumentPosition( w, node ) ;
  373. var scroll = FCKTools.GetScrollPosition( w ) ;
  374. pos.x -= scroll.X ;
  375. pos.y -= scroll.Y ;
  376. return pos ;
  377. }
  378. FCKTools.ProtectFormStyles = function( formNode )
  379. {
  380. if ( !formNode || formNode.nodeType != 1 || formNode.tagName.toLowerCase() != 'form' )
  381. return [] ;
  382. var hijackRecord = [] ;
  383. var hijackNames = [ 'style', 'className' ] ;
  384. for ( var i = 0 ; i < hijackNames.length ; i++ )
  385. {
  386. var name = hijackNames[i] ;
  387. if ( formNode.elements.namedItem( name ) )
  388. {
  389. var hijackNode = formNode.elements.namedItem( name ) ;
  390. hijackRecord.push( [ hijackNode, hijackNode.nextSibling ] ) ;
  391. formNode.removeChild( hijackNode ) ;
  392. }
  393. }
  394. return hijackRecord ;
  395. }
  396. FCKTools.RestoreFormStyles = function( formNode, hijackRecord )
  397. {
  398. if ( !formNode || formNode.nodeType != 1 || formNode.tagName.toLowerCase() != 'form' )
  399. return ;
  400. if ( hijackRecord.length > 0 )
  401. {
  402. for ( var i = hijackRecord.length - 1 ; i >= 0 ; i-- )
  403. {
  404. var node = hijackRecord[i][0] ;
  405. var sibling = hijackRecord[i][1] ;
  406. if ( sibling )
  407. formNode.insertBefore( node, sibling ) ;
  408. else
  409. formNode.appendChild( node ) ;
  410. }
  411. }
  412. }
  413. // Perform a one-step DFS walk.
  414. FCKTools.GetNextNode = function( node, limitNode )
  415. {
  416. if ( node.firstChild )
  417. return node.firstChild ;
  418. else if ( node.nextSibling )
  419. return node.nextSibling ;
  420. else
  421. {
  422. var ancestor = node.parentNode ;
  423. while ( ancestor )
  424. {
  425. if ( ancestor == limitNode )
  426. return null ;
  427. if ( ancestor.nextSibling )
  428. return ancestor.nextSibling ;
  429. else
  430. ancestor = ancestor.parentNode ;
  431. }
  432. }
  433. return null ;
  434. }
  435. FCKTools.GetNextTextNode = function( textnode, limitNode, checkStop )
  436. {
  437. node = this.GetNextNode( textnode, limitNode ) ;
  438. if ( checkStop && node && checkStop( node ) )
  439. return null ;
  440. while ( node && node.nodeType != 3 )
  441. {
  442. node = this.GetNextNode( node, limitNode ) ;
  443. if ( checkStop && node && checkStop( node ) )
  444. return null ;
  445. }
  446. return node ;
  447. }
  448. /**
  449.  * Merge all objects passed by argument into a single object.
  450.  */
  451. FCKTools.Merge = function()
  452. {
  453. var args = arguments ;
  454. var o = args[0] ;
  455. for ( var i = 1 ; i < args.length ; i++ )
  456. {
  457. var arg = args[i] ;
  458. for ( var p in arg )
  459. o[p] = arg[p] ;
  460. }
  461. return o ;
  462. }
  463. /**
  464.  * Check if the passed argument is a real Array. It may not working when
  465.  * calling it cross windows.
  466.  */
  467. FCKTools.IsArray = function( it )
  468. {
  469. return ( it instanceof Array ) ;
  470. }
  471. /**
  472.  * Appends a "length" property to an object, containing the number of
  473.  * properties available on it, excluded the append property itself.
  474.  */
  475. FCKTools.AppendLengthProperty = function( targetObject, propertyName )
  476. {
  477. var counter = 0 ;
  478. for ( var n in targetObject )
  479. counter++ ;
  480. return targetObject[ propertyName || 'length' ] = counter ;
  481. }
  482. /**
  483.  * Gets the browser parsed version of a css text (style attribute value). On
  484.  * some cases, the browser makes changes to the css text, returning a different
  485.  * value. For example, hexadecimal colors get transformed to rgb().
  486.  */
  487. FCKTools.NormalizeCssText = function( unparsedCssText )
  488. {
  489. // Injects the style in a temporary span object, so the browser parses it,
  490. // retrieving its final format.
  491. var tempSpan = document.createElement( 'span' ) ;
  492. tempSpan.style.cssText = unparsedCssText ;
  493. return tempSpan.style.cssText ;
  494. }
  495. /**
  496.  * Utility function to wrap a call to an object's method,
  497.  * so it can be passed for example to an event handler,
  498.  * and then it will be executed with 'this' being the object.
  499.  */
  500. FCKTools.Hitch = function( obj, methodName )
  501. {
  502.   return function() { obj[methodName].apply(obj, arguments); } ;
  503. }