diff --git a/modules/editor/skins/xquared/doc/api/_01.html b/modules/editor/skins/xquared/doc/api/_01.html
deleted file mode 100644
index bd7000e14..000000000
--- a/modules/editor/skins/xquared/doc/api/_01.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
- JsDoc: Browser.js
-
-
-
-
-
-
-
-
Library: Browser.js
-
-
-
Constructors
-
-
-
Functions
-
-
-
Objects
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:20 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_02.html b/modules/editor/skins/xquared/doc/api/_02.html
deleted file mode 100644
index bc396fa0a..000000000
--- a/modules/editor/skins/xquared/doc/api/_02.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
- JsDoc:
-
-
-
-
-
-
-
-
Library: Controls.js
-
-
- Overview
-
-
-
xq.controls provides common UI elements such as dialog.
-
-
-
-
-
Constructors
-
-
-
-
-
-
-
-
-
Functions
-
-
-
-
-
-
-
- this.form.onsubmit(
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cancelButton.onclick(
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- this.param.renderItem(
item )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- item
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:20 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_03.html b/modules/editor/skins/xquared/doc/api/_03.html
deleted file mode 100644
index 527f10740..000000000
--- a/modules/editor/skins/xquared/doc/api/_03.html
+++ /dev/null
@@ -1,161 +0,0 @@
-
-
-
-
-
- JsDoc: DomTree.js
-
-
-
-
-
-
-
-
Library: DomTree.js
-
-
-
Constructors
-
-
-
-
-
-
-
-
-
Functions
-
-
-
-
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- el
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- findRight(
el )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- el
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Objects
-
-
-
-
-
-
-
Provide various tree operations.
-
-TODO: Add specs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:21 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_04.html b/modules/editor/skins/xquared/doc/api/_04.html
deleted file mode 100644
index 080339233..000000000
--- a/modules/editor/skins/xquared/doc/api/_04.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
- JsDoc:
-
-
-
-
-
-
-
-
Library: EditHistory.js
-
-
- Overview
-
-
-
xq.EditHistory manages editing history and performs UNDO/REDO.
-
-
-
-
-
Constructors
-
-
-
Functions
-
-
-
Objects
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:21 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_05.html b/modules/editor/skins/xquared/doc/api/_05.html
deleted file mode 100644
index 4b8bee6a9..000000000
--- a/modules/editor/skins/xquared/doc/api/_05.html
+++ /dev/null
@@ -1,796 +0,0 @@
-
-
-
-
-
- JsDoc:
-
-
-
-
-
-
-
-
Library: Editor.js
-
-
- Overview
-
-
-
xq.Editor manages configurations such as autocompletion and autocorrection, edit mode/normal mode switching, handles editing commands, keyboard shortcuts and other events.
-
-
-
-
-
Constructors
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Functions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- criteria(
text )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- text
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- criteria(
text )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- text
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- this.contentElement.form.onsubmit(
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cancelMousedown(
e )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- e
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- node
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- exitCondition(
node )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- node
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Objects
-
-
-
-
-
-
-
object
-
-
-
- this.config
-
-
-
-
-
Editor's configuration
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Element
-
-
-
- this.contentElement
-
-
-
-
-
Original content element
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Document
-
-
-
- this.doc
-
-
-
-
-
Owner document of content element
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Element
-
-
-
- this.body
-
-
-
-
-
Body of content element
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Object
-
-
-
- this.currentEditMode
-
-
-
-
-
False or 'readonly' means read-only mode, true or 'wysiwyg' means WYSIWYG editing mode, and 'source' means source editing mode.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
xq.RichDom
-
-
-
- this.rdom
-
-
-
-
-
RichDom instance
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
xq.Validator
-
-
-
- this.validator
-
-
-
-
-
Validator instance
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Element
-
-
-
- this.outmostWrapper
-
-
-
-
-
Outmost wrapper div
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Element
-
-
-
- this.sourceEditorDiv
-
-
-
-
-
Source editor container
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Element
-
-
-
- this.sourceEditorTextarea
-
-
-
-
-
Source editor textarea
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Element
-
-
-
- this.wysiwygEditorDiv
-
-
-
-
-
WYSIWYG editor container
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
IFrame
-
-
-
- this.editorFrame
-
-
-
-
-
Design mode iframe
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Window
-
-
-
- this.editorWin
-
-
-
-
-
Window that contains design mode iframe
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Document
-
-
-
- this.editorDoc
-
-
-
-
-
Document that contained by design mode iframe
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Element
-
-
-
- this.editorBody
-
-
-
-
-
Body that contained by design mode iframe
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Element
-
-
-
- this.toolbarContainer
-
-
-
-
-
Toolbar container
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Array
-
-
-
- this.toolbarButtons
-
-
-
-
-
Toolbar buttons
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
xq.EditHistory
-
-
-
- this.editHistory
-
-
-
-
-
Undo/redo manager
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:34 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_06.html b/modules/editor/skins/xquared/doc/api/_06.html
deleted file mode 100644
index 3aa42a640..000000000
--- a/modules/editor/skins/xquared/doc/api/_06.html
+++ /dev/null
@@ -1,216 +0,0 @@
-
-
-
-
-
- JsDoc: RichDom.js
-
-
-
-
-
-
-
-
Library: RichDom.js
-
-
-
Constructors
-
-
-
-
-
-
-
-
-
-
-
-
-
Functions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- node
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- exitCondition(
node )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- node
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xq.RichDom.createInstance(
)
-
-
-
-
-
Creates and returns instance of browser specific implementation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Objects
-
-
-
-
-
-
-
Encapsulates browser incompatibility problem and provides rich set of DOM manipulation API.
-
-RichDom provides basic CRUD + Advanced DOM manipulation API, various query methods and caret/selection management API
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
instance of DomTree
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:48 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_07.html b/modules/editor/skins/xquared/doc/api/_07.html
deleted file mode 100644
index 58e74f9aa..000000000
--- a/modules/editor/skins/xquared/doc/api/_07.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
- JsDoc: RichDomGecko.js
-
-
-
-
-
-
-
-
Library: RichDomGecko.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.RichDomGecko
-
-
-
-
-
RichDom for Gecko
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:48 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_08.html b/modules/editor/skins/xquared/doc/api/_08.html
deleted file mode 100644
index 56f0609f3..000000000
--- a/modules/editor/skins/xquared/doc/api/_08.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
- JsDoc: RichDomTrident.js
-
-
-
-
-
-
-
-
Library: RichDomTrident.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.RichDomTrident
-
-
-
-
-
RichDom for Internet Explorer 6 and 7
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:48 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_09.html b/modules/editor/skins/xquared/doc/api/_09.html
deleted file mode 100644
index 5a3a1fe0f..000000000
--- a/modules/editor/skins/xquared/doc/api/_09.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
- JsDoc: RichDomW3.js
-
-
-
-
-
-
-
-
Library: RichDomW3.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.RichDomW3
-
-
-
-
-
RichDom for W3C Standard Engine
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:49 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_10.html b/modules/editor/skins/xquared/doc/api/_10.html
deleted file mode 100644
index 9c4670246..000000000
--- a/modules/editor/skins/xquared/doc/api/_10.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
- JsDoc: RichDomWebkit.js
-
-
-
-
-
-
-
-
Library: RichDomWebkit.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.RichDomWebkit
-
-
-
-
-
RichDom for Webkit
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:49 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_11.html b/modules/editor/skins/xquared/doc/api/_11.html
deleted file mode 100644
index c5409a591..000000000
--- a/modules/editor/skins/xquared/doc/api/_11.html
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-
-
- JsDoc: RichTable.js
-
-
-
-
-
-
-
-
Library: RichTable.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
-
-
- xq.RichTable.create(
rdom, cols, rows, headerPositions )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- rdom
-
-
-
-
-
-
-
-
-
-
-
- cols
-
-
-
-
-
-
-
-
-
-
-
- rows
-
-
-
-
-
-
-
-
-
-
-
- headerPositions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Objects
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:49 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_12.html b/modules/editor/skins/xquared/doc/api/_12.html
deleted file mode 100644
index 2d0bff85a..000000000
--- a/modules/editor/skins/xquared/doc/api/_12.html
+++ /dev/null
@@ -1,189 +0,0 @@
-
-
-
-
-
- JsDoc: Shortcut.js
-
-
-
-
-
-
-
-
Library: Shortcut.js
-
-
-
Constructors
-
-
-
-
-
-
-
-
-
Functions
-
-
-
-
-
-
-
- xq.Shortcut.interprete(
expression )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- expression
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xq.Shortcut._interpreteModifier(
expression, modifierName )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- expression
-
-
-
-
-
-
-
-
-
-
-
- modifierName
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xq.Shortcut._interpreteWhich(
keyName )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- keyName
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:49 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_13.html b/modules/editor/skins/xquared/doc/api/_13.html
deleted file mode 100644
index 46fe53499..000000000
--- a/modules/editor/skins/xquared/doc/api/_13.html
+++ /dev/null
@@ -1,153 +0,0 @@
-
-
-
-
-
- JsDoc: Validator.js
-
-
-
-
-
-
-
-
Library: Validator.js
-
-
-
Constructors
-
-
-
-
-
-
-
Functions
-
-
-
-
-
-
-
-
-
- xq.Validator.createInstance(
curUrl, urlValidationMode, allowedTags, allowedAttrs )
-
-
-
-
-
Creates and returns instance of browser specific implementation.
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- curUrl
-
-
-
-
-
-
-
-
-
-
-
- urlValidationMode
-
-
-
-
-
-
-
-
-
-
-
- allowedTags
-
-
-
-
-
-
-
-
-
-
-
- allowedAttrs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.Validator
-
-
-
-
-
Validates and invalidates designmode contents
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:49 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_14.html b/modules/editor/skins/xquared/doc/api/_14.html
deleted file mode 100644
index 3a15872b4..000000000
--- a/modules/editor/skins/xquared/doc/api/_14.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
- JsDoc: ValidatorGecko.js
-
-
-
-
-
-
-
-
Library: ValidatorGecko.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.ValidatorGecko
-
-
-
-
-
Validator for Gecko Engine
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:49 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_15.html b/modules/editor/skins/xquared/doc/api/_15.html
deleted file mode 100644
index ee41915a5..000000000
--- a/modules/editor/skins/xquared/doc/api/_15.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
- JsDoc: ValidatorTrident.js
-
-
-
-
-
-
-
-
Library: ValidatorTrident.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.ValidatorTrident
-
-
-
-
-
Validator for Internet Explorer 6 and 7
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:50 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_16.html b/modules/editor/skins/xquared/doc/api/_16.html
deleted file mode 100644
index 5b7576800..000000000
--- a/modules/editor/skins/xquared/doc/api/_16.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
- JsDoc: ValidatorW3.js
-
-
-
-
-
-
-
-
Library: ValidatorW3.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.ValidatorW3
-
-
-
-
-
Validator for W3C Standard Engine
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:50 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_17.html b/modules/editor/skins/xquared/doc/api/_17.html
deleted file mode 100644
index b4e3818df..000000000
--- a/modules/editor/skins/xquared/doc/api/_17.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
- JsDoc: ValidatorWebkit.js
-
-
-
-
-
-
-
-
Library: ValidatorWebkit.js
-
-
-
Constructors
-
-
-
-
-
Functions
-
-
-
-
-
Objects
-
-
-
-
-
-
-
-
- xq.ValidatorWebkit
-
-
-
-
-
Validator for Webkit
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:50 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_18.html b/modules/editor/skins/xquared/doc/api/_18.html
deleted file mode 100644
index 88d060871..000000000
--- a/modules/editor/skins/xquared/doc/api/_18.html
+++ /dev/null
@@ -1,512 +0,0 @@
-
-
-
-
-
- JsDoc: XQuared.js
-
-
-
-
-
-
-
-
Library: XQuared.js
-
-
-
Constructors
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Functions
-
-
-
-
-
-
-
-
-
- xq.asEventSource(
object, prefix, events )
-
-
-
-
-
Make given object as event source
-
-
-
-
-
-
parameters
-
-
-
-
- Object
-
-
- object
-
-
- target object
-
-
-
-
-
- String
-
-
- prefix
-
-
- prefix for generated functions
-
-
-
-
-
- Array
-
-
- events
-
-
- array of string which contains name of events
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Returns the index of given element
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- n
-
-
-
-
-
-
-
-
-
-
-
returns
-
-
-
-
- Number
-
-
- index or -1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Date.pass(
msec )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- msec
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Date. elapsed(
msec )
-
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- msec
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- data
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xq.findXquaredScript(
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xq.shouldLoadOthers(
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xq.loadScript(
url )
-
-
-
-
-
-
-
-
-
parameters
-
-
-
-
-
-
-
- url
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xq.loadOthers(
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Objects
-
-
-
-
-
-
-
Namespace for entire Xquared classes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:50 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/_19.html b/modules/editor/skins/xquared/doc/api/_19.html
deleted file mode 100644
index 4616b926c..000000000
--- a/modules/editor/skins/xquared/doc/api/_19.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
- JsDoc: _ui_templates.js
-
-
-
-
-
-
-
-
Library: _ui_templates.js
-
-
-
Constructors
-
-
-
Functions
-
-
-
Objects
-
-
-
-
- Generated by
JsDoc Toolkit 1.3.1 on Wed, 21 Nov 2007 09:57:50 GMT.
-
-
-
diff --git a/modules/editor/skins/xquared/doc/api/constructor.gif b/modules/editor/skins/xquared/doc/api/constructor.gif
deleted file mode 100644
index ba779972c..000000000
Binary files a/modules/editor/skins/xquared/doc/api/constructor.gif and /dev/null differ
diff --git a/modules/editor/skins/xquared/doc/api/default.css b/modules/editor/skins/xquared/doc/api/default.css
deleted file mode 100644
index cfe837beb..000000000
--- a/modules/editor/skins/xquared/doc/api/default.css
+++ /dev/null
@@ -1,116 +0,0 @@
-body,a
-{
- color: #000;
- font: 12px verdana;
-}
-
-ul
-{
- list-style-type: none;
- margin-left: 10px;
- padding-left: 10px;
-}
-
-.content { }
-.docs { }
-.signature { font-weight: normal; }
-.code {
- font: 11px monaco,monospace;
- padding: 4px;
- margin-left: 18px;
- border: 1px dashed #ccc;
-}
-
-.itemTitle
-{
- font-size: 12px;
- font-weight: bold;
- height: 16px;
-}
-
-.item { }
-
-.sectionHead
-{
- font-size: 18px;
- font-weight: bold;
- background-color: #C0C1DE;
- color: #fff;
- margin-top: 18px;
- padding: 2px 4px 2px 4px;
-}
-
-.section
-{
- padding: 8px;
- border: 1px #8A92BC solid;
- margin: 4px;
-}
-
-.detailHead
-{
- border-bottom: 1px #8FB685 dotted;
- font-size: 12px;
- font-weight: bold;
- color: #798E73;
- margin-top: 18px;
-}
-
-.desc { padding: 8px; }
-
-.fileHead
-{
- background-image: url(file.gif);
- background-repeat: no-repeat;
- padding-left: 20px;
- font-weight: bold;
- font-size: 14px;
- line-height: 20px;
-}
-
-.overview .itemTitle
-{
- background-image: url(overview.gif);
- background-repeat: no-repeat;
- padding-left: 20px;
-}
-
-.constructor .itemTitle
-{
- background-image: url(constructor.gif);
- background-repeat: no-repeat;
- padding-left: 20px;
-}
-
-.function .itemTitle
-{
- background-image: url(function.gif);
- background-repeat: no-repeat;
- padding-left: 20px;
-}
-
-.object .itemTitle
-{
- background-image: url(object.gif);
- background-repeat: no-repeat;
- padding-left: 20px;
-}
-
-.type
-{
- font-style: italic;
- color: #999;
- font-weight: normal;
-}
-
-.itemTitle a.type { font-weight: bold; }
-
-.finePrint
-{
- color: #878787;
- font-family: verdana;
- font-size: 10px;
- text-align: right;
-}
-
-.params td { padding-right: 10px; }
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/file.gif b/modules/editor/skins/xquared/doc/api/file.gif
deleted file mode 100644
index 9c7446e41..000000000
Binary files a/modules/editor/skins/xquared/doc/api/file.gif and /dev/null differ
diff --git a/modules/editor/skins/xquared/doc/api/file_list.html b/modules/editor/skins/xquared/doc/api/file_list.html
deleted file mode 100644
index f6c3a20f5..000000000
--- a/modules/editor/skins/xquared/doc/api/file_list.html
+++ /dev/null
@@ -1,149 +0,0 @@
-
-
-
-
- JsDoc
-
-
-
-
-File Index
-
-
-
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/function.gif b/modules/editor/skins/xquared/doc/api/function.gif
deleted file mode 100644
index be00b964b..000000000
Binary files a/modules/editor/skins/xquared/doc/api/function.gif and /dev/null differ
diff --git a/modules/editor/skins/xquared/doc/api/index.html b/modules/editor/skins/xquared/doc/api/index.html
deleted file mode 100644
index 3df8e5bfc..000000000
--- a/modules/editor/skins/xquared/doc/api/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
- JsDoc
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/object.gif b/modules/editor/skins/xquared/doc/api/object.gif
deleted file mode 100644
index 409b58e33..000000000
Binary files a/modules/editor/skins/xquared/doc/api/object.gif and /dev/null differ
diff --git a/modules/editor/skins/xquared/doc/api/overview.gif b/modules/editor/skins/xquared/doc/api/overview.gif
deleted file mode 100644
index 241c2574e..000000000
Binary files a/modules/editor/skins/xquared/doc/api/overview.gif and /dev/null differ
diff --git a/modules/editor/skins/xquared/doc/api/splash.html b/modules/editor/skins/xquared/doc/api/splash.html
deleted file mode 100644
index 8c7495195..000000000
--- a/modules/editor/skins/xquared/doc/api/splash.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
- JsDoc
-
-
-
-
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_01.html b/modules/editor/skins/xquared/doc/api/src_01.html
deleted file mode 100644
index 4d8272800..000000000
--- a/modules/editor/skins/xquared/doc/api/src_01.html
+++ /dev/null
@@ -1,24 +0,0 @@
- 1 xq.Browser = {
- 2 // By Layout Engines
- 3 isTrident : navigator.appName == "Microsoft Internet Explorer" ,
- 4 isWebkit : navigator.userAgent.indexOf ( 'AppleWebKit/' ) > - 1 ,
- 5 isGecko : navigator.userAgent.indexOf ( 'Gecko' ) > - 1 && navigator.userAgent.indexOf ( 'KHTML' ) == - 1 ,
- 6 isKHTML : navigator.userAgent.indexOf ( 'KHTML' ) != - 1 ,
- 7 isPresto : navigator.appName == "Opera" ,
- 8
- 9 // By Platforms
- 10 isMac : navigator.userAgent.indexOf ( "Macintosh" ) != - 1 ,
- 11 isUbuntu : navigator.userAgent.indexOf ( 'Ubuntu' ) != - 1 ,
- 12
- 13 // By Browsers
- 14 isIE : navigator.appName == "Microsoft Internet Explorer" ,
- 15 isIE6 : navigator.userAgent.indexOf ( 'MSIE 6' ) != - 1 ,
- 16 isIE7 : navigator.userAgent.indexOf ( 'MSIE 7' ) != - 1
- 17 } ;
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_02.html b/modules/editor/skins/xquared/doc/api/src_02.html
deleted file mode 100644
index 7d1de91f7..000000000
--- a/modules/editor/skins/xquared/doc/api/src_02.html
+++ /dev/null
@@ -1,344 +0,0 @@
- 1 /**
- 2 * @fileOverview xq.controls provides common UI elements such as dialog.
- 3 */
- 4 xq.controls = { } ;
- 5
- 6
- 7
- 8 xq.controls.FormDialog = Class.create ( {
- 9 /**
- 10 * @constructor
- 11 *
- 12 * @param {String} html HTML string which contains FORM
- 13 * @param {Function} [onLoadHandler] callback function to be called when the form is loaded
- 14 */
- 15 initialize : function ( xed , html , onLoadHandler , onCloseHandler ) {
- 16 this.xed = xed ;
- 17 this.html = html ;
- 18 this.onLoadHandler = onLoadHandler || function ( ) { } ;
- 19 this.onCloseHandler = onCloseHandler || function ( ) { } ;
- 20 this.form = null ;
- 21 } ,
- 22 /**
- 23 * Show dialog
- 24 *
- 25 * @param {Object} [options] collection of options
- 26 */
- 27 show : function ( options ) {
- 28 options = options || { } ;
- 29 options.position = options.position || 'centerOfWindow' ;
- 30 options.mode = options.mode || 'modal' ;
- 31 options.cancelOnEsc = options.cancelOnEsc || true ;
- 32
- 33 var self = this ;
- 34
- 35 // create and append container
- 36 var container = $ ( document.createElement ( 'DIV' ) ) ;
- 37 container.style.display = 'none' ;
- 38 document.body.appendChild ( container ) ;
- 39
- 40 // initialize form
- 41 container.innerHTML = this.html ;
- 42 this.form = $ ( container.getElementsByTagName ( 'FORM' ) [ 0 ] ) ;
- 43
- 44 this.form.onsubmit = function ( ) {
- 45 self.onCloseHandler ( $ ( this ) . serialize ( true ) ) ;
- 46 self.close ( ) ;
- 47 return false ;
- 48 } ;
- 49
- 50 var cancelButton = this.form.getElementsByClassName ( 'cancel' ) [ 0 ] ;
- 51 cancelButton.onclick = function ( ) {
- 52 self.onCloseHandler ( ) ;
- 53 self.close ( ) ;
- 54 } ;
- 55
- 56 // append dialog
- 57 document.body.appendChild ( this.form ) ;
- 58 container.parentNode.removeChild ( container ) ;
- 59
- 60 // place dialog to center of window
- 61 this.setPosition ( options.position ) ;
- 62
- 63 // give focus
- 64 var elementToFocus = this.form.getElementsByClassName ( 'initialFocus' ) ;
- 65 if ( elementToFocus.length > 0 ) elementToFocus [ 0 ] . focus ( ) ;
- 66
- 67 // handle cancelOnEsc option
- 68 if ( options.cancelOnEsc ) {
- 69 Event.observe ( this.form , 'keydown' , function ( e ) {
- 70 if ( e.keyCode == 27 ) {
- 71 this.onCloseHandler ( ) ;
- 72 this.close ( ) ;
- 73 }
- 74 return false ;
- 75 } . bind ( this ) ) ;
- 76 }
- 77
- 78 this.onLoadHandler ( this ) ;
- 79 } ,
- 80 close : function ( ) {
- 81 this.form.parentNode.removeChild ( this.form ) ;
- 82 } ,
- 83 setPosition : function ( target ) {
- 84 var targetElement ;
- 85
- 86 if ( target == 'centerOfWindow' ) {
- 87 targetElement = document.documentElement ;
- 88 } else if ( target == 'centerOfEditor' ) {
- 89 targetElement = this.xed.getDoc ( ) [ xq.Browser.isTrident ? "body" : "documentElement" ] ;
- 90 } else if ( target == 'nearbyCaret' ) {
- 91 throw "Not implemented yet" ;
- 92 } else {
- 93 throw "Invalid argument: " + target ;
- 94 }
- 95
- 96 var targetWidth = targetElement.clientWidth ;
- 97 var targetHeight = targetElement.clientHeight ;
- 98 var dialogWidth = this.form.clientWidth ;
- 99 var dialogHeight = this.form.clientHeight ;
-100
-101 var x = parseInt ( ( targetWidth - dialogWidth ) / 2);
-102 var y = parseInt((targetHeight - dialogHeight) / 2 ) ;
-103
-104 this.form.style.left = x + "px" ;
-105 this.form.style.top = y + "px" ;
-106 }
-107 } )
-108
-109
-110
-111 xq.controls.QuickSearchDialog = Class.create ( {
-112 /**
-113 * @constructor
-114 */
-115 initialize : function ( xed , param ) {
-116 this.xed = xed ;
-117
-118 this.rdom = xq.RichDom.createInstance ( ) ;
-119 this.rdom.setRoot ( document.body ) ;
-120
-121 this.param = param ;
-122 if ( ! this.param.renderItem ) this.param.renderItem = function ( item ) {
-123 return this.rdom.getInnerText ( item ) ;
-124 } . bind ( this ) ;
-125
-126 this.container = null ;
-127 } ,
-128
-129 getQuery : function ( ) {
-130 if ( ! this.container ) return "" ;
-131 return this._getInputField ( ) . value ;
-132 } ,
-133
-134 onSubmit : function ( e ) {
-135 if ( this.matchCount ( ) > 0 ) {
-136 this.param.onSelect ( this.xed , this.list [ this._getSelectedIndex ( ) ] ) ;
-137 }
-138
-139 this.close ( ) ;
-140 Event.stop ( e ) ;
-141 return false ;
-142 } ,
-143
-144 onCancel : function ( e ) {
-145 if ( this.param.onCancel ) this.param.onCancel ( this.xed ) ;
-146 this.close ( ) ;
-147 } ,
-148
-149 onBlur : function ( e ) {
-150 // TODO: Ugly
-151 setTimeout ( function ( ) { this.onCancel ( e ) } . bind ( this ) , 400 ) ;
-152 } ,
-153
-154 onKey : function ( e ) {
-155 var esc = new xq.Shortcut ( "ESC" ) ;
-156 var enter = new xq.Shortcut ( "ENTER" ) ;
-157 var up = new xq.Shortcut ( "UP" ) ;
-158 var down = new xq.Shortcut ( "DOWN" ) ;
-159
-160 if ( esc.matches ( e ) ) {
-161 this.onCancel ( e ) ;
-162 } else if ( enter.matches ( e ) ) {
-163 this.onSubmit ( e ) ;
-164 } else if ( up.matches ( e ) ) {
-165 this._moveSelectionUp ( ) ;
-166 } else if ( down.matches ( e ) ) {
-167 this._moveSelectionDown ( ) ;
-168 } else {
-169 this.updateList ( ) ;
-170 }
-171 } ,
-172
-173 onClick : function ( e ) {
-174 var target = e.srcElement || e.target ;
-175 if ( target.nodeName == "LI" ) {
-176
-177 var index = this._getIndexOfLI ( target ) ;
-178 this.param.onSelect ( this.xed , this.list [ index ] ) ;
-179 }
-180 } ,
-181
-182 onList : function ( list ) {
-183 this.list = list ;
-184 this.renderList ( list ) ;
-185 } ,
-186
-187 updateList : function ( ) {
-188 window.setTimeout ( function ( ) {
-189 this.param.listProvider ( this.getQuery ( ) , this.xed , this.onList.bind ( this ) ) ;
-190 } . bind ( this ) , 0 ) ;
-191 } ,
-192
-193 renderList : function ( list )
-194 {
-195 var ol = this._getListContainer ( ) ;
-196 ol.innerHTML = "" ;
-197
-198 for ( var i = 0 ; i < list.length ; i ++ ) {
-199 var li = this.rdom.createElement ( 'LI' ) ;
-200 li.innerHTML = this.param.renderItem ( list [ i ] ) ;
-201 ol.appendChild ( li ) ;
-202 }
-203
-204 if ( ol.hasChildNodes ( ) ) {
-205 ol.firstChild.className = "selected" ;
-206 }
-207 } ,
-208
-209 show : function ( ) {
-210 if ( ! this.container ) this.container = this._create ( ) ;
-211
-212 var dialog = this.rdom.insertNodeAt ( this.container , this.rdom.getRoot ( ) , "end" ) ;
-213 this.setPosition ( 'centerOfEditor' ) ;
-214 this.updateList ( ) ;
-215 this.focus ( ) ;
-216 } ,
-217
-218 close : function ( ) {
-219 this.rdom.deleteNode ( this.container ) ;
-220 } ,
-221
-222 focus : function ( ) {
-223 this._getInputField ( ) . focus ( ) ;
-224 } ,
-225
-226 setPosition : function ( target ) {
-227 var targetElement ;
-228
-229 if ( target == 'centerOfWindow' ) {
-230 targetElement = document.documentElement ;
-231 } else if ( target == 'centerOfEditor' ) {
-232 targetElement = this.xed.getDoc ( ) . documentElement ;
-233 } else if ( target == 'nearbyCaret' ) {
-234 throw "Not implemented yet" ;
-235 } else {
-236 throw "Invalid argument: " + target ;
-237 }
-238
-239 var targetWidth = targetElement.clientWidth ;
-240 var targetHeight = targetElement.clientHeight ;
-241 var dialogWidth = this.container.clientWidth ;
-242 var dialogHeight = this.container.clientHeight ;
-243
-244 var x = parseInt ( ( targetWidth - dialogWidth ) / 2);
-245 var y = parseInt((targetHeight - dialogHeight) / 2 ) ;
-246 this.container.style.left = x + "px" ;
-247 this.container.style.top = y + "px" ;
-248 } ,
-249
-250 matchCount : function ( ) {
-251 return this.list ? this.list.length : 0 ;
-252 } ,
-253
-254 _create : function ( ) {
-255 // make container
-256 var container = this.rdom.createElement ( "DIV" ) ;
-257 container.className = "xqQuickSearch" ;
-258
-259 // make title
-260 if ( this.param.title ) {
-261 var title = this.rdom.createElement ( "H1" ) ;
-262 title.innerHTML = this.param.title ;
-263 container.appendChild ( title ) ;
-264 }
-265
-266 // make input field
-267 var inputWrapper = this.rdom.createElement ( "DIV" ) ;
-268 inputWrapper.className = "input" ;
-269 var form = this.rdom.createElement ( "FORM" ) ;
-270 var input = this.rdom.createElement ( "INPUT" ) ;
-271 input.type = "text" ;
-272 input.value = "" ;
-273 form.appendChild ( input ) ;
-274 inputWrapper.appendChild ( form ) ;
-275 container.appendChild ( inputWrapper ) ;
-276
-277 // make list
-278 var list = this.rdom.createElement ( "OL" ) ;
-279
-280 Event.observe ( input , 'blur' , this.onBlur.bindAsEventListener ( this ) ) ;
-281 Event.observe ( input , 'keypress' , this.onKey.bindAsEventListener ( this ) ) ;
-282 Event.observe ( list , 'click' , this.onClick.bindAsEventListener ( this ) , true ) ;
-283 Event.observe ( form , 'submit' , this.onSubmit.bindAsEventListener ( this ) ) ;
-284 Event.observe ( form , 'reset' , this.onCancel.bindAsEventListener ( this ) ) ;
-285
-286 container.appendChild ( list ) ;
-287 return container ;
-288 } ,
-289
-290 _getInputField : function ( ) {
-291 return this.container.getElementsByTagName ( 'INPUT' ) [ 0 ] ;
-292 } ,
-293
-294 _getListContainer : function ( ) {
-295 return this.container.getElementsByTagName ( 'OL' ) [ 0 ] ;
-296 } ,
-297
-298 _getSelectedIndex : function ( ) {
-299 var ol = this._getListContainer ( ) ;
-300 for ( var i = 0 ; i < ol.childNodes.length ; i ++ ) {
-301 if ( ol.childNodes [ i ] . className == 'selected' ) return i ;
-302 }
-303 } ,
-304
-305 _getIndexOfLI : function ( li ) {
-306 var ol = this._getListContainer ( ) ;
-307 for ( var i = 0 ; i < ol.childNodes.length ; i ++ ) {
-308 if ( ol.childNodes [ i ] == li ) return i ;
-309 }
-310 } ,
-311
-312 _moveSelectionUp : function ( ) {
-313 var count = this.matchCount ( ) ;
-314 if ( count == 0 ) return ;
-315 var index = this._getSelectedIndex ( ) ;
-316 var ol = this._getListContainer ( ) ;
-317 ol.childNodes [ index ] . className = "" ;
-318
-319 index -- ;
-320 if ( index < 0 ) index = count - 1 ;
-321
-322 ol.childNodes [ index ] . className = "selected" ;
-323 } ,
-324
-325 _moveSelectionDown : function ( ) {
-326 var count = this.matchCount ( ) ;
-327 if ( count == 0 ) return ;
-328 var index = this._getSelectedIndex ( ) ;
-329 var ol = this._getListContainer ( ) ;
-330 ol.childNodes [ index ] . className = "" ;
-331
-332 index ++ ;
-333 if ( index >= count ) index = 0 ;
-334
-335 ol.childNodes [ index ] . className = "selected" ;
-336 }
-337 } ) ;
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_03.html b/modules/editor/skins/xquared/doc/api/src_03.html
deleted file mode 100644
index 076de09f1..000000000
--- a/modules/editor/skins/xquared/doc/api/src_03.html
+++ /dev/null
@@ -1,325 +0,0 @@
- 1 /**
- 2 * Provide various tree operations.
- 3 *
- 4 * TODO: Add specs
- 5 */
- 6 xq.DomTree = Class.create ( {
- 7 initialize : function ( ) {
- 8 this._blockTags = [ "DIV" , "DD" , "LI" , "ADDRESS" , "CAPTION" , "DT" , "H1" , "H2" , "H3" , "H4" , "H5" , "H6" , "HR" , "P" , "BODY" , "BLOCKQUOTE" , "PRE" , "PARAM" , "DL" , "OL" , "UL" , "TABLE" , "THEAD" , "TBODY" , "TR" , "TH" , "TD" ] ;
- 9 this._blockContainerTags = [ "DIV" , "DD" , "LI" , "BODY" , "BLOCKQUOTE" , "UL" , "OL" , "DL" , "TABLE" , "THEAD" , "TBODY" , "TR" , "TH" , "TD" ] ;
- 10 this._listContainerTags = [ "OL" , "UL" , "DL" ] ;
- 11 this._tableCellTags = [ "TH" , "TD" ] ;
- 12 this._blockOnlyContainerTags = [ "BODY" , "BLOCKQUOTE" , "UL" , "OL" , "DL" , "TABLE" , "THEAD" , "TBODY" , "TR" ] ;
- 13 this._atomicTags = [ "IMG" , "OBJECT" , "BR" , "HR" ] ;
- 14 } ,
- 15
- 16 getBlockTags : function ( ) {
- 17 return this._blockTags ;
- 18 } ,
- 19
- 20 /**
- 21 * Find common ancestor(parent) and his immediate children(left and right).
- 22 *
- 23 * A --- B -+- C -+- D -+- E
- 24 * |
- 25 * +- F -+- G
- 26 *
- 27 * For example:
- 28 * > findCommonAncestorAndImmediateChildrenOf("E", "G")
- 29 *
- 30 * will return
- 31 *
- 32 * > {parent:"B", left:"C", right:"F"}
- 33 */
- 34 findCommonAncestorAndImmediateChildrenOf : function ( left , right ) {
- 35 if ( left.parentNode == right.parentNode ) {
- 36 return {
- 37 left : left ,
- 38 right : right ,
- 39 parent : left.parentNode
- 40 } ;
- 41 } else {
- 42 var parentsOfLeft = this.collectParentsOf ( left , true ) ;
- 43 var parentsOfRight = this.collectParentsOf ( right , true ) ;
- 44 var ca = this.getCommonAncestor ( parentsOfLeft , parentsOfRight ) ;
- 45
- 46 var leftAncestor = parentsOfLeft.find ( function ( node ) { return node.parentNode == ca } ) ;
- 47 var rightAncestor = parentsOfRight.find ( function ( node ) { return node.parentNode == ca } ) ;
- 48
- 49 return {
- 50 left : leftAncestor ,
- 51 right : rightAncestor ,
- 52 parent : ca
- 53 } ;
- 54 }
- 55 } ,
- 56
- 57 /**
- 58 * Find leaves at edge.
- 59 *
- 60 * A --- B -+- C -+- D -+- E
- 61 * |
- 62 * +- F -+- G
- 63 *
- 64 * For example:
- 65 * > getLeavesAtEdge("A")
- 66 *
- 67 * will return
- 68 *
- 69 * > ["E", "G"]
- 70 */
- 71 getLeavesAtEdge : function ( element ) {
- 72 if ( ! element.hasChildNodes ( ) ) return [ null , null ] ;
- 73
- 74 var findLeft = function ( el ) {
- 75 for ( var i = 0 ; i < el.childNodes.length ; i ++ ) {
- 76 if ( el.childNodes [ i ] . nodeType == 1 && this.isBlock ( el.childNodes [ i ] ) ) return findLeft ( el.childNodes [ i ] ) ;
- 77 }
- 78 return el ;
- 79 } . bind ( this ) ;
- 80
- 81 var findRight = function ( el ) {
- 82 for ( var i = el.childNodes.length ; i -- ; ) {
- 83 if ( el.childNodes [ i ] . nodeType == 1 && this.isBlock ( el.childNodes [ i ] ) ) return findRight ( el.childNodes [ i ] ) ;
- 84 }
- 85 return el ;
- 86 } . bind ( this ) ;
- 87
- 88 var left = findLeft ( element ) ;
- 89 var right = findRight ( element ) ;
- 90 return [ left == element ? null : left , right == element ? null : right ] ;
- 91 } ,
- 92
- 93 getCommonAncestor : function ( parents1 , parents2 ) {
- 94 for ( var i = 0 ; i < parents1.length ; i ++ ) {
- 95 for ( var j = 0 ; j < parents2.length ; j ++ ) {
- 96 if ( parents1 [ i ] == parents2 [ j ] ) return parents1 [ i ] ;
- 97 }
- 98 }
- 99 } ,
-100
-101 collectParentsOf : function ( node , includeSelf , exitCondition ) {
-102 var parents = [ ] ;
-103 if ( includeSelf ) parents.push ( node ) ;
-104
-105 while ( ( node = node.parentNode ) && ( node.nodeName != "HTML" ) && ! ( typeof exitCondition == "function" && exitCondition ( node ) ) ) parents.push ( node ) ;
-106 return parents ;
-107 } ,
-108
-109 isDescendantOf : function ( parent , child ) {
-110 if ( parent.length > 0 ) {
-111 for ( var i = 0 ; i < parent.length ; i ++ ) {
-112 if ( this.isDescendantOf ( parent [ i ] , child ) ) return true ;
-113 }
-114 return false ;
-115 }
-116
-117 if ( parent == child ) return false ;
-118
-119 while ( child = child.parentNode )
-120 if ( child == parent ) return true ;
-121 return false ;
-122 } ,
-123
-124 /**
-125 * Perform tree walking (foreward)
-126 */
-127 walkForward : function ( node ) {
-128 if ( node.hasChildNodes ( ) ) return node.firstChild ;
-129 if ( node.nextSibling ) return node.nextSibling ;
-130
-131 while ( node = node.parentNode ) {
-132 if ( node.nextSibling ) return node.nextSibling ;
-133 }
-134
-135 return null ;
-136 } ,
-137
-138 /**
-139 * Perform tree walking (backward)
-140 */
-141 walkBackward : function ( node ) {
-142 if ( node.previousSibling ) {
-143 node = node.previousSibling ;
-144 while ( node.hasChildNodes ( ) ) { node = node.lastChild ; }
-145 return node ;
-146 }
-147
-148 return node.parentNode ;
-149 } ,
-150
-151 /**
-152 * Perform tree walking (to next siblings)
-153 */
-154 walkNext : function ( node ) { return node.nextSibling } ,
-155
-156 /**
-157 * Perform tree walking (to next siblings)
-158 */
-159 walkPrev : function ( node ) { return node.previousSibling } ,
-160
-161 /**
-162 * Returns true if target is followed by start
-163 */
-164 checkTargetForward : function ( start , target ) {
-165 return this._check ( start , this.walkForward , target ) ;
-166 } ,
-167
-168 /**
-169 * Returns true if start is followed by target
-170 */
-171 checkTargetBackward : function ( start , target ) {
-172 return this._check ( start , this.walkBackward , target ) ;
-173 } ,
-174
-175 findForward : function ( start , condition , exitCondition ) {
-176 return this._find ( start , this.walkForward , condition , exitCondition ) ;
-177 } ,
-178
-179 findBackward : function ( start , condition , exitCondition ) {
-180 return this._find ( start , this.walkBackward , condition , exitCondition ) ;
-181 } ,
-182
-183 /** @private */
-184 _check : function ( start , direction , target ) {
-185 if ( start == target ) return false ;
-186
-187 while ( start = direction ( start ) ) {
-188 if ( start == target ) return true ;
-189 }
-190 return false ;
-191 } ,
-192
-193 /** @private */
-194 _find : function ( start , direction , condition , exitCondition ) {
-195 while ( start = direction ( start ) ) {
-196 if ( exitCondition && exitCondition ( start ) ) return null ;
-197 if ( condition ( start ) ) return start ;
-198 }
-199 return null ;
-200 } ,
-201
-202 /**
-203 * Walks Forward through DOM tree from start to end, and collects all nodes that matches with a filter.
-204 * If no filter provided, it just collects all nodes.
-205 *
-206 * @param function filter a filter function
-207 */
-208 collectNodesBetween : function ( start , end , filter ) {
-209 if ( start == end ) return [ start , end ] . findAll ( filter || function ( ) { return true } ) ;
-210
-211 var nodes = this.collectForward ( start , function ( node ) { return node == end } , filter ) ;
-212 if (
-213 start != end &&
-214 typeof filter == "function" &&
-215 filter ( end )
-216 ) nodes.push ( end ) ;
-217
-218 return nodes ;
-219 } ,
-220
-221 collectForward : function ( start , exitCondition , filter ) {
-222 return this.collect ( start , this.walkForward , exitCondition , filter ) ;
-223 } ,
-224
-225 collectBackward : function ( start , exitCondition , filter ) {
-226 return this.collect ( start , this.walkBackward , exitCondition , filter ) ;
-227 } ,
-228
-229 collectNext : function ( start , exitCondition , filter ) {
-230 return this.collect ( start , this.walkNext , exitCondition , filter ) ;
-231 } ,
-232
-233 collectPrev : function ( start , exitCondition , filter ) {
-234 return this.collect ( start , this.walkPrev , exitCondition , filter ) ;
-235 } ,
-236
-237 collect : function ( start , next , exitCondition , filter ) {
-238 var nodes = [ start ] ;
-239
-240 while ( true ) {
-241 start = next ( start ) ;
-242 if (
-243 ( start == null ) ||
-244 ( typeof exitCondition == "function" && exitCondition ( start ) )
-245 ) break ;
-246
-247 nodes.push ( start ) ;
-248 }
-249
-250 return ( typeof filter == "function" ) ? nodes.findAll ( filter ) : nodes ;
-251 } ,
-252
-253
-254 hasBlocks : function ( element ) {
-255 var nodes = element.childNodes ;
-256 for ( var i = 0 ; i < nodes.length ; i ++ ) {
-257 if ( this.isBlock ( nodes [ i ] ) ) return true ;
-258 }
-259 return false ;
-260 } ,
-261
-262 hasMixedContents : function ( element ) {
-263 if ( ! this.isBlock ( element ) ) return false ;
-264 if ( ! this.isBlockContainer ( element ) ) return false ;
-265
-266 var hasTextOrInline = false ;
-267 var hasBlock = false ;
-268 for ( var i = 0 ; i < element.childNodes.length ; i ++ ) {
-269 var node = element.childNodes [ i ] ;
-270 if ( ! hasTextOrInline && this.isTextOrInlineNode ( node ) ) hasTextOrInline = true ;
-271 if ( ! hasBlock && this.isBlock ( node ) ) hasBlock = true ;
-272
-273 if ( hasTextOrInline && hasBlock ) break ;
-274 }
-275 if ( ! hasTextOrInline || ! hasBlock ) return false ;
-276
-277 return true ;
-278 } ,
-279
-280 isBlockOnlyContainer : function ( element ) {
-281 if ( ! element ) return false ;
-282 return this._blockOnlyContainerTags.include ( typeof element == 'string' ? element : element.nodeName ) ;
-283 } ,
-284
-285 isTableCell : function ( element ) {
-286 if ( ! element ) return false ;
-287 return this._tableCellTags.include ( typeof element == 'string' ? element : element.nodeName ) ;
-288 } ,
-289
-290 isBlockContainer : function ( element ) {
-291 if ( ! element ) return false ;
-292 return this._blockContainerTags.include ( typeof element == 'string' ? element : element.nodeName ) ;
-293 } ,
-294
-295 isHeading : function ( element ) {
-296 if ( ! element ) return false ;
-297 return ( typeof element == 'string' ? element : element.nodeName ) . match ( /H\d/ ) ;
-298 } ,
-299
-300 isBlock : function ( element ) {
-301 if ( ! element ) return false ;
-302 return this._blockTags.include ( typeof element == 'string' ? element : element.nodeName ) ;
-303 } ,
-304
-305 isAtomic : function ( element ) {
-306 if ( ! element ) return false ;
-307 return this._atomicTags.include ( typeof element == 'string' ? element : element.nodeName ) ;
-308 } ,
-309
-310 isListContainer : function ( element ) {
-311 if ( ! element ) return false ;
-312 return this._listContainerTags.include ( typeof element == 'string' ? element : element.nodeName ) ;
-313 } ,
-314
-315 isTextOrInlineNode : function ( node ) {
-316 return node && ( node.nodeType == 3 || ! this.isBlock ( node ) ) ;
-317 }
-318 } ) ;
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_04.html b/modules/editor/skins/xquared/doc/api/src_04.html
deleted file mode 100644
index 50db4821a..000000000
--- a/modules/editor/skins/xquared/doc/api/src_04.html
+++ /dev/null
@@ -1,163 +0,0 @@
- 1 /**
- 2 * @fileOverview xq.EditHistory manages editing history and performs UNDO/REDO.
- 3 */
- 4 xq.EditHistory = Class.create ( {
- 5 /**
- 6 * Initializer
- 7 *
- 8 * @constructor
- 9 * @param {xq.RichDom} rdom RichDom instance
- 10 * @param {Number} [max] maximum UNDO buffer size(default value is 100).
- 11 */
- 12 initialize : function ( rdom , max ) {
- 13 if ( ! rdom ) throw "IllegalArgumentException" ;
- 14
- 15 this.disabled = false ;
- 16 this.max = max || 100 ;
- 17 this.rdom = rdom ;
- 18 this.root = rdom.getRoot ( ) ;
- 19 this.clear ( ) ;
- 20
- 21 this.lastModified = Date.get ( ) ;
- 22 } ,
- 23 getLastModifiedDate : function ( ) {
- 24 return this.lastModified ;
- 25 } ,
- 26 isUndoable : function ( ) {
- 27 return this.queue.length > 0 && this.index > 0 ;
- 28 } ,
- 29 isRedoable : function ( ) {
- 30 return this.queue.length > 0 && this.index < this.queue.length - 1 ;
- 31 } ,
- 32 disable : function ( ) {
- 33 this.disabled = true ;
- 34 } ,
- 35 enable : function ( ) {
- 36 this.disabled = false ;
- 37 } ,
- 38 undo : function ( ) {
- 39 this.pushContent ( ) ;
- 40
- 41 if ( this.isUndoable ( ) ) {
- 42 this.index -- ;
- 43 this.popContent ( ) ;
- 44 return true ;
- 45 } else {
- 46 return false ;
- 47 }
- 48 } ,
- 49 redo : function ( ) {
- 50 if ( this.isRedoable ( ) ) {
- 51 this.index ++ ;
- 52 this.popContent ( ) ;
- 53 return true ;
- 54 } else {
- 55 return false ;
- 56 }
- 57 } ,
- 58 onCommand : function ( ) {
- 59 this.lastModified = Date.get ( ) ;
- 60 if ( this.disabled ) return false ;
- 61
- 62 return this.pushContent ( ) ;
- 63 } ,
- 64 onEvent : function ( event ) {
- 65 this.lastModified = Date.get ( ) ;
- 66 if ( this.disabled ) return false ;
- 67
- 68 // ignore normal keys
- 69 if ( 'keydown' == event.type && ! ( event.ctrlKey || event.metaKey ) ) return false ;
- 70 if ( [ 'keydown' , 'keyup' , 'keypress' ] . include ( event.type ) && ! event.ctrlKey && ! event.altKey && ! event.metaKey && ! [ 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 ] . include ( event.keyCode ) ) return false ;
- 71 if ( [ 'keydown' , 'keyup' , 'keypress' ] . include ( event.type ) && ( event.ctrlKey || event.metaKey ) && [ 89 , 90 ] . include ( event.keyCode ) ) return false ;
- 72
- 73 // ignore ctrl/shift/alt/meta keys
- 74 if ( [ 16 , 17 , 18 , 224 ] . include ( event.keyCode ) ) return false ;
- 75
- 76 return this.pushContent ( ) ;
- 77 } ,
- 78 popContent : function ( ) {
- 79 this.lastModified = Date.get ( ) ;
- 80 var entry = this.queue [ this.index ] ;
- 81 if ( entry.caret > 0 ) {
- 82 var html = entry.html.substring ( 0 , entry.caret ) + '<span id="caret_marker_00700"></span>' + entry.html.substring ( entry.caret ) ;
- 83 this.root.innerHTML = html ;
- 84 } else {
- 85 this.root.innerHTML = entry.html ;
- 86 }
- 87 this.restoreCaret ( ) ;
- 88 } ,
- 89 pushContent : function ( ignoreCaret ) {
- 90 if ( xq.Browser.isTrident && ! ignoreCaret && ! this.rdom.hasFocus ( ) ) return false ;
- 91 if ( ! this.rdom.getCurrentElement ( ) ) return false ;
- 92
- 93 var html = this.root.innerHTML ;
- 94 if ( html == ( this.queue [ this.index ] ? this.queue [ this.index ] . html : null ) ) return false ;
- 95 var caret = ignoreCaret ? - 1 : this.saveCaret ( ) ;
- 96
- 97 if ( this.queue.length >= this.max ) {
- 98 this.queue.shift ( ) ;
- 99 } else {
-100 this.index ++ ;
-101 }
-102
-103 this.queue.splice ( this.index , this.queue.length - this.index , { html : html , caret : caret } ) ;
-104 return true ;
-105 } ,
-106 clear : function ( ) {
-107 this.index = - 1 ;
-108 this.queue = [ ] ;
-109 this.pushContent ( true ) ;
-110 } ,
-111 saveCaret : function ( ) {
-112 if ( this.rdom.hasSelection ( ) ) return null ;
-113
-114 // FF on Mac has a caret problem with these lines. --2007/11/19
-115 var marker = this.rdom.pushMarker ( ) ;
-116 var str = xq.Browser.isTrident ? '<SPAN class=' + marker.className : '<span class="' + marker.className + '"' ;
-117 var caret = this.rdom.getRoot ( ) . innerHTML.indexOf ( str ) ;
-118 this.rdom.popMarker ( true ) ;
-119
-120 return caret ;
-121
-122 /*
-123 // This is old code. It also has same problem.
-124
-125 if(this.rdom.hasSelection()) return null;
-126
-127 var bookmark = this.rdom.saveSelection();
-128 var marker = this.rdom.pushMarker();
-129
-130 var str = xq.Browser.isTrident ? '<SPAN class='+marker.className : '<span class="'+marker.className+'"';
-131 var caret = this.rdom.getRoot().innerHTML.indexOf(str);
-132
-133 this.rdom.popMarker();
-134 this.rdom.restoreSelection(bookmark);
-135
-136 return caret;
-137 */
-138 } ,
-139 restoreCaret : function ( ) {
-140 var marker = this.rdom.$ ( 'caret_marker_00700' ) ;
-141
-142 if ( marker ) {
-143 this.rdom.selectElement ( marker , true ) ;
-144 this.rdom.collapseSelection ( false ) ;
-145 this.rdom.deleteNode ( marker ) ;
-146 } else {
-147 var node = this.rdom.tree.findForward ( this.rdom.getRoot ( ) , function ( node ) {
-148 return this.isBlock ( node ) && ! this.hasBlocks ( node ) ;
-149 } . bind ( this.rdom.tree ) ) ;
-150 this.rdom.selectElement ( node , false ) ;
-151 this.rdom.collapseSelection ( false ) ;
-152
-153 }
-154 }
-155 } ) ;
-156
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_05.html b/modules/editor/skins/xquared/doc/api/src_05.html
deleted file mode 100644
index c8bbff96a..000000000
--- a/modules/editor/skins/xquared/doc/api/src_05.html
+++ /dev/null
@@ -1,2216 +0,0 @@
- 1 /**
- 2 * @fileOverview xq.Editor manages configurations such as autocompletion and autocorrection, edit mode/normal mode switching, handles editing commands, keyboard shortcuts and other events.
- 3 */
- 4 xq.Editor = Class.create ( {
- 5 /**
- 6 * Initialize editor but it doesn't automatically start designMode. setEditMode should be called after initialization.
- 7 *
- 8 * @constructor
- 9 * @param {Element} contentElement HTML element(TEXTAREA or normal block element such as DIV) to be replaced with editable area
- 10 * @param {Element} toolbarContainer HTML element which contains toolbar icons
- 11 */
- 12 initialize : function ( contentElement , toolbarContainer ) {
- 13 if ( ! contentElement ) throw "[contentElement] is null" ;
- 14 if ( contentElement.nodeType != 1 ) throw "[contentElement] is not an element" ;
- 15
- 16 xq.asEventSource ( this , "Editor" , [ "ElementChanged" , "BeforeEvent" , "AfterEvent" , "CurrentContentChanged" , "StaticContentChanged" , "CurrentEditModeChanged" ] ) ;
- 17
- 18 /**
- 19 * Editor's configuration
- 20 * @type object
- 21 */
- 22 this.config = { } ;
- 23 this.config.enableLinkClick = false ;
- 24 this.config.changeCursorOnLink = false ;
- 25 this.config.generateDefaultToolbar = true ;
- 26 this.config.defaultToolbarButtonMap = [
- 27 [
- 28 { className : "foregroundColor" , title : "Foreground color" , handler : "xed.handleForegroundColor()" } ,
- 29 { className : "backgroundColor" , title : "Background color" , handler : "xed.handleBackgroundColor()" }
- 30 ] ,
- 31 [
- 32 { className : "link" , title : "Link" , handler : "xed.handleLink()" } ,
- 33 { className : "strongEmphasis" , title : "Strong emphasis" , handler : "xed.handleStrongEmphasis()" } ,
- 34 { className : "emphasis" , title : "Emphasis" , handler : "xed.handleEmphasis()" } ,
- 35 { className : "underline" , title : "Underline" , handler : "xed.handleUnderline()" } ,
- 36 { className : "strike" , title : "Strike" , handler : "xed.handleStrike()" } ,
- 37 { className : "superscription" , title : "Superscription" , handler : "xed.handleSuperscription()" } ,
- 38 { className : "subscription" , title : "Subscription" , handler : "xed.handleSubscription()" }
- 39 ] ,
- 40 [
- 41 { className : "removeFormat" , title : "Remove format" , handler : "xed.handleRemoveFormat()" }
- 42 ] ,
- 43 [
- 44 { className : "justifyLeft" , title : "Justify left" , handler : "xed.handleJustify('left')" } ,
- 45 { className : "justifyCenter" , title : "Justify center" , handler : "xed.handleJustify('center')" } ,
- 46 { className : "justifyRight" , title : "Justify right" , handler : "xed.handleJustify('right')" } ,
- 47 { className : "justifyBoth" , title : "Justify both" , handler : "xed.handleJustify('both')" }
- 48 ] ,
- 49 [
- 50 { className : "indent" , title : "Indent" , handler : "xed.handleIndent()" } ,
- 51 { className : "outdent" , title : "Outdent" , handler : "xed.handleOutdent()" }
- 52 ] ,
- 53 [
- 54 { className : "unorderedList" , title : "Unordered list" , handler : "xed.handleList('UL')" } ,
- 55 { className : "orderedList" , title : "Ordered list" , handler : "xed.handleList('OL')" }
- 56 ] ,
- 57 [
- 58 { className : "paragraph" , title : "Paragraph" , handler : "xed.handleApplyBlock('P')" } ,
- 59 { className : "heading1" , title : "Heading 1" , handler : "xed.handleApplyBlock('H1')" } ,
- 60 { className : "blockquote" , title : "Blockquote" , handler : "xed.handleApplyBlock('BLOCKQUOTE')" } ,
- 61 { className : "code" , title : "Code" , handler : "xed.handleList('CODE')" } ,
- 62 { className : "division" , title : "Division" , handler : "xed.handleApplyBlock('DIV')" }
- 63 ] ,
- 64 [
- 65 { className : "table" , title : "Table" , handler : "xed.handleTable(3,3,'tl')" } ,
- 66 { className : "separator" , title : "Separator" , handler : "xed.handleSeparator()" }
- 67 ] ,
- 68 [
- 69 { className : "html" , title : "Edit source" , handler : "xed.toggleSourceAndWysiwygMode()" }
- 70 ] ,
- 71 [
- 72 { className : "undo" , title : "Undo" , handler : "xed.handleUndo()" } ,
- 73 { className : "redo" , title : "Redo" , handler : "xed.handleRedo()" }
- 74 ]
- 75 ] ;
- 76
- 77 this.config.imagePathForDefaultToobar = 'img/toolbar/' ;
- 78
- 79 // relative | host_relative | absolute | browser_default
- 80 this.config.urlValidationMode = 'absolute' ;
- 81
- 82 this.config.automaticallyHookSubmitEvent = true ;
- 83
- 84 this.config.allowedTags = [ 'a' , 'abbr' , 'acronym' , 'address' , 'blockquote' , 'br' , 'caption' , 'cite' , 'code' , 'dd' , 'dfn' , 'div' , 'dl' , 'dt' , 'em' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'hr' , 'img' , 'kbd' , 'li' , 'ol' , 'p' , 'pre' , 'q' , 'samp' , 'span' , 'sup' , 'sub' , 'strong' , 'table' , 'thead' , 'tbody' , 'td' , 'th' , 'tr' , 'ul' , 'var' ] ;
- 85 this.config.allowedAttributes = [ 'alt' , 'cite' , 'class' , 'datetime' , 'height' , 'href' , 'id' , 'rel' , 'rev' , 'src' , 'style' , 'title' , 'width' ] ;
- 86
- 87 this.config.shortcuts = { } ;
- 88 this.config.autocorrections = { } ;
- 89 this.config.autocompletions = { } ;
- 90 this.config.templateProcessors = { } ;
- 91 this.config.contextMenuHandlers = { } ;
- 92
- 93 /**
- 94 * Original content element
- 95 * @type Element
- 96 */
- 97 this.contentElement = contentElement ;
- 98
- 99 /**
-100 * Owner document of content element
-101 * @type Document
-102 */
-103 this.doc = this.contentElement.ownerDocument ;
-104
-105 /**
-106 * Body of content element
-107 * @type Element
-108 */
-109 this.body = this.doc.body ;
-110
-111 /**
-112 * False or 'readonly' means read-only mode, true or 'wysiwyg' means WYSIWYG editing mode, and 'source' means source editing mode.
-113 * @type Object
-114 */
-115 this.currentEditMode = 'readonly' ;
-116
-117 /**
-118 * RichDom instance
-119 * @type xq.RichDom
-120 */
-121 this.rdom = xq.RichDom.createInstance ( ) ;
-122
-123 /**
-124 * Validator instance
-125 * @type xq.Validator
-126 */
-127 this.validator = null ;
-128
-129 /**
-130 * Outmost wrapper div
-131 * @type Element
-132 */
-133 this.outmostWrapper = null ;
-134
-135 /**
-136 * Source editor container
-137 * @type Element
-138 */
-139 this.sourceEditorDiv = null ;
-140
-141 /**
-142 * Source editor textarea
-143 * @type Element
-144 */
-145 this.sourceEditorTextarea = null ;
-146
-147 /**
-148 * WYSIWYG editor container
-149 * @type Element
-150 */
-151 this.wysiwygEditorDiv = null ;
-152
-153 /**
-154 * Design mode iframe
-155 * @type IFrame
-156 */
-157 this.editorFrame = null ;
-158
-159 /**
-160 * Window that contains design mode iframe
-161 * @type Window
-162 */
-163 this.editorWin = null ;
-164
-165 /**
-166 * Document that contained by design mode iframe
-167 * @type Document
-168 */
-169 this.editorDoc = null ;
-170
-171 /**
-172 * Body that contained by design mode iframe
-173 * @type Element
-174 */
-175 this.editorBody = null ;
-176
-177 /**
-178 * Toolbar container
-179 * @type Element
-180 */
-181 this.toolbarContainer = toolbarContainer ;
-182
-183 /**
-184 * Toolbar buttons
-185 * @type Array
-186 */
-187 this.toolbarButtons = null ;
-188
-189 /**
-190 * Undo/redo manager
-191 * @type xq.EditHistory
-192 */
-193 this.editHistory = null ;
-194
-195 this._contextMenuContainer = null ;
-196 this._contextMenuItems = null ;
-197
-198 this._validContentCache = null ;
-199 this._lastModified = null ;
-200
-201 this.addShortcuts ( this._getDefaultShortcuts ( ) ) ;
-202 this.addTemplateProcessors ( this._getDefaultTemplateProcessors ( ) ) ;
-203
-204 this.addListener ( {
-205 onEditorCurrentContentChanged : function ( xed ) {
-206 var curFocusElement = xed.rdom.getCurrentElement ( ) ;
-207 if ( ! curFocusElement ) return ;
-208
-209 if ( xed._lastFocusElement != curFocusElement ) {
-210 if ( ! xed.rdom.tree.isBlockOnlyContainer ( xed._lastFocusElement ) && xed.rdom.tree.isBlock ( xed._lastFocusElement ) ) {
-211 xed.rdom.removeTrailingWhitespace ( xed._lastFocusElement ) ;
-212 }
-213 xed._fireOnElementChanged ( xed._lastFocusElement , curFocusElement ) ;
-214 xed._lastFocusElement = curFocusElement ;
-215 }
-216
-217 xed.updateAllToolbarButtonsStatus ( curFocusElement ) ;
-218 }
-219 } ) ;
-220 } ,
-221
-222
-223
-224 /////////////////////////////////////////////
-225 // Configuration Management
-226
-227 _getDefaultShortcuts : function ( ) {
-228 if ( xq.Browser.isMac ) {
-229 // Mac FF & Safari
-230 return [
-231 { event : "Ctrl+Shift+SPACE" , handler : "this.handleAutocompletion(); stop = true;" } ,
-232 { event : "ENTER" , handler : "this.handleEnter(false, false)" } ,
-233 { event : "Ctrl+ENTER" , handler : "this.handleEnter(true, false)" } ,
-234 { event : "Ctrl+Shift+ENTER" , handler : "this.handleEnter(true, true)" } ,
-235 { event : "TAB" , handler : "this.handleTab()" } ,
-236 { event : "Shift+TAB" , handler : "this.handleShiftTab()" } ,
-237 { event : "DELETE" , handler : "this.handleDelete()" } ,
-238 { event : "BACKSPACE" , handler : "this.handleBackspace()" } ,
-239
-240 { event : "Ctrl+B" , handler : "this.handleStrongEmphasis()" } ,
-241 { event : "Ctrl+I" , handler : "this.handleEmphasis()" } ,
-242 { event : "Ctrl+U" , handler : "this.handleUnderline()" } ,
-243 { event : "Ctrl+K" , handler : "this.handleStrike()" } ,
-244 { event : "Meta+Z" , handler : "this.handleUndo()" } ,
-245 { event : "Meta+Shift+Z" , handler : "this.handleRedo()" } ,
-246 { event : "Meta+Y" , handler : "this.handleRedo()" }
-247 ] ;
-248 } else if ( xq.Browser.isUbuntu ) {
-249 // Ubunto FF
-250 return [
-251 { event : "Ctrl+SPACE" , handler : "this.handleAutocompletion(); stop = true;" } ,
-252 { event : "ENTER" , handler : "this.handleEnter(false, false)" } ,
-253 { event : "Ctrl+ENTER" , handler : "this.handleEnter(true, false)" } ,
-254 { event : "Ctrl+Shift+ENTER" , handler : "this.handleEnter(true, true)" } ,
-255 { event : "TAB" , handler : "this.handleTab()" } ,
-256 { event : "Shift+TAB" , handler : "this.handleShiftTab()" } ,
-257 { event : "DELETE" , handler : "this.handleDelete()" } ,
-258 { event : "BACKSPACE" , handler : "this.handleBackspace()" } ,
-259
-260 { event : "Ctrl+B" , handler : "this.handleStrongEmphasis()" } ,
-261 { event : "Ctrl+I" , handler : "this.handleEmphasis()" } ,
-262 { event : "Ctrl+U" , handler : "this.handleUnderline()" } ,
-263 { event : "Ctrl+K" , handler : "this.handleStrike()" } ,
-264 { event : "Ctrl+Z" , handler : "this.handleUndo()" } ,
-265 { event : "Ctrl+Y" , handler : "this.handleRedo()" }
-266 ] ;
-267 } else {
-268 // Win IE & FF
-269 return [
-270 { event : "Ctrl+SPACE" , handler : "this.handleAutocompletion(); stop = true;" } ,
-271 { event : "ENTER" , handler : "this.handleEnter(false, false)" } ,
-272 { event : "Ctrl+ENTER" , handler : "this.handleEnter(true, false)" } ,
-273 { event : "Ctrl+Shift+ENTER" , handler : "this.handleEnter(true, true)" } ,
-274 { event : "TAB" , handler : "this.handleTab()" } ,
-275 { event : "Shift+TAB" , handler : "this.handleShiftTab()" } ,
-276 { event : "DELETE" , handler : "this.handleDelete()" } ,
-277 { event : "BACKSPACE" , handler : "this.handleBackspace()" } ,
-278
-279 { event : "Ctrl+B" , handler : "this.handleStrongEmphasis()" } ,
-280 { event : "Ctrl+I" , handler : "this.handleEmphasis()" } ,
-281 { event : "Ctrl+U" , handler : "this.handleUnderline()" } ,
-282 { event : "Ctrl+K" , handler : "this.handleStrike()" } ,
-283 { event : "Ctrl+Z" , handler : "this.handleUndo()" } ,
-284 { event : "Ctrl+Y" , handler : "this.handleRedo()" }
-285 ] ;
-286 }
-287 } ,
-288
-289 _getDefaultTemplateProcessors : function ( ) {
-290 return [
-291 {
-292 id : "predefinedKeywordProcessor" ,
-293 handler : function ( html ) {
-294 var today = Date.get ( ) ;
-295 var keywords = {
-296 year : today.getFullYear ( ) ,
-297 month : today.getMonth ( ) + 1 ,
-298 date : today.getDate ( ) ,
-299 hour : today.getHours ( ) ,
-300 min : today.getMinutes ( ) ,
-301 sec : today.getSeconds ( )
-302 } ;
-303
-304 return html.replace ( /\{xq:(year|month|date|hour|min|sec)\}/img , function ( text , keyword ) {
-305 return keywords [ keyword ] || keyword ;
-306 } ) ;
-307 }
-308 }
-309 ] ;
-310 } ,
-311
-312 /**
-313 * Adds or replaces keyboard shortcut.
-314 *
-315 * @param {String} shortcut keymap expression like "CTRL+Space"
-316 * @param {Object} handler string or function to be evaluated or called
-317 */
-318 addShortcut : function ( shortcut , handler ) {
-319 this.config.shortcuts [ shortcut ] = { "event" : new xq.Shortcut ( shortcut ) , "handler" : handler } ;
-320 } ,
-321
-322 /**
-323 * Adds several keyboard shortcuts at once.
-324 *
-325 * @param {Array} list of shortcuts. each element should have following structure: {event:"keymap expression", handler:handler}
-326 */
-327 addShortcuts : function ( list ) {
-328 list.each ( function ( shortcut ) {
-329 this.addShortcut ( shortcut.event , shortcut.handler ) ;
-330 } . bind ( this ) ) ;
-331 } ,
-332
-333 /**
-334 * Returns keyboard shortcut matches with given keymap expression.
-335 *
-336 * @param {String} shortcut keymap expression like "CTRL+Space"
-337 */
-338 getShortcut : function ( shortcut ) { return this.config.shortcuts [ shortcut ] ; } ,
-339
-340 /**
-341 * Returns entire keyboard shortcuts' map
-342 */
-343 getShortcuts : function ( ) { return this.config.shortcuts ; } ,
-344
-345 /**
-346 * Remove keyboard shortcut matches with given keymap expression.
-347 *
-348 * @param {String} shortcut keymap expression like "CTRL+Space"
-349 */
-350 removeShortcut : function ( shortcut ) { delete this.config.shortcuts [ shortcut ] ; } ,
-351
-352 /**
-353 * Adds or replaces autocorrection handler.
-354 *
-355 * @param {String} id unique identifier
-356 * @param {Object} criteria regex pattern or function to be used as a criterion for match
-357 * @param {Object} handler string or function to be evaluated or called when criteria met
-358 */
-359 addAutocorrection : function ( id , criteria , handler ) {
-360 if ( criteria.exec ) {
-361 var pattern = criteria ;
-362 criteria = function ( text ) { return text.match ( pattern ) } ;
-363 }
-364 this.config.autocorrections [ id ] = { "criteria" : criteria , "handler" : handler } ;
-365 } ,
-366
-367 /**
-368 * Adds several autocorrection handlers at once.
-369 *
-370 * @param {Array} list of autocorrection. each element should have following structure: {id:"identifier", criteria:criteria, handler:handler}
-371 */
-372 addAutocorrections : function ( list ) {
-373 list.each ( function ( ac ) {
-374 this.addAutocorrection ( ac.id , ac.criteria , ac.handler ) ;
-375 } . bind ( this ) ) ;
-376 } ,
-377
-378 /**
-379 * Returns autocorrection handler matches with given id
-380 *
-381 * @param {String} id unique identifier
-382 */
-383 getAutocorrection : function ( id ) { return this.config.autocorrection [ id ] ; } ,
-384
-385 /**
-386 * Returns entire autocorrections' map
-387 */
-388 getAutocorrections : function ( ) { return this.config.autocorrections ; } ,
-389
-390 /**
-391 * Removes autocorrection handler matches with given id
-392 *
-393 * @param {String} id unique identifier
-394 */
-395 removeAutocorrection : function ( id ) { delete this.config.autocorrections [ id ] ; } ,
-396
-397 /**
-398 * Adds or replaces autocompletion handler.
-399 *
-400 * @param {String} id unique identifier
-401 * @param {Object} criteria regex pattern or function to be used as a criterion for match
-402 * @param {Object} handler string or function to be evaluated or called when criteria met
-403 */
-404 addAutocompletion : function ( id , criteria , handler ) {
-405 if ( criteria.exec ) {
-406 var pattern = criteria ;
-407 criteria = function ( text ) {
-408 var m = pattern.exec ( text ) ;
-409 return m ? m.index : - 1 ;
-410 } ;
-411 }
-412 this.config.autocompletions [ id ] = { "criteria" : criteria , "handler" : handler } ;
-413 } ,
-414
-415 /**
-416 * Adds several autocompletion handlers at once.
-417 *
-418 * @param {Array} list of autocompletion. each element should have following structure: {id:"identifier", criteria:criteria, handler:handler}
-419 */
-420 addAutocompletions : function ( list ) {
-421 list.each ( function ( ac ) {
-422 this.addAutocompletion ( ac.id , ac.criteria , ac.handler ) ;
-423 } . bind ( this ) ) ;
-424 } ,
-425
-426 /**
-427 * Returns autocompletion handler matches with given id
-428 *
-429 * @param {String} id unique identifier
-430 */
-431 getAutocompletion : function ( id ) { return this.config.autocompletions [ id ] ; } ,
-432
-433 /**
-434 * Returns entire autocompletions' map
-435 */
-436 getAutocompletions : function ( ) { return this.config.autocompletions ; } ,
-437
-438 /**
-439 * Removes autocompletion handler matches with given id
-440 *
-441 * @param {String} id unique identifier
-442 */
-443 removeAutocompletion : function ( id ) { delete this.config.autocompletions [ id ] ; } ,
-444
-445 /**
-446 * Adds or replaces template processor.
-447 *
-448 * @param {String} id unique identifier
-449 * @param {Object} handler string or function to be evaluated or called when template inserted
-450 */
-451 addTemplateProcessor : function ( id , handler ) {
-452 this.config.templateProcessors [ id ] = { "handler" : handler } ;
-453 } ,
-454
-455 /**
-456 * Adds several template processors at once.
-457 *
-458 * @param {Array} list of template processors. Each element should have following structure: {id:"identifier", handler:handler}
-459 */
-460 addTemplateProcessors : function ( list ) {
-461 list.each ( function ( tp ) {
-462 this.addTemplateProcessor ( tp.id , tp.handler ) ;
-463 } . bind ( this ) ) ;
-464 } ,
-465
-466 /**
-467 * Returns template processor matches with given id
-468 *
-469 * @param {String} id unique identifier
-470 */
-471 getTemplateProcessor : function ( id ) { return this.config.templateProcessors [ id ] ; } ,
-472
-473 /**
-474 * Returns entire template processors' map
-475 */
-476 getTemplateProcessors : function ( ) { return this.config.templateProcessors ; } ,
-477
-478 /**
-479 * Removes template processor matches with given id
-480 *
-481 * @param {String} id unique identifier
-482 */
-483 removeTemplateProcessor : function ( id ) { delete this.config.templateProcessors [ id ] ; } ,
-484
-485
-486
-487 /**
-488 * Adds or replaces context menu handler.
-489 *
-490 * @param {String} id unique identifier
-491 * @param {Object} handler string or function to be evaluated or called when onContextMenu occured
-492 */
-493 addContextMenuHandler : function ( id , handler ) {
-494 this.config.contextMenuHandlers [ id ] = { "handler" : handler } ;
-495 } ,
-496
-497 /**
-498 * Adds several context menu handlers at once.
-499 *
-500 * @param {Array} list of handlers. Each element should have following structure: {id:"identifier", handler:handler}
-501 */
-502 addContextMenuHandlers : function ( list ) {
-503 list.each ( function ( mh ) {
-504 this.addContextMenuHandler ( mh.id , mh.handler ) ;
-505 } . bind ( this ) ) ;
-506 } ,
-507
-508 /**
-509 * Returns context menu handler matches with given id
-510 *
-511 * @param {String} id unique identifier
-512 */
-513 getContextMenuHandler : function ( id ) { return this.config.contextMenuHandlers [ id ] ; } ,
-514
-515 /**
-516 * Returns entire context menu handlers' map
-517 */
-518 getContextMenuHandlers : function ( ) { return this.config.contextMenuHandlers ; } ,
-519
-520 /**
-521 * Removes context menu handler matches with given id
-522 *
-523 * @param {String} id unique identifier
-524 */
-525 removeContextMenuHandler : function ( id ) { delete this.config.contextMenuHandlers [ id ] ; } ,
-526
-527
-528
-529 /////////////////////////////////////////////
-530 // Edit mode management
-531
-532 /**
-533 * Returns current edit mode - readonly, wysiwyg, source
-534 */
-535 getCurrentEditMode : function ( ) {
-536 return this.currentEditMode ;
-537 } ,
-538
-539 toggleSourceAndWysiwygMode : function ( ) {
-540 var mode = this.getCurrentEditMode ( ) ;
-541 if ( mode == 'readonly' ) return ;
-542 this.setEditMode ( mode == 'wysiwyg' ? 'source' : 'wysiwyg' ) ;
-543
-544 return true ;
-545 } ,
-546
-547 /**
-548 * Switches between edit-mode/normal mode.
-549 *
-550 * @param {Object} mode false or 'readonly' means read-only mode, true or 'wysiwyg' means WYSIWYG editing mode, and 'source' means source editing mode.
-551 */
-552 setEditMode : function ( mode ) {
-553 if ( this.currentEditMode == mode ) return ;
-554
-555 var firstCall = mode != false && mode != 'readonly' && ! this.outmostWrapper ;
-556 if ( firstCall ) {
-557 // Create editor element if needed
-558 this._createEditorFrame ( ) ;
-559 this._registerEventHandlers ( ) ;
-560
-561 this.loadCurrentContentFromStaticContent ( ) ;
-562 this.editHistory = new xq.EditHistory ( this.rdom ) ;
-563 }
-564
-565 if ( mode == 'wysiwyg' ) {
-566 // Update contents
-567 if ( this.currentEditMode == 'source' ) this.setStaticContent ( this.getSourceContent ( ) ) ;
-568 this.loadCurrentContentFromStaticContent ( ) ;
-569
-570 // Make static content invisible
-571 this.contentElement.style.display = "none" ;
-572
-573 // Make WYSIWYG editor visible
-574 this.sourceEditorDiv.style.display = "none" ;
-575 this.wysiwygEditorDiv.style.display = "block" ;
-576 this.outmostWrapper.style.display = "block" ;
-577
-578 this.currentEditMode = mode ;
-579
-580 if ( ! xq.Browser.isTrident ) {
-581 window.setTimeout ( function ( ) {
-582 if ( this.getDoc ( ) . designMode == 'On' ) return ;
-583
-584 // Without it, Firefox doesn't display embedded SWF
-585 this.getDoc ( ) . designMode = 'On' ;
-586
-587 // turn off Firefox's table editing feature
-588 try { this.getDoc ( ) . execCommand ( "enableInlineTableEditing" , false , "false" ) } catch ( ignored ) { }
-589 } . bind ( this ) , 0 ) ;
-590 }
-591
-592 this.enableToolbarButtons ( ) ;
-593 if ( ! firstCall ) this.focus ( ) ;
-594 } else if ( mode == 'source' ) {
-595 // Update contents
-596 if ( this.currentEditMode == 'wysiwyg' ) this.setStaticContent ( this.getWysiwygContent ( ) ) ;
-597 this.loadCurrentContentFromStaticContent ( ) ;
-598
-599 // Make static content invisible
-600 this.contentElement.style.display = "none" ;
-601
-602 // Make source editor visible
-603 this.sourceEditorDiv.style.display = "block" ;
-604 this.wysiwygEditorDiv.style.display = "none" ;
-605 this.outmostWrapper.style.display = "block" ;
-606
-607 this.currentEditMode = mode ;
-608
-609 this.disableToolbarButtons ( [ 'html' ] ) ;
-610 if ( ! firstCall ) this.focus ( ) ;
-611 } else {
-612 // Update contents
-613 this.setStaticContent ( this.getCurrentContent ( ) ) ;
-614 this.loadCurrentContentFromStaticContent ( ) ;
-615
-616 // Make editor and toolbar invisible
-617 this.outmostWrapper.style.display = "none" ;
-618
-619 // Make static content visible
-620 this.contentElement.style.display = "block" ;
-621
-622 this.currentEditMode = mode ;
-623 }
-624
-625 this._fireOnCurrentEditModeChanged ( this , mode ) ;
-626 } ,
-627
-628 /**
-629 * Load CSS into editing-mode document
-630 *
-631 * @param {string} path URL
-632 */
-633 loadStylesheet : function ( path ) {
-634 var head = this.editorDoc.getElementsByTagName ( "HEAD" ) [ 0 ] ;
-635 var link = this.editorDoc.createElement ( "LINK" ) ;
-636 link.rel = "Stylesheet" ;
-637 link.type = "text/css" ;
-638 link.href = path ;
-639 head.appendChild ( link ) ;
-640 } ,
-641
-642 /**
-643 * Sets editor's dynamic content from static content
-644 */
-645 loadCurrentContentFromStaticContent : function ( ) {
-646 // update WYSIWYG editor
-647 var html = this.validator.invalidate ( this.getStaticContentAsDOM ( ) ) ;
-648 html = this.removeUnnecessarySpaces ( html ) ;
-649
-650 if ( html.blank ( ) ) {
-651 this.rdom.clearRoot ( ) ;
-652 } else {
-653 this.rdom.getRoot ( ) . innerHTML = html ;
-654 }
-655 this.rdom.wrapAllInlineOrTextNodesAs ( "P" , this.rdom.getRoot ( ) , true ) ;
-656
-657 // update source editor
-658 var source = this.getWysiwygContent ( true , true ) ;
-659
-660 this.sourceEditorTextarea.value = source ;
-661 if ( xq.Browser.isWebkit ) {
-662 this.sourceEditorTextarea.innerHTML = source ;
-663 }
-664
-665 this._fireOnCurrentContentChanged ( this ) ;
-666 } ,
-667
-668 /**
-669 * Enables all toolbar buttons
-670 *
-671 * @param {Array} [exceptions] array of string containing classnames to exclude
-672 */
-673 enableToolbarButtons : function ( exceptions ) {
-674 if ( ! this.toolbarContainer ) return ;
-675
-676 this._execForAllToolbarButtons ( exceptions , function ( li , exception ) {
-677 li.firstChild.className = ! exception ? '' : 'disabled' ;
-678 } ) ;
-679
-680 // Toolbar image icon disappears without following code:
-681 if ( xq.Browser.isIE6 ) {
-682 this.toolbarContainer.style.display = 'none' ;
-683 setTimeout ( function ( ) { this.toolbarContainer.style.display = 'block' ; } . bind ( this ) , 0 ) ;
-684 }
-685 } ,
-686
-687 /**
-688 * Disables all toolbar buttons
-689 *
-690 * @param {Array} [exceptions] array of string containing classnames to exclude
-691 */
-692 disableToolbarButtons : function ( exceptions ) {
-693 this._execForAllToolbarButtons ( exceptions , function ( li , exception ) {
-694 li.firstChild.className = exception ? '' : 'disabled' ;
-695 } ) ;
-696 } ,
-697
-698 _execForAllToolbarButtons : function ( exceptions , exec ) {
-699 if ( ! this.toolbarContainer ) return ;
-700 exceptions = exceptions || [ ] ;
-701
-702 $ ( this.toolbarContainer ) . select ( 'li' ) . each ( function ( li ) {
-703 var buttonsClassName = li.classNames ( ) . find ( function ( name ) { return name != 'xq_separator' } ) ;
-704 var exception = exceptions.include ( buttonsClassName ) ;
-705 exec ( li , exception ) ;
-706 } ) ;
-707 } ,
-708
-709 _updateToolbarButtonStatus : function ( buttonClassName , selected ) {
-710 var button = this.toolbarButtons.get ( buttonClassName ) ;
-711 if ( button ) button.firstChild.firstChild.className = selected ? 'selected' : '' ;
-712 } ,
-713
-714 updateAllToolbarButtonsStatus : function ( element ) {
-715 if ( ! this.toolbarContainer ) return ;
-716 if ( ! this.toolbarButtons ) {
-717 var classNames = [
-718 "emphasis" , "strongEmphasis" , "underline" , "strike" , "superscription" , "subscription" ,
-719 "justifyLeft" , "justifyCenter" , "justifyRight" , "justifyBoth" ,
-720 "unorderedList" , "orderedList" , "code" ,
-721 "paragraph" , "heading1" , "heading2" , "heading3" , "heading4" , "heading5" , "heading6"
-722 ] ;
-723
-724 this.toolbarButtons = $H ( { } ) ;
-725
-726 classNames.each ( function ( className ) {
-727 var found = $ ( this.toolbarContainer ) . getElementsBySelector ( "." + className ) ;
-728 var button = found && found.length > 0 ? found [ 0 ] : null ;
-729 if ( button ) this.toolbarButtons.set ( className , button ) ;
-730 } . bind ( this ) ) ;
-731 }
-732
-733 var buttons = this.toolbarButtons ;
-734
-735 var info = this.rdom.collectStructureAndStyle ( element ) ;
-736
-737 this._updateToolbarButtonStatus ( 'emphasis' , info.em ) ;
-738 this._updateToolbarButtonStatus ( 'strongEmphasis' , info.strong ) ;
-739 this._updateToolbarButtonStatus ( 'underline' , info.underline ) ;
-740 this._updateToolbarButtonStatus ( 'strike' , info.strike ) ;
-741 this._updateToolbarButtonStatus ( 'superscription' , info.superscription ) ;
-742 this._updateToolbarButtonStatus ( 'subscription' , info.subscription ) ;
-743
-744 this._updateToolbarButtonStatus ( 'justifyLeft' , info.justification == 'left' ) ;
-745 this._updateToolbarButtonStatus ( 'justifyCenter' , info.justification == 'center' ) ;
-746 this._updateToolbarButtonStatus ( 'justifyRight' , info.justification == 'right' ) ;
-747 this._updateToolbarButtonStatus ( 'justifyBoth' , info.justification == 'justify' ) ;
-748
-749 this._updateToolbarButtonStatus ( 'orderedList' , info.list == 'OL' ) ;
-750 this._updateToolbarButtonStatus ( 'unorderedList' , info.list == 'UL' ) ;
-751 this._updateToolbarButtonStatus ( 'code' , info.list == 'CODE' ) ;
-752
-753 this._updateToolbarButtonStatus ( 'paragraph' , info.block == 'P' ) ;
-754 this._updateToolbarButtonStatus ( 'heading1' , info.block == 'H1' ) ;
-755 this._updateToolbarButtonStatus ( 'heading2' , info.block == 'H2' ) ;
-756 this._updateToolbarButtonStatus ( 'heading3' , info.block == 'H3' ) ;
-757 this._updateToolbarButtonStatus ( 'heading4' , info.block == 'H4' ) ;
-758 this._updateToolbarButtonStatus ( 'heading5' , info.block == 'H5' ) ;
-759 this._updateToolbarButtonStatus ( 'heading6' , info.block == 'H6' ) ;
-760 } ,
-761
-762 removeUnnecessarySpaces : function ( html ) {
-763 var blocks = this.rdom.tree.getBlockTags ( ) . join ( "|" ) ;
-764 var regex = new RegExp ( "\\s*<(/?)(" + blocks + ")>\\s*" , "img" ) ;
-765 return html.replace ( regex , '<$1$2>' ) ;
-766 } ,
-767
-768 /**
-769 * Gets editor's dynamic content from current editor(source or WYSIWYG)
-770 *
-771 * @return {Object} HTML String
-772 */
-773 getCurrentContent : function ( performFullValidation ) {
-774 if ( this.getCurrentEditMode ( ) == 'source' ) {
-775 return this.getSourceContent ( performFullValidation ) ;
-776 } else {
-777 return this.getWysiwygContent ( performFullValidation ) ;
-778 }
-779 } ,
-780
-781 /**
-782 * Gets editor's dynamic content from WYSIWYG editor
-783 *
-784 * @return {Object} HTML String
-785 */
-786 getWysiwygContent : function ( performFullValidation , dontUseCache ) {
-787 if ( dontUseCache || ! performFullValidation ) return this.validator.validate ( this.rdom.getRoot ( ) , performFullValidation ) ;
-788
-789 var lastModified = this.editHistory.getLastModifiedDate ( ) ;
-790 if ( this._lastModified != lastModified ) {
-791 this._validContentCache = this.validator.validate ( this.rdom.getRoot ( ) , performFullValidation ) ;
-792 this._lastModified = lastModified ;
-793 }
-794 return this._validContentCache ;
-795 } ,
-796
-797 /**
-798 * Gets editor's dynamic content from source editor
-799 *
-800 * @return {Object} HTML String
-801 */
-802 getSourceContent : function ( performFullValidation ) {
-803 var raw = this.sourceEditorTextarea [ xq.Browser.isWebkit ? 'innerHTML' : 'value' ] ;
-804 var tempDiv = document.createElement ( 'div' ) ;
-805 tempDiv.innerHTML = this.removeUnnecessarySpaces ( raw ) ;
-806
-807 var rdom = xq.RichDom.createInstance ( ) ;
-808 rdom.setRoot ( document.body ) ;
-809 rdom.wrapAllInlineOrTextNodesAs ( "P" , tempDiv , true ) ;
-810
-811 return this.validator.validate ( tempDiv , performFullValidation ) ;
-812 } ,
-813
-814 /**
-815 * Sets editor's original content
-816 *
-817 * @param {Object} content HTML String
-818 */
-819 setStaticContent : function ( content ) {
-820 if ( this.contentElement.nodeName == 'TEXTAREA' ) {
-821 this.contentElement.value = content ;
-822 if ( xq.Browser.isWebkit ) {
-823 this.contentElement.innerHTML = content ;
-824 }
-825 } else {
-826 this.contentElement.innerHTML = content ;
-827 }
-828 this._fireOnStaticContentChanged ( this , content ) ;
-829 } ,
-830
-831 /**
-832 * Gets editor's original content
-833 *
-834 * @return {Object} HTML String
-835 */
-836 getStaticContent : function ( ) {
-837 var content ;
-838 if ( this.contentElement.nodeName == 'TEXTAREA' ) {
-839 content = this.contentElement [ xq.Browser.isWebkit ? 'innerHTML' : 'value' ] ;
-840 } else {
-841 content = this.contentElement.innerHTML ;
-842 }
-843 return content ;
-844 } ,
-845
-846 /**
-847 * Gets editor's original content as DOM node
-848 *
-849 * @return {Object} HTML String
-850 */
-851 getStaticContentAsDOM : function ( ) {
-852 if ( this.contentElement.nodeName == 'TEXTAREA' ) {
-853 var div = this.doc.createElement ( 'DIV' ) ;
-854 div.innerHTML = this.contentElement [ xq.Browser.isWebkit ? 'innerHTML' : 'value' ] ;
-855 return div ;
-856 } else {
-857 return this.contentElement ;
-858 }
-859 } ,
-860
-861 /**
-862 * Gives focus to editor
-863 */
-864 focus : function ( ) {
-865 if ( this.getCurrentEditMode ( ) == 'wysiwyg' ) {
-866 this.rdom.focus ( ) ;
-867 window.setTimeout ( function ( ) {
-868 this.updateAllToolbarButtonsStatus ( this.rdom.getCurrentElement ( ) ) ;
-869 } . bind ( this ) , 0 ) ;
-870 } else if ( this.getCurrentEditMode ( ) == 'source' ) {
-871 this.sourceEditorTextarea.focus ( ) ;
-872 }
-873 } ,
-874
-875 /**
-876 * Returns designmode iframe object
-877 */
-878 getFrame : function ( ) {
-879 return this.editorFrame ;
-880 } ,
-881
-882 /**
-883 * Returns designmode window object
-884 */
-885 getWin : function ( ) {
-886 return this.editorWin ;
-887 } ,
-888
-889 /**
-890 * Returns designmode document object
-891 */
-892 getDoc : function ( ) {
-893 return this.editorDoc ;
-894 } ,
-895
-896 /**
-897 * Returns outmost wrapper element
-898 */
-899 getOutmostWrapper : function ( ) {
-900 return this.outmostWrapper ;
-901 } ,
-902
-903 /**
-904 * Returns designmode body object
-905 */
-906 getBody : function ( ) {
-907 return this.editorBody ;
-908 } ,
-909
-910 _createEditorFrame : function ( ) {
-911 // create outer DIV
-912 this.outmostWrapper = this.doc.createElement ( 'div' ) ;
-913 this.outmostWrapper.className = "xquared" ;
-914
-915 this.contentElement.parentNode.insertBefore ( this.outmostWrapper , this.contentElement ) ;
-916
-917 // create toolbar is needed
-918 if ( ! this.toolbarContainer && this.config.generateDefaultToolbar ) {
-919 this.toolbarContainer = this._generateDefaultToolbar ( ) ;
-920 this.outmostWrapper.appendChild ( this.toolbarContainer ) ;
-921 }
-922
-923 // create source editor div
-924 this.sourceEditorDiv = this.doc.createElement ( 'div' ) ;
-925 this.sourceEditorDiv.className = "editor source_editor" ; //TODO: remove editor
-926 this.sourceEditorDiv.style.display = "none" ;
-927 this.outmostWrapper.appendChild ( this.sourceEditorDiv ) ;
-928
-929 // create TEXTAREA for source editor
-930 this.sourceEditorTextarea = this.doc.createElement ( 'textarea' ) ;
-931 this.sourceEditorDiv.appendChild ( this.sourceEditorTextarea ) ;
-932
-933 // create WYSIWYG editor div
-934 this.wysiwygEditorDiv = this.doc.createElement ( 'div' ) ;
-935 this.wysiwygEditorDiv.className = "editor wysiwyg_editor" ; //TODO: remove editor
-936 this.wysiwygEditorDiv.style.display = "none" ;
-937 this.outmostWrapper.appendChild ( this.wysiwygEditorDiv ) ;
-938
-939 // create designmode iframe for WYSIWYG editor
-940 this.editorFrame = this.doc.createElement ( 'iframe' ) ;
-941 this.rdom.setAttributes ( this.editorFrame , {
-942 "frameBorder" : "0" ,
-943 "marginWidth" : "0" ,
-944 "marginHeight" : "0" ,
-945 "leftMargin" : "0" ,
-946 "topMargin" : "0" ,
-947 "allowTransparency" : "true"
-948 } ) ;
-949 this.wysiwygEditorDiv.appendChild ( this.editorFrame ) ;
-950
-951 var doc = this.editorFrame.contentWindow.document ;
-952 if ( xq.Browser.isTrident ) doc.designMode = 'On' ;
-953
-954 doc.open ( ) ;
-955 doc.write ( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">' ) ;
-956 doc.write ( '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko">' ) ;
-957 doc.write ( '<head>' ) ;
-958
-959 // it is needed to force href of pasted content to be an absolute url
-960 if ( ! xq.Browser.isTrident ) doc.write ( '<base href="./" />' ) ;
-961
-962 doc.write ( '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />' ) ;
-963 doc.write ( '<title>XQuared</title>' ) ;
-964 if ( this.config.changeCursorOnLink ) doc.write ( '<style>.xed a {cursor: pointer !important;}</style>' ) ;
-965 doc.write ( '</head>' ) ;
-966 doc.write ( '<body><p>' + this.rdom.makePlaceHolderString ( ) + '</p></body>' ) ;
-967 doc.write ( '</html>' ) ;
-968 doc.close ( ) ;
-969
-970 this.editorWin = this.editorFrame.contentWindow ;
-971 this.editorDoc = this.editorWin.document ;
-972 this.editorBody = this.editorDoc.body ;
-973 this.editorBody.className = "xed" ;
-974
-975 // it is needed to fix IE6 horizontal scrollbar problem
-976 if ( xq.Browser.isIE6 ) {
-977 this.editorDoc.documentElement.style.overflowY = 'auto' ;
-978 this.editorDoc.documentElement.style.overflowX = 'hidden' ;
-979 }
-980
-981 this.rdom.setWin ( this.editorWin ) ;
-982 this.rdom.setRoot ( this.editorBody ) ;
-983 this.validator = xq.Validator.createInstance ( this.doc.location.href , this.config.urlValidationMode , this.config.allowedTags , this.config.allowedAttributes ) ;
-984
-985 // hook onsubmit of form
-986 if ( this.config.automaticallyHookSubmitEvent && this.contentElement.nodeName == 'TEXTAREA' && this.contentElement.form ) {
-987 var original = this.contentElement.form.onsubmit ;
-988
-989 this.contentElement.form.onsubmit = function ( ) {
-990 this.contentElement.value = this.getCurrentContent ( true ) ;
-991 if ( original ) {
-992 return original ( ) ;
-993 } else {
-994 return true ;
-995 }
-996 } . bind ( this ) ;
-997 }
-998 } ,
-999
-1000 _addStyleRule : function ( selector , rule ) {
-1001 if ( ! this.dynamicStyle ) {
-1002 if ( xq.Browser.isTrident ) {
-1003 this.dynamicStyle = this.doc.createStyleSheet ( ) ;
-1004 } else {
-1005 var style = this.doc.createElement ( 'style' ) ;
-1006 this.doc.body.appendChild ( style ) ;
-1007 this.dynamicStyle = $A ( this.doc.styleSheets ) . last ( ) ;
-1008 }
-1009 }
-1010
-1011 if ( xq.Browser.isTrident ) {
-1012 this.dynamicStyle.addRule ( selector , rule ) ;
-1013 } else {
-1014 this.dynamicStyle.insertRule ( selector + " {" + rule + "}" , this.dynamicStyle.cssRules.length ) ;
-1015 }
-1016 } ,
-1017
-1018 _generateDefaultToolbar : function ( ) {
-1019 // override image path
-1020 this._addStyleRule ( ".xquared div.toolbar" , "background-image: url(" + this.config.imagePathForDefaultToobar + "toolbarBg.gif)" ) ;
-1021 this._addStyleRule ( ".xquared ul.buttons li" , "background-image: url(" + this.config.imagePathForDefaultToobar + "toolbarButtonBg.gif)" ) ;
-1022 this._addStyleRule ( ".xquared ul.buttons li.xq_separator" , "background-image: url(" + this.config.imagePathForDefaultToobar + "toolbarSeparator.gif)" ) ;
-1023
-1024 // outmost container
-1025 var container = this.doc.createElement ( 'div' ) ;
-1026 container.className = 'toolbar' ;
-1027
-1028 // button container
-1029 var buttons = this.doc.createElement ( 'ul' ) ;
-1030 buttons.className = 'buttons' ;
-1031 container.appendChild ( buttons ) ;
-1032
-1033 // Generate buttons from map and append it to button container
-1034 var cancelMousedown = function ( e ) { Event.stop ( e ) ; return false } ;
-1035 var map = this.config.defaultToolbarButtonMap ;
-1036 for ( var i = 0 ; i < map.length ; i ++ ) {
-1037 for ( var j = 0 ; j < map [ i ] . length ; j ++ ) {
-1038 var buttonConfig = map [ i ] [ j ] ;
-1039
-1040 var li = this.doc.createElement ( 'li' ) ;
-1041 buttons.appendChild ( li ) ;
-1042 li.className = buttonConfig.className ;
-1043
-1044 var span = this.doc.createElement ( 'span' ) ;
-1045 li.appendChild ( span ) ;
-1046
-1047 var a = this.doc.createElement ( 'a' ) ;
-1048 span.appendChild ( a ) ;
-1049 a.href = '#' ;
-1050 a.title = buttonConfig.title ;
-1051 a.handler = buttonConfig.handler ;
-1052 a.xed = this ;
-1053 Event.observe ( a , 'mousedown' , cancelMousedown ) ;
-1054 Event.observe ( a , 'click' , function ( e ) {
-1055 var xed = this.xed ;
-1056
-1057 if ( $ ( this.parentNode ) . hasClassName ( 'disabled' ) || xed.toolbarContainer.hasClassName ( 'disabled' ) ) {
-1058 Event.stop ( e ) ;
-1059 return false ;
-1060 }
-1061
-1062 if ( xq.Browser.isTrident ) xed.focus ( ) ;
-1063
-1064 var handler = this.handler ;
-1065 var stop = ( typeof handler == "function" ) ? handler ( xed ) : eval ( handler ) ;
-1066 if ( stop ) {
-1067 Event.stop ( e ) ;
-1068 return false ;
-1069 } else {
-1070 return true ;
-1071 }
-1072 } . bind ( a ) ) ;
-1073
-1074 var img = this.doc.createElement ( 'img' ) ;
-1075 a.appendChild ( img ) ;
-1076 img.src = this.config.imagePathForDefaultToobar + buttonConfig.className + '.gif' ;
-1077
-1078 if ( j == 0 && i != 0 ) li.className + = ' xq_separator' ;
-1079 }
-1080 }
-1081
-1082 return container ;
-1083 } ,
-1084
-1085
-1086
-1087 /////////////////////////////////////////////
-1088 // Event Management
-1089
-1090 _registerEventHandlers : function ( ) {
-1091 var events = [ 'keydown' , 'click' , 'keyup' , 'mouseup' , 'contextmenu' , 'scroll' ] ;
-1092
-1093 if ( xq.Browser.isTrident && this.config.changeCursorOnLink ) events.push ( 'mousemove' ) ;
-1094 if ( xq.Browser.isMac && xq.Browser.isGecko ) events.push ( 'keypress' ) ;
-1095
-1096 for ( var i = 0 ; i < events.length ; i ++ ) {
-1097 Event.observe ( this.getDoc ( ) , events [ i ] , this._handleEvent.bindAsEventListener ( this ) ) ;
-1098 }
-1099 } ,
-1100
-1101 _handleEvent : function ( e ) {
-1102 this._fireOnBeforeEvent ( this , e ) ;
-1103
-1104 var stop = false ;
-1105
-1106 var modifiedByCorrection = false ;
-1107
-1108 if ( e.type == 'mousemove' && this.config.changeCursorOnLink ) {
-1109 // Trident only
-1110 var link = ! ! this.rdom.getParentElementOf ( e.srcElement , [ "A" ] ) ;
-1111 if ( this.editorBody.contentEditable != link && ! this.rdom.hasSelection ( ) ) this.editorBody.contentEditable = ! link ;
-1112 } else if ( e.type == 'click' && e.button == 0 && this.config.enableLinkClick ) {
-1113 var a = this.rdom.getParentElementOf ( e.target || e.srcElement , [ "A" ] ) ;
-1114 if ( a ) stop = this.handleClick ( e , a ) ;
-1115 } else if ( e.type == ( xq.Browser.isMac && xq.Browser.isGecko ? "keypress" : "keydown" ) ) {
-1116 var undoPerformed = false ;
-1117
-1118 modifiedByCorrection = this.rdom.correctParagraph ( ) ;
-1119 for ( var key in this.config.shortcuts ) {
-1120 if ( ! this.config.shortcuts [ key ] . event.matches ( e ) ) continue ;
-1121
-1122 var handler = this.config.shortcuts [ key ] . handler ;
-1123 var xed = this ;
-1124 stop = ( typeof handler == "function" ) ? handler ( this ) : eval ( handler ) ;
-1125
-1126 if ( key == "undo" ) undoPerformed = true ;
-1127 }
-1128 } else if ( [ "mouseup" , "keyup" ] . include ( e.type ) ) {
-1129 modifiedByCorrection = this.rdom.correctParagraph ( ) ;
-1130 } else if ( [ "contextmenu" ] . include ( e.type ) ) {
-1131 this._handleContextMenu ( e ) ;
-1132 }
-1133
-1134 if ( stop ) Event.stop ( e ) ;
-1135
-1136 this._fireOnCurrentContentChanged ( this ) ;
-1137 this._fireOnAfterEvent ( this , e ) ;
-1138
-1139 if ( ! undoPerformed && ! modifiedByCorrection ) this.editHistory.onEvent ( e ) ;
-1140
-1141 return ! stop ;
-1142 } ,
-1143
-1144 /**
-1145 * TODO: remove dup with handleAutocompletion
-1146 */
-1147 handleAutocorrection : function ( ) {
-1148 var block = this.rdom.getCurrentBlockElement ( ) ;
-1149
-1150 // TODO: use complete unescape algorithm
-1151 var text = this.rdom.getInnerText ( block ) . replace ( / /gi , " " ) ;
-1152
-1153 var acs = this.config.autocorrections ;
-1154 var performed = false ;
-1155
-1156 var stop = false ;
-1157 for ( var key in acs ) {
-1158 var ac = acs [ key ] ;
-1159 if ( ac.criteria ( text ) ) {
-1160 try {
-1161 this.editHistory.onCommand ( ) ;
-1162 this.editHistory.disable ( ) ;
-1163 if ( typeof ac.handler == "String" ) {
-1164 var xed = this ;
-1165 var rdom = this.rdom ;
-1166 eval ( ac.handler ) ;
-1167 } else {
-1168 stop = ac.handler ( this , this.rdom , block , text ) ;
-1169 }
-1170 this.editHistory.enable ( ) ;
-1171 } catch ( ignored ) { }
-1172
-1173 block = this.rdom.getCurrentBlockElement ( ) ;
-1174 text = this.rdom.getInnerText ( block ) ;
-1175
-1176 performed = true ;
-1177 if ( stop ) break ;
-1178 }
-1179 }
-1180
-1181 return stop ;
-1182 } ,
-1183
-1184 /**
-1185 * TODO: remove dup with handleAutocorrection
-1186 */
-1187 handleAutocompletion : function ( ) {
-1188 var acs = $H ( this.config.autocompletions ) ;
-1189 if ( acs.size ( ) == 0 ) return ;
-1190
-1191 if ( this.rdom.hasSelection ( ) ) {
-1192 var text = this.rdom.getSelectionAsText ( ) ;
-1193 this.rdom.deleteSelection ( ) ;
-1194 var wrapper = this.rdom.insertNode ( this.rdom.createElement ( "SPAN" ) ) ;
-1195 wrapper.innerHTML = text ;
-1196
-1197 var marker = this.rdom.pushMarker ( ) ;
-1198
-1199 var filtered =
-1200 acs.map ( function ( pair ) {
-1201 return [ pair.key , pair.value.criteria ( text ) ] ;
-1202 } . bind ( this ) ) . findAll ( function ( elem ) {
-1203 return elem [ 1 ] != - 1 ;
-1204 } ) . sortBy ( function ( elem ) {
-1205 return elem [ 1 ] ;
-1206 } ) ;
-1207
-1208 if ( filtered.length == 0 ) {
-1209 this.rdom.popMarker ( true ) ;
-1210 return ;
-1211 }
-1212 var ac = acs.get ( filtered [ 0 ] [ 0 ] ) ;
-1213
-1214 this.editHistory.disable ( ) ;
-1215 } else {
-1216 var marker = this.rdom.pushMarker ( ) ;
-1217
-1218 var filtered =
-1219 acs.map ( function ( pair ) {
-1220 return [ pair.key , this.rdom.testSmartWrap ( marker , pair.value.criteria ) . textIndex ] ;
-1221 } . bind ( this ) ) . findAll ( function ( elem ) {
-1222 return elem [ 1 ] != - 1 ;
-1223 } ) . sortBy ( function ( elem ) {
-1224 return elem [ 1 ] ;
-1225 } ) ;
-1226
-1227 if ( filtered.length == 0 ) {
-1228 this.rdom.popMarker ( true ) ;
-1229 return ;
-1230 }
-1231
-1232 var ac = acs.get ( filtered [ 0 ] [ 0 ] ) ;
-1233
-1234 this.editHistory.disable ( ) ;
-1235
-1236 var wrapper = this.rdom.smartWrap ( marker , "SPAN" , ac.criteria ) ;
-1237 }
-1238
-1239 var block = this.rdom.getCurrentBlockElement ( ) ;
-1240
-1241 // TODO: use complete unescape algorithm
-1242 var text = this.rdom.getInnerText ( wrapper ) . replace ( / /gi , " " ) ;
-1243
-1244 try {
-1245 // call handler
-1246 if ( typeof ac.handler == "String" ) {
-1247 var xed = this ;
-1248 var rdom = this.rdom ;
-1249 eval ( ac.handler ) ;
-1250 } else {
-1251 ac.handler ( this , this.rdom , block , wrapper , text ) ;
-1252 }
-1253 } catch ( ignored ) { }
-1254
-1255 try {
-1256 this.rdom.unwrapElement ( wrapper ) ;
-1257 } catch ( ignored ) { }
-1258
-1259
-1260 if ( this.rdom.isEmptyBlock ( block ) ) this.rdom.correctEmptyElement ( block ) ;
-1261
-1262 this.editHistory.enable ( ) ;
-1263 this.editHistory.onCommand ( ) ;
-1264
-1265 this.rdom.popMarker ( true ) ;
-1266 } ,
-1267
-1268 /**
-1269 * Handles click event
-1270 *
-1271 * @param {Event} e click event
-1272 * @param {Element} target target element(usually has A tag)
-1273 */
-1274 handleClick : function ( e , target ) {
-1275 var href = decodeURI ( target.href ) ;
-1276 if ( ! xq.Browser.isTrident ) {
-1277 if ( ! e.ctrlKey && ! e.shiftKey && e.button != 1 ) {
-1278 window.location.href = href ;
-1279 return true ;
-1280 }
-1281 } else {
-1282 if ( e.shiftKey ) {
-1283 window.open ( href , "_blank" ) ;
-1284 } else {
-1285 window.location.href = href ;
-1286 }
-1287 return true ;
-1288 }
-1289
-1290 return false ;
-1291 } ,
-1292
-1293 /**
-1294 * Show link dialog
-1295 *
-1296 * TODO: should support modify/unlink
-1297 */
-1298 handleLink : function ( ) {
-1299 var text = this.rdom.getSelectionAsText ( ) || '' ;
-1300 var dialog = new xq.controls.FormDialog (
-1301 this ,
-1302 xq.ui_templates.basicLinkDialog ,
-1303 function ( dialog ) {
-1304 if ( text ) {
-1305 dialog.form.text.value = text ;
-1306 dialog.form.url.focus ( ) ;
-1307 dialog.form.url.select ( ) ;
-1308 }
-1309 } ,
-1310 function ( data ) {
-1311 this.focus ( ) ;
-1312
-1313 if ( xq.Browser.isTrident ) {
-1314 var rng = this.rdom.rng ( ) ;
-1315 rng.moveToBookmark ( bm ) ;
-1316 rng.select ( ) ;
-1317 }
-1318
-1319 if ( ! data ) return ;
-1320 this.handleInsertLink ( false , data.url , data.text , data.text ) ;
-1321 } . bind ( this )
-1322 ) ;
-1323
-1324 if ( xq.Browser.isTrident ) var bm = this.rdom.rng ( ) . getBookmark ( ) ;
-1325
-1326 dialog.show ( { position : 'centerOfEditor' } ) ;
-1327
-1328 return true ;
-1329 } ,
-1330
-1331 /**
-1332 * Inserts link or apply link into selected area
-1333 *
-1334 * @param {boolean} autoSelection if set true and there's no selection, automatically select word to link(if possible)
-1335 * @param {String} url url
-1336 * @param {String} title title of link
-1337 * @param {String} text text of link. If there's a selection(manually or automatically), it will be replaced with this text
-1338 *
-1339 * @returns {Element} created element
-1340 */
-1341 handleInsertLink : function ( autoSelection , url , title , text ) {
-1342 if ( autoSelection && ! this.rdom.hasSelection ( ) ) {
-1343 var marker = this.rdom.pushMarker ( ) ;
-1344 var a = this.rdom.smartWrap ( marker , "A" , function ( text ) {
-1345 var index = text.lastIndexOf ( " " ) ;
-1346 return index == - 1 ? index : index + 1 ;
-1347 } ) ;
-1348 a.href = url ;
-1349 a.title = title ;
-1350 if ( text ) {
-1351 a.innerHTML = ""
-1352 a.appendChild ( this.rdom.createTextNode ( text ) ) ;
-1353 } else if ( ! a.hasChildNodes ( ) ) {
-1354 this.rdom.deleteNode ( a ) ;
-1355 }
-1356 this.rdom.popMarker ( true ) ;
-1357 } else {
-1358 text = text || ( this.rdom.hasSelection ( ) ? this.rdom.getSelectionAsText ( ) : null ) ;
-1359 if ( ! text ) return ;
-1360
-1361 this.rdom.deleteSelection ( ) ;
-1362
-1363 var a = this.rdom.createElement ( 'A' ) ;
-1364 a.href = url ;
-1365 a.title = title ;
-1366 a.appendChild ( this.rdom.createTextNode ( text ) ) ;
-1367 this.rdom.insertNode ( a ) ;
-1368 }
-1369
-1370 var historyAdded = this.editHistory.onCommand ( ) ;
-1371 this._fireOnCurrentContentChanged ( this ) ;
-1372
-1373 return true ;
-1374 } ,
-1375
-1376 /**
-1377 * Called when enter key pressed.
-1378 *
-1379 * @param {boolean} skipAutocorrection if set true, skips autocorrection
-1380 * @param {boolean} forceInsertParagraph if set true, inserts paragraph
-1381 */
-1382 handleEnter : function ( skipAutocorrection , forceInsertParagraph ) {
-1383 // If it has selection, perform default action.
-1384 if ( this.rdom.hasSelection ( ) ) return false ;
-1385
-1386 // Perform autocorrection
-1387 if ( ! skipAutocorrection && this.handleAutocorrection ( ) ) return true ;
-1388
-1389 var atEmptyBlock = this.rdom.isCaretAtEmptyBlock ( ) ;
-1390 var atStart = atEmptyBlock || this.rdom.isCaretAtBlockStart ( ) ;
-1391 var atEnd = atEmptyBlock || ( ! atStart && this.rdom.isCaretAtBlockEnd ( ) ) ;
-1392 var atEdge = atEmptyBlock || atStart || atEnd ;
-1393
-1394 if ( ! atEdge ) {
-1395 var block = this.rdom.getCurrentBlockElement ( ) ;
-1396 var marker = this.rdom.pushMarker ( ) ;
-1397
-1398 if ( this.rdom.isFirstLiWithNestedList ( block ) && ! forceInsertParagraph ) {
-1399 var parent = block.parentNode ;
-1400 this.rdom.unwrapElement ( block ) ;
-1401 block = parent ;
-1402 } else if ( block.nodeName != "LI" && this.rdom.tree.isBlockContainer ( block ) ) {
-1403 block = this.rdom.wrapAllInlineOrTextNodesAs ( "P" , block , true ) . first ( ) ;
-1404 }
-1405 this.rdom.splitElementUpto ( marker , block ) ;
-1406
-1407 this.rdom.popMarker ( true ) ;
-1408 } else if ( atEmptyBlock ) {
-1409 this._handleEnterAtEmptyBlock ( ) ;
-1410 } else {
-1411 this._handleEnterAtEdge ( atStart , forceInsertParagraph ) ;
-1412 }
-1413
-1414 return true ;
-1415 } ,
-1416
-1417 /**
-1418 * Moves current block upward or downward
-1419 *
-1420 * @param {boolean} up moves current block upward
-1421 */
-1422 handleMoveBlock : function ( up ) {
-1423 var block = this.rdom.moveBlock ( this.rdom.getCurrentBlockElement ( ) , up ) ;
-1424 if ( block ) {
-1425 this.rdom.selectElement ( block , false ) ;
-1426 block.scrollIntoView ( false ) ;
-1427
-1428 var historyAdded = this.editHistory.onCommand ( ) ;
-1429 this._fireOnCurrentContentChanged ( this ) ;
-1430 }
-1431 return true ;
-1432 } ,
-1433
-1434 /**
-1435 * Called when tab key pressed
-1436 */
-1437 handleTab : function ( ) {
-1438 var hasSelection = this.rdom.hasSelection ( ) ;
-1439 var table = this.rdom.getParentElementOf ( this.rdom.getCurrentBlockElement ( ) , [ "TABLE" ] ) ;
-1440
-1441 if ( hasSelection ) {
-1442 this.handleIndent ( ) ;
-1443 } else if ( table && table.className == "datatable" ) {
-1444 this.handleMoveToNextCell ( ) ;
-1445 } else if ( this.rdom.isCaretAtBlockStart ( ) ) {
-1446 this.handleIndent ( ) ;
-1447 } else {
-1448 this.handleInsertTab ( ) ;
-1449 }
-1450
-1451 return true ;
-1452 } ,
-1453
-1454 /**
-1455 * Called when shift+tab key pressed
-1456 */
-1457 handleShiftTab : function ( ) {
-1458 var hasSelection = this.rdom.hasSelection ( ) ;
-1459 var table = this.rdom.getParentElementOf ( this.rdom.getCurrentBlockElement ( ) , [ "TABLE" ] ) ;
-1460
-1461 if ( hasSelection ) {
-1462 this.handleOutdent ( ) ;
-1463 } else if ( table && table.className == "datatable" ) {
-1464 this.handleMoveToPreviousCell ( ) ;
-1465 } else {
-1466 this.handleOutdent ( ) ;
-1467 }
-1468
-1469 return true ;
-1470 } ,
-1471
-1472 /**
-1473 * Inserts three non-breaking spaces
-1474 */
-1475 handleInsertTab : function ( ) {
-1476 this.rdom.insertHtml ( ' ' ) ;
-1477 this.rdom.insertHtml ( ' ' ) ;
-1478 this.rdom.insertHtml ( ' ' ) ;
-1479
-1480 return true ;
-1481 } ,
-1482
-1483 /**
-1484 * Called when delete key pressed
-1485 */
-1486 handleDelete : function ( ) {
-1487 if ( this.rdom.hasSelection ( ) || ! this.rdom.isCaretAtBlockEnd ( ) ) return false ;
-1488 return this._handleMerge ( true ) ;
-1489 } ,
-1490
-1491 /**
-1492 * Called when backspace key pressed
-1493 */
-1494 handleBackspace : function ( ) {
-1495 if ( this.rdom.hasSelection ( ) || ! this.rdom.isCaretAtBlockStart ( ) ) return false ;
-1496 return this._handleMerge ( false ) ;
-1497 } ,
-1498
-1499 _handleMerge : function ( withNext ) {
-1500 var block = this.rdom.getCurrentBlockElement ( ) ;
-1501
-1502 // save caret position;
-1503 var marker = this.rdom.pushMarker ( ) ;
-1504
-1505 // perform merge
-1506 var merged = this.rdom.mergeElement ( block , withNext , withNext ) ;
-1507 if ( ! merged && ! withNext ) this.rdom.extractOutElementFromParent ( block ) ;
-1508
-1509 // restore caret position
-1510 this.rdom.popMarker ( true ) ;
-1511 if ( merged ) this.rdom.correctEmptyElement ( merged ) ;
-1512
-1513 var historyAdded = this.editHistory.onCommand ( ) ;
-1514 this._fireOnCurrentContentChanged ( this ) ;
-1515
-1516 return ! ! merged ;
-1517 } ,
-1518
-1519 /**
-1520 * (in table) Moves caret to the next cell
-1521 */
-1522 handleMoveToNextCell : function ( ) {
-1523 this._handleMoveToCell ( "next" ) ;
-1524 } ,
-1525
-1526 /**
-1527 * (in table) Moves caret to the previous cell
-1528 */
-1529 handleMoveToPreviousCell : function ( ) {
-1530 this._handleMoveToCell ( "prev" ) ;
-1531 } ,
-1532
-1533 /**
-1534 * (in table) Moves caret to the above cell
-1535 */
-1536 handleMoveToAboveCell : function ( ) {
-1537 this._handleMoveToCell ( "above" ) ;
-1538 } ,
-1539
-1540 /**
-1541 * (in table) Moves caret to the below cell
-1542 */
-1543 handleMoveToBelowCell : function ( ) {
-1544 this._handleMoveToCell ( "below" ) ;
-1545 } ,
-1546
-1547 _handleMoveToCell : function ( dir ) {
-1548 var block = this.rdom.getCurrentBlockElement ( ) ;
-1549 var cell = this.rdom.getParentElementOf ( block , [ "TD" , "TH" ] ) ;
-1550 var table = this.rdom.getParentElementOf ( cell , [ "TABLE" ] ) ;
-1551 var rtable = new xq.RichTable ( this.rdom , table ) ;
-1552 var target = null ;
-1553
-1554 if ( [ "next" , "prev" ] . include ( dir ) ) {
-1555 var toNext = dir == "next" ;
-1556 target = toNext ? rtable.getNextCellOf ( cell ) : rtable.getPreviousCellOf ( cell ) ;
-1557 } else {
-1558 var toBelow = dir == "below" ;
-1559 target = toBelow ? rtable.getBelowCellOf ( cell ) : rtable.getAboveCellOf ( cell ) ;
-1560 }
-1561
-1562 if ( ! target ) {
-1563 var finder = function ( node ) { return ! [ 'TD' , 'TH' ] . include ( node.nodeName ) && this.tree.isBlock ( node ) && ! this.tree.hasBlocks ( node ) ; } . bind ( this.rdom ) ;
-1564 var exitCondition = function ( node ) { return this.tree.isBlock ( node ) && ! this.tree.isDescendantOf ( this.getRoot ( ) , node ) } . bind ( this.rdom ) ;
-1565
-1566 target = ( toNext || toBelow ) ?
-1567 this.rdom.tree.findForward ( cell , finder , exitCondition ) :
-1568 this.rdom.tree.findBackward ( table , finder , exitCondition ) ;
-1569 }
-1570
-1571 if ( target ) this.rdom.placeCaretAtStartOf ( target ) ;
-1572 } ,
-1573
-1574 /**
-1575 * Applies STRONG tag
-1576 */
-1577 handleStrongEmphasis : function ( ) {
-1578 this.rdom.applyStrongEmphasis ( ) ;
-1579
-1580 var historyAdded = this.editHistory.onCommand ( ) ;
-1581 this._fireOnCurrentContentChanged ( this ) ;
-1582
-1583 return true ;
-1584 } ,
-1585
-1586 /**
-1587 * Applies EM tag
-1588 */
-1589 handleEmphasis : function ( ) {
-1590 this.rdom.applyEmphasis ( ) ;
-1591
-1592 var historyAdded = this.editHistory.onCommand ( ) ;
-1593 this._fireOnCurrentContentChanged ( this ) ;
-1594
-1595 return true ;
-1596 } ,
-1597
-1598 /**
-1599 * Applies EM.underline tag
-1600 */
-1601 handleUnderline : function ( ) {
-1602 this.rdom.applyUnderline ( ) ;
-1603
-1604 var historyAdded = this.editHistory.onCommand ( ) ;
-1605 this._fireOnCurrentContentChanged ( this ) ;
-1606
-1607 return true ;
-1608 } ,
-1609
-1610 /**
-1611 * Applies SPAN.strike tag
-1612 */
-1613 handleStrike : function ( ) {
-1614 this.rdom.applyStrike ( ) ;
-1615
-1616 var historyAdded = this.editHistory.onCommand ( ) ;
-1617 this._fireOnCurrentContentChanged ( this ) ;
-1618
-1619 return true ;
-1620 } ,
-1621
-1622 /**
-1623 * Removes all style
-1624 */
-1625 handleRemoveFormat : function ( ) {
-1626 this.rdom.applyRemoveFormat ( ) ;
-1627
-1628 var historyAdded = this.editHistory.onCommand ( ) ;
-1629 this._fireOnCurrentContentChanged ( this ) ;
-1630
-1631 return true ;
-1632 } ,
-1633
-1634 /**
-1635 * Inserts table
-1636 *
-1637 * @param {Number} cols number of columns
-1638 * @param {Number} rows number of rows
-1639 * @param {String} headerPosition position of THs. "T" or "L" or "TL". "T" means top, "L" means left.
-1640 */
-1641 handleTable : function ( cols , rows , headerPositions ) {
-1642 var cur = this.rdom.getCurrentBlockElement ( ) ;
-1643 if ( this.rdom.getParentElementOf ( cur , [ "TABLE" ] ) ) return true ;
-1644
-1645 var rtable = xq.RichTable.create ( this.rdom , cols , rows , headerPositions ) ;
-1646 if ( this.rdom.tree.isBlockContainer ( cur ) ) {
-1647 var wrappers = this.rdom.wrapAllInlineOrTextNodesAs ( "P" , cur , true ) ;
-1648 cur = wrappers.last ( ) ;
-1649 }
-1650 var tableDom = this.rdom.insertNodeAt ( rtable.getDom ( ) , cur , "after" ) ;
-1651 this.rdom.placeCaretAtStartOf ( rtable.getCellAt ( 0 , 0 ) ) ;
-1652
-1653 if ( this.rdom.isEmptyBlock ( cur ) ) this.rdom.deleteNode ( cur , true ) ;
-1654
-1655 var historyAdded = this.editHistory.onCommand ( ) ;
-1656 this._fireOnCurrentContentChanged ( this ) ;
-1657
-1658 return true ;
-1659 } ,
-1660
-1661 handleInsertNewRowAt : function ( where ) {
-1662 var cur = this.rdom.getCurrentBlockElement ( ) ;
-1663 var tr = this.rdom.getParentElementOf ( cur , [ "TR" ] ) ;
-1664 if ( ! tr ) return true ;
-1665
-1666 var table = this.rdom.getParentElementOf ( tr , [ "TABLE" ] ) ;
-1667 var rtable = new xq.RichTable ( this.rdom , table ) ;
-1668 var row = rtable.insertNewRowAt ( tr , where ) ;
-1669
-1670 this.rdom.placeCaretAtStartOf ( row.cells [ 0 ] ) ;
-1671 return true ;
-1672 } ,
-1673 handleInsertNewColumnAt : function ( where ) {
-1674 var cur = this.rdom.getCurrentBlockElement ( ) ;
-1675 var td = this.rdom.getParentElementOf ( cur , [ "TD" ] , true ) ;
-1676 if ( ! td ) return true ;
-1677
-1678 var table = this.rdom.getParentElementOf ( td , [ "TABLE" ] ) ;
-1679 var rtable = new xq.RichTable ( this.rdom , table ) ;
-1680 rtable.insertNewCellAt ( td , where ) ;
-1681
-1682 this.rdom.placeCaretAtStartOf ( cur ) ;
-1683 return true ;
-1684 } ,
-1685
-1686 handleDeleteRow : function ( ) {
-1687 var cur = this.rdom.getCurrentBlockElement ( ) ;
-1688 var tr = this.rdom.getParentElementOf ( cur , [ "TR" ] ) ;
-1689 if ( ! tr ) return true ;
-1690
-1691 var table = this.rdom.getParentElementOf ( tr , [ "TABLE" ] ) ;
-1692 var rtable = new xq.RichTable ( this.rdom , table ) ;
-1693 var blockToMove = rtable.deleteRow ( tr ) ;
-1694
-1695 this.rdom.placeCaretAtStartOf ( blockToMove ) ;
-1696 return true ;
-1697 } ,
-1698
-1699 handleDeleteColumn : function ( ) {
-1700 var cur = this.rdom.getCurrentBlockElement ( ) ;
-1701 var td = this.rdom.getParentElementOf ( cur , [ "TD" ] , true ) ;
-1702 if ( ! td ) return true ;
-1703
-1704 var table = this.rdom.getParentElementOf ( td , [ "TABLE" ] ) ;
-1705 var rtable = new xq.RichTable ( this.rdom , table ) ;
-1706 rtable.deleteCell ( td ) ;
-1707
-1708 return true ;
-1709 } ,
-1710
-1711 /**
-1712 * Performs block indentation
-1713 */
-1714 handleIndent : function ( ) {
-1715 if ( this.rdom.hasSelection ( ) ) {
-1716 var blocks = this.rdom.getBlockElementsAtSelectionEdge ( true , true ) ;
-1717 if ( blocks.first ( ) != blocks.last ( ) ) {
-1718 var affected = this.rdom.indentElements ( blocks.first ( ) , blocks.last ( ) ) ;
-1719 this.rdom.selectBlocksBetween ( affected.first ( ) , affected.last ( ) ) ;
-1720
-1721 var historyAdded = this.editHistory.onCommand ( ) ;
-1722 this._fireOnCurrentContentChanged ( this ) ;
-1723
-1724 return true ;
-1725 }
-1726 }
-1727
-1728 var block = this.rdom.getCurrentBlockElement ( ) ;
-1729 var affected = this.rdom.indentElement ( block ) ;
-1730
-1731 if ( affected ) {
-1732 this.rdom.placeCaretAtStartOf ( affected ) ;
-1733
-1734 var historyAdded = this.editHistory.onCommand ( ) ;
-1735 this._fireOnCurrentContentChanged ( this ) ;
-1736 }
-1737
-1738 return true ;
-1739 } ,
-1740
-1741 /**
-1742 * Performs block outdentation
-1743 */
-1744 handleOutdent : function ( ) {
-1745 if ( this.rdom.hasSelection ( ) ) {
-1746 var blocks = this.rdom.getBlockElementsAtSelectionEdge ( true , true ) ;
-1747 if ( blocks.first ( ) != blocks.last ( ) ) {
-1748 var affected = this.rdom.outdentElements ( blocks.first ( ) , blocks.last ( ) ) ;
-1749 this.rdom.selectBlocksBetween ( affected.first ( ) , affected.last ( ) ) ;
-1750
-1751 var historyAdded = this.editHistory.onCommand ( ) ;
-1752 this._fireOnCurrentContentChanged ( this ) ;
-1753
-1754 return true ;
-1755 }
-1756 }
-1757
-1758 var block = this.rdom.getCurrentBlockElement ( ) ;
-1759 var affected = this.rdom.outdentElement ( block ) ;
-1760
-1761 if ( affected ) {
-1762 this.rdom.placeCaretAtStartOf ( affected ) ;
-1763
-1764 var historyAdded = this.editHistory.onCommand ( ) ;
-1765 this._fireOnCurrentContentChanged ( this ) ;
-1766 }
-1767
-1768 return true ;
-1769 } ,
-1770
-1771 /**
-1772 * Applies list.
-1773 *
-1774 * @param {String} type "UL" or "OL" or "CODE". CODE generates OL.code
-1775 */
-1776 handleList : function ( type ) {
-1777 if ( this.rdom.hasSelection ( ) ) {
-1778 var blocks = this.rdom.getBlockElementsAtSelectionEdge ( true , true ) ;
-1779 if ( blocks.first ( ) != blocks.last ( ) ) {
-1780 blocks = this.rdom.applyLists ( blocks.first ( ) , blocks.last ( ) , type ) ;
-1781 } else {
-1782 blocks [ 0 ] = blocks [ 1 ] = this.rdom.applyList ( blocks.first ( ) , type ) ;
-1783 }
-1784 this.rdom.selectBlocksBetween ( blocks.first ( ) , blocks.last ( ) ) ;
-1785 } else {
-1786 var block = this.rdom.applyList ( this.rdom.getCurrentBlockElement ( ) , type ) ;
-1787 this.rdom.placeCaretAtStartOf ( block ) ;
-1788 }
-1789 var historyAdded = this.editHistory.onCommand ( ) ;
-1790 this._fireOnCurrentContentChanged ( this ) ;
-1791
-1792 return true ;
-1793 } ,
-1794
-1795 /**
-1796 * Applies justification
-1797 *
-1798 * @param {String} dir "left", "center", "right" or "both"
-1799 */
-1800 handleJustify : function ( dir ) {
-1801 var block = this.rdom.getCurrentBlockElement ( ) ;
-1802 var dir = ( dir == "left" || dir == "both" ) && ( block.style.textAlign == "left" || block.style.textAlign == "" ) ? "both" : dir ;
-1803
-1804 if ( this.rdom.hasSelection ( ) ) {
-1805 var blocks = this.rdom.getSelectedBlockElements ( ) ;
-1806 this.rdom.justifyBlocks ( blocks , dir ) ;
-1807 this.rdom.selectBlocksBetween ( blocks.first ( ) , blocks.last ( ) ) ;
-1808 } else {
-1809 this.rdom.justifyBlock ( block , dir ) ;
-1810 }
-1811 var historyAdded = this.editHistory.onCommand ( ) ;
-1812 this._fireOnCurrentContentChanged ( this ) ;
-1813
-1814 return true ;
-1815 } ,
-1816
-1817 /**
-1818 * Removes current block element
-1819 */
-1820 handleRemoveBlock : function ( ) {
-1821 var block = this.rdom.getCurrentBlockElement ( ) ;
-1822 var blockToMove = this.rdom.removeBlock ( block ) ;
-1823 this.rdom.placeCaretAtStartOf ( blockToMove ) ;
-1824 blockToMove.scrollIntoView ( false ) ;
-1825 } ,
-1826
-1827 /**
-1828 * Applies background color
-1829 *
-1830 * @param {String} color CSS color string
-1831 */
-1832 handleBackgroundColor : function ( color ) {
-1833 if ( color ) {
-1834 this.rdom.applyBackgroundColor ( color ) ;
-1835
-1836 var historyAdded = this.editHistory.onCommand ( ) ;
-1837 this._fireOnCurrentContentChanged ( this ) ;
-1838 } else {
-1839 var dialog = new xq.controls.FormDialog (
-1840 this ,
-1841 xq.ui_templates.basicColorPickerDialog ,
-1842 function ( dialog ) { } ,
-1843 function ( data ) {
-1844 this.focus ( ) ;
-1845
-1846 if ( xq.Browser.isTrident ) {
-1847 var rng = this.rdom.rng ( ) ;
-1848 rng.moveToBookmark ( bm ) ;
-1849 rng.select ( ) ;
-1850 }
-1851
-1852 if ( ! data ) return ;
-1853
-1854 this.handleBackgroundColor ( data.color ) ;
-1855 } . bind ( this )
-1856 ) ;
-1857
-1858 if ( xq.Browser.isTrident ) var bm = this.rdom.rng ( ) . getBookmark ( ) ;
-1859
-1860 dialog.show ( { position : 'centerOfEditor' } ) ;
-1861 }
-1862 return true ;
-1863 } ,
-1864
-1865 /**
-1866 * Applies foreground color
-1867 *
-1868 * @param {String} color CSS color string
-1869 */
-1870 handleForegroundColor : function ( color ) {
-1871 if ( color ) {
-1872 this.rdom.applyForegroundColor ( color ) ;
-1873
-1874 var historyAdded = this.editHistory.onCommand ( ) ;
-1875 this._fireOnCurrentContentChanged ( this ) ;
-1876 } else {
-1877 var dialog = new xq.controls.FormDialog (
-1878 this ,
-1879 xq.ui_templates.basicColorPickerDialog ,
-1880 function ( dialog ) { } ,
-1881 function ( data ) {
-1882 this.focus ( ) ;
-1883
-1884 if ( xq.Browser.isTrident ) {
-1885 var rng = this.rdom.rng ( ) ;
-1886 rng.moveToBookmark ( bm ) ;
-1887 rng.select ( ) ;
-1888 }
-1889
-1890 if ( ! data ) return ;
-1891
-1892 this.handleForegroundColor ( data.color ) ;
-1893 } . bind ( this )
-1894 ) ;
-1895
-1896 if ( xq.Browser.isTrident ) var bm = this.rdom.rng ( ) . getBookmark ( ) ;
-1897
-1898 dialog.show ( { position : 'centerOfEditor' } ) ;
-1899 }
-1900 return true ;
-1901 } ,
-1902
-1903 /**
-1904 * Applies superscription
-1905 */
-1906 handleSuperscription : function ( ) {
-1907 this.rdom.applySuperscription ( ) ;
-1908
-1909 var historyAdded = this.editHistory.onCommand ( ) ;
-1910 this._fireOnCurrentContentChanged ( this ) ;
-1911
-1912 return true ;
-1913 } ,
-1914
-1915 /**
-1916 * Applies subscription
-1917 */
-1918 handleSubscription : function ( ) {
-1919 this.rdom.applySubscription ( ) ;
-1920
-1921 var historyAdded = this.editHistory.onCommand ( ) ;
-1922 this._fireOnCurrentContentChanged ( this ) ;
-1923
-1924 return true ;
-1925 } ,
-1926
-1927 /**
-1928 * Change of wrap current block's tag
-1929 */
-1930 handleApplyBlock : function ( tagName ) {
-1931 if ( this.rdom.hasSelection ( ) ) {
-1932 var blocks = this.rdom.getBlockElementsAtSelectionEdge ( true , true ) ;
-1933 if ( blocks.first ( ) != blocks.last ( ) ) {
-1934 var applied = this.rdom.applyTagIntoElements ( tagName , blocks.first ( ) , blocks.last ( ) ) ;
-1935 this.rdom.selectBlocksBetween ( applied.first ( ) , applied.last ( ) ) ;
-1936
-1937 var historyAdded = this.editHistory.onCommand ( ) ;
-1938 this._fireOnCurrentContentChanged ( this ) ;
-1939
-1940 return true ;
-1941 }
-1942 }
-1943
-1944 var block = this.rdom.getCurrentBlockElement ( ) ;
-1945 this.rdom.pushMarker ( ) ;
-1946 var applied =
-1947 this.rdom.applyTagIntoElement ( tagName , block ) ||
-1948 block ;
-1949 this.rdom.popMarker ( true ) ;
-1950
-1951 if ( this.rdom.isEmptyBlock ( applied ) ) {
-1952 this.rdom.correctEmptyElement ( applied ) ;
-1953 this.rdom.placeCaretAtStartOf ( applied ) ;
-1954 }
-1955
-1956 var historyAdded = this.editHistory.onCommand ( ) ;
-1957 this._fireOnCurrentContentChanged ( this ) ;
-1958
-1959 return true ;
-1960 } ,
-1961
-1962 /**
-1963 * Inserts seperator (HR)
-1964 */
-1965 handleSeparator : function ( ) {
-1966 this.rdom.collapseSelection ( ) ;
-1967
-1968 var curBlock = this.rdom.getCurrentBlockElement ( ) ;
-1969 var atStart = this.rdom.isCaretAtBlockStart ( ) ;
-1970 if ( this.rdom.tree.isBlockContainer ( curBlock ) ) curBlock = this.rdom.wrapAllInlineOrTextNodesAs ( "P" , curBlock , true ) [ 0 ] ;
-1971
-1972 this.rdom.insertNodeAt ( this.rdom.createElement ( "HR" ) , curBlock , atStart ? "before" : "after" ) ;
-1973 this.rdom.placeCaretAtStartOf ( curBlock ) ;
-1974
-1975 // add undo history
-1976 var historyAdded = this.editHistory.onCommand ( ) ;
-1977 this._fireOnCurrentContentChanged ( this ) ;
-1978
-1979 return true ;
-1980 } ,
-1981
-1982 /**
-1983 * Performs UNDO
-1984 */
-1985 handleUndo : function ( ) {
-1986 var performed = this.editHistory.undo ( ) ;
-1987 this._fireOnCurrentContentChanged ( this ) ;
-1988
-1989 var curBlock = this.rdom.getCurrentBlockElement ( ) ;
-1990 if ( ! xq.Browser.isTrident && curBlock ) {
-1991 curBlock.scrollIntoView ( false ) ;
-1992 }
-1993 return true ;
-1994 } ,
-1995
-1996 /**
-1997 * Performs REDO
-1998 */
-1999 handleRedo : function ( ) {
-2000 var performed = this.editHistory.redo ( ) ;
-2001 this._fireOnCurrentContentChanged ( this ) ;
-2002
-2003 var curBlock = this.rdom.getCurrentBlockElement ( ) ;
-2004 if ( ! xq.Browser.isTrident && curBlock ) {
-2005 curBlock.scrollIntoView ( false ) ;
-2006 }
-2007 return true ;
-2008 } ,
-2009
-2010
-2011
-2012 _handleContextMenu : function ( e ) {
-2013 if ( xq.Browser.isWebkit ) {
-2014 if ( e.metaKey || Event.isLeftClick ( e ) ) return false ;
-2015 } else if ( e.shiftKey || e.ctrlKey || e.altKey ) {
-2016 return false ;
-2017 }
-2018
-2019 var x = Event.pointerX ( e ) ;
-2020 var y = Event.pointerY ( e ) ;
-2021 var pos = Position.cumulativeOffset ( this.getFrame ( ) ) ;
-2022 x + = pos [ 0 ] ;
-2023 y + = pos [ 1 ] ;
-2024 this._contextMenuTargetElement = e.target || e.srcElement ;
-2025
-2026 //TODO: Safari on Windows doesn't work with context key(app key)
-2027 if ( ! x || ! y || xq.Browser.isTrident ) {
-2028 var pos = Position.cumulativeOffset ( this._contextMenuTargetElement ) ;
-2029 var posFrame = Position.cumulativeOffset ( this.getFrame ( ) ) ;
-2030 x = pos [ 0 ] + posFrame [ 0 ] - this.getDoc ( ) . documentElement.scrollLeft ;
-2031 y = pos [ 1 ] + posFrame [ 1 ] - this.getDoc ( ) . documentElement.scrollTop ;
-2032 }
-2033
-2034 if ( ! xq.Browser.isTrident ) {
-2035 var doc = this.getDoc ( ) ;
-2036 var body = this.getBody ( ) ;
-2037
-2038 x - = doc.documentElement.scrollLeft ;
-2039 y - = doc.documentElement.scrollTop ;
-2040
-2041 if ( doc != body ) {
-2042 x - = body.scrollLeft ;
-2043 y - = body.scrollTop ;
-2044 }
-2045 }
-2046
-2047 for ( var cmh in this.config.contextMenuHandlers ) {
-2048 var stop = this.config.contextMenuHandlers [ cmh ] . handler ( this , this._contextMenuTargetElement , x , y ) ;
-2049 if ( stop ) {
-2050 Event.stop ( e ) ;
-2051 return true ;
-2052 }
-2053 }
-2054
-2055 return false ;
-2056 } ,
-2057
-2058 showContextMenu : function ( menuItems , x , y ) {
-2059 if ( ! menuItems || menuItems.length <= 0 ) return ;
-2060
-2061 if ( ! this._contextMenuContainer ) {
-2062 this._contextMenuContainer = this.doc.createElement ( 'UL' ) ;
-2063 this._contextMenuContainer.className = 'xqContextMenu' ;
-2064 this._contextMenuContainer.style.display = 'none' ;
-2065
-2066 Event.observe ( this.doc , 'click' , this._contextMenuClicked.bindAsEventListener ( this ) ) ;
-2067 Event.observe ( this.rdom.getDoc ( ) , 'click' , this.hideContextMenu.bindAsEventListener ( this ) ) ;
-2068
-2069 this.body.appendChild ( this._contextMenuContainer ) ;
-2070 } else {
-2071 while ( this._contextMenuContainer.childNodes.length > 0 )
-2072 this._contextMenuContainer.removeChild ( this._contextMenuContainer.childNodes [ 0 ] ) ;
-2073 }
-2074
-2075 for ( var i = 0 ; i < menuItems.length ; i ++ ) {
-2076 menuItems [ i ] . _node = this._addContextMenuItem ( menuItems [ i ] ) ;
-2077 }
-2078
-2079 this._contextMenuContainer.style.display = 'block' ;
-2080 this._contextMenuContainer.style.left = Math.min ( Math.max ( this.doc.body.scrollWidth , this.doc.documentElement.clientWidth ) - this._contextMenuContainer.offsetWidth , x ) + 'px' ;
-2081 this._contextMenuContainer.style.top = Math.min ( Math.max ( this.doc.body.scrollHeight , this.doc.documentElement.clientHeight ) - this._contextMenuContainer.offsetHeight , y ) + 'px' ;
-2082
-2083 this._contextMenuItems = menuItems ;
-2084 } ,
-2085
-2086 hideContextMenu : function ( ) {
-2087 if ( this._contextMenuContainer )
-2088 this._contextMenuContainer.style.display = 'none' ;
-2089 } ,
-2090
-2091 _addContextMenuItem : function ( item ) {
-2092 if ( ! this._contextMenuContainer ) throw "No conext menu container exists" ;
-2093
-2094 var node = this.doc.createElement ( 'LI' ) ;
-2095 if ( item.disabled ) node.className + = ' disabled' ;
-2096
-2097 if ( item.title == '----' ) {
-2098 node.innerHTML = ' ' ;
-2099 node.className = 'separator' ;
-2100 } else {
-2101 if ( item.handler ) {
-2102 node.innerHTML = '<a href="javascript:;" onclick="return false;">' + ( item.title.toString ( ) . escapeHTML ( ) ) + '</a>' ;
-2103 } else {
-2104 node.innerHTML = ( item.title.toString ( ) . escapeHTML ( ) ) ;
-2105 }
-2106 }
-2107
-2108 if ( item.className ) node.className = item.className ;
-2109
-2110 this._contextMenuContainer.appendChild ( node ) ;
-2111
-2112 return node ;
-2113 } ,
-2114
-2115 _contextMenuClicked : function ( e ) {
-2116 this.hideContextMenu ( ) ;
-2117
-2118 if ( ! this._contextMenuContainer ) return ;
-2119
-2120 var node = Event.findElement ( e , 'LI' ) ;
-2121 if ( ! node || ! this.rdom.tree.isDescendantOf ( this._contextMenuContainer , node ) ) return ;
-2122
-2123 for ( var i = 0 ; i < this._contextMenuItems.length ; i ++ ) {
-2124 if ( this._contextMenuItems [ i ] . _node == node ) {
-2125 var handler = this._contextMenuItems [ i ] . handler ;
-2126 if ( ! this._contextMenuItems [ i ] . disabled && handler ) {
-2127 var xed = this ;
-2128 var element = this._contextMenuTargetElement ;
-2129 if ( typeof handler == "function" ) {
-2130 handler ( xed , element ) ;
-2131 } else {
-2132 eval ( handler ) ;
-2133 }
-2134 }
-2135 break ;
-2136 }
-2137 }
-2138 } ,
-2139
-2140 /**
-2141 * Inserts HTML template
-2142 *
-2143 * @param {String} html Template string. It should have single root element
-2144 * @returns {Element} inserted element
-2145 */
-2146 insertTemplate : function ( html ) {
-2147 return this.rdom.insertHtml ( this._processTemplate ( html ) ) ;
-2148 } ,
-2149
-2150 /**
-2151 * Places given HTML template nearby target.
-2152 *
-2153 * @param {String} html Template string. It should have single root element
-2154 * @param {Node} target Target node.
-2155 * @param {String} where Possible values: "before", "start", "end", "after"
-2156 *
-2157 * @returns {Element} Inserted element.
-2158 */
-2159 insertTemplateAt : function ( html , target , where ) {
-2160 return this.rdom.insertHtmlAt ( this._processTemplate ( html ) , target , where ) ;
-2161 } ,
-2162
-2163 _processTemplate : function ( html ) {
-2164 // apply template processors
-2165 var tps = $H ( this.getTemplateProcessors ( ) ) . values ( ) ;
-2166 for ( var i = 0 ; i < tps.length ; i ++ ) {
-2167 html = tps [ i ] . handler ( html ) ;
-2168 }
-2169
-2170 // remove all whitespace characters between block tags
-2171 return html = this.removeUnnecessarySpaces ( html ) ;
-2172 } ,
-2173
-2174
-2175
-2176 /** @private */
-2177 _handleEnterAtEmptyBlock : function ( ) {
-2178 var block = this.rdom.getCurrentBlockElement ( ) ;
-2179 if ( this.rdom.tree.isTableCell ( block ) && this.rdom.isFirstBlockOfBody ( block ) ) {
-2180 block = this.rdom.insertNodeAt ( this.rdom.makeEmptyParagraph ( ) , this.rdom.getRoot ( ) , "start" ) ;
-2181 } else {
-2182 block =
-2183 this.rdom.outdentElement ( block ) ||
-2184 this.rdom.extractOutElementFromParent ( block ) ||
-2185 this.rdom.replaceTag ( "P" , block ) ||
-2186 this.rdom.insertNewBlockAround ( block ) ;
-2187 }
-2188
-2189 this.rdom.placeCaretAtStartOf ( block ) ;
-2190 if ( ! xq.Browser.isTrident ) block.scrollIntoView ( false ) ;
-2191 } ,
-2192
-2193 /** @private */
-2194 _handleEnterAtEdge : function ( atStart , forceInsertParagraph ) {
-2195 var block = this.rdom.getCurrentBlockElement ( ) ;
-2196 var blockToPlaceCaret ;
-2197
-2198 if ( atStart && this.rdom.isFirstBlockOfBody ( block ) ) {
-2199 blockToPlaceCaret = this.rdom.insertNodeAt ( this.rdom.makeEmptyParagraph ( ) , this.rdom.getRoot ( ) , "start" ) ;
-2200 } else {
-2201 if ( this.rdom.tree.isTableCell ( block ) ) forceInsertParagraph = true ;
-2202 var newBlock = this.rdom.insertNewBlockAround ( block , atStart , forceInsertParagraph ? "P" : null ) ;
-2203 blockToPlaceCaret = ! atStart ? newBlock : newBlock.nextSibling ;
-2204 }
-2205
-2206 this.rdom.placeCaretAtStartOf ( blockToPlaceCaret ) ;
-2207 if ( ! xq.Browser.isTrident ) blockToPlaceCaret.scrollIntoView ( false ) ;
-2208 }
-2209 } ) ;
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_06.html b/modules/editor/skins/xquared/doc/api/src_06.html
deleted file mode 100644
index 32b20a15b..000000000
--- a/modules/editor/skins/xquared/doc/api/src_06.html
+++ /dev/null
@@ -1,2262 +0,0 @@
- 1 /**
- 2 * Encapsulates browser incompatibility problem and provides rich set of DOM manipulation API.
- 3 *
- 4 * RichDom provides basic CRUD + Advanced DOM manipulation API, various query methods and caret/selection management API
- 5 */
- 6 xq.RichDom = Class.create ( {
- 7 /**
- 8 * Initialize RichDom. Target window and root element should be set after initialization. See setWin and setRoot.
- 9 *
- 10 * @constructor
- 11 */
- 12 initialize : function ( ) {
- 13 /**
- 14 * {xq.DomTree} instance of DomTree
- 15 */
- 16 this.tree = new xq.DomTree ( ) ;
- 17
- 18 this._lastMarkerId = 0 ;
- 19 } ,
- 20
- 21
- 22
- 23 /**
- 24 * @param {Window} win Browser's window object
- 25 */
- 26 setWin : function ( win ) {
- 27 if ( ! win ) throw "[win] is null" ;
- 28 this.win = win ;
- 29 } ,
- 30
- 31 /**
- 32 * @param {Element} root Root element
- 33 */
- 34 setRoot : function ( root ) {
- 35 if ( ! root ) throw "[root] is null" ;
- 36 if ( this.win && ( root.ownerDocument != this.win.document ) ) throw "root.ownerDocument != this.win.document" ;
- 37 this.root = root ;
- 38 this.doc = this.root.ownerDocument ;
- 39 } ,
- 40
- 41 /**
- 42 * @returns Browser's window object.
- 43 */
- 44 getWin : function ( ) { return this.win } ,
- 45
- 46 /**
- 47 * @returns Document object of root element.
- 48 */
- 49 getDoc : function ( ) { return this.doc } ,
- 50
- 51 /**
- 52 * @returns Root element.
- 53 */
- 54 getRoot : function ( ) { return this.root } ,
- 55
- 56
- 57
- 58 /////////////////////////////////////////////
- 59 // CRUDs
- 60
- 61 clearRoot : function ( ) {
- 62 this.root.innerHTML = "" ;
- 63 this.root.appendChild ( this.makeEmptyParagraph ( ) ) ;
- 64 } ,
- 65
- 66 /**
- 67 * Removes place holders and empty text nodes of given element.
- 68 *
- 69 * @param {Element} element target element
- 70 */
- 71 removePlaceHoldersAndEmptyNodes : function ( element ) {
- 72 var children = element.childNodes ;
- 73 if ( ! children ) return ;
- 74 var stopAt = this.getBottommostLastChild ( element ) ;
- 75 if ( ! stopAt ) return ;
- 76 stopAt = this.tree.walkForward ( stopAt ) ;
- 77
- 78 while ( true ) {
- 79 if ( ! element || element == stopAt ) break ;
- 80
- 81 if (
- 82 this.isPlaceHolder ( element ) ||
- 83 ( element.nodeType == 3 && element.nodeValue == "" ) ||
- 84 ( ! this.getNextSibling ( element ) && element.nodeType == 3 && element.nodeValue.strip ( ) == "" )
- 85 ) {
- 86 var deleteTarget = element ;
- 87 element = this.tree.walkForward ( element ) ;
- 88
- 89 this.deleteNode ( deleteTarget ) ;
- 90 } else {
- 91 element = this.tree.walkForward ( element ) ;
- 92 }
- 93 }
- 94 } ,
- 95
- 96 /**
- 97 * Sets multiple attributes into element at once
- 98 *
- 99 * @param {Element} element target element
-100 * @param {Object} map key-value pairs
-101 */
-102 setAttributes : function ( element , map ) {
-103 for ( key in map ) element.setAttribute ( key , map [ key ] ) ;
-104 } ,
-105
-106 /**
-107 * Creates textnode by given node value.
-108 *
-109 * @param {String} value value of textnode
-110 * @returns {Node} Created text node
-111 */
-112 createTextNode : function ( value ) { return this.doc.createTextNode ( value ) ; } ,
-113
-114 /**
-115 * Creates empty element by given tag name.
-116 *
-117 * @param {String} tagName name of tag
-118 * @returns {Element} Created element
-119 */
-120 createElement : function ( tagName ) { return this.doc.createElement ( tagName ) ; } ,
-121
-122 /**
-123 * Creates element from HTML string
-124 *
-125 * @param {String} html HTML string
-126 * @returns {Element} Created element
-127 */
-128 createElementFromHtml : function ( html ) {
-129 var node = this.createElement ( "div" ) ;
-130 node.innerHTML = html ;
-131 if ( node.childNodes.length != 1 ) {
-132 throw "Illegal HTML fragment" ;
-133 }
-134 return this.getFirstChild ( node ) ;
-135 } ,
-136
-137 /**
-138 * Deletes node from DOM tree.
-139 *
-140 * @param {Node} node Target node which should be deleted
-141 * @param {boolean} deleteEmptyParentsRecursively Recursively delete empty parent elements
-142 * @param {boolean} correctEmptyParent Call #correctEmptyElement on empty parent element after deletion
-143 */
-144 deleteNode : function ( node , deleteEmptyParentsRecursively , correctEmptyParent ) {
-145 if ( ! node || ! node.parentNode ) return ;
-146
-147 var parent = node.parentNode ;
-148 parent.removeChild ( node ) ;
-149
-150 if ( deleteEmptyParentsRecursively ) {
-151 while ( ! parent.hasChildNodes ( ) ) {
-152 node = parent ;
-153 parent = node.parentNode ;
-154 if ( ! parent || this.getRoot ( ) == node ) break ;
-155 parent.removeChild ( node ) ;
-156 }
-157 }
-158
-159 if ( correctEmptyParent && this.isEmptyBlock ( parent ) ) {
-160 parent.innerHTML = "" ;
-161 this.correctEmptyElement ( parent ) ;
-162 }
-163 } ,
-164
-165 /**
-166 * Inserts given node into current caret position
-167 *
-168 * @param {Node} node Target node
-169 * @returns {Node} Inserted node. It could be different with given node.
-170 */
-171 insertNode : function ( node ) { throw "Not implemented" } ,
-172
-173 /**
-174 * Inserts given html into current caret position
-175 *
-176 * @param {String} html HTML string
-177 * @returns {Node} Inserted node. It could be different with given node.
-178 */
-179 insertHtml : function ( html ) {
-180 return this.insertNode ( this.createElementFromHtml ( html ) ) ;
-181 } ,
-182
-183 /**
-184 * Creates textnode from given text and inserts it into current caret position
-185 *
-186 * @param {String} text Value of textnode
-187 * @returns {Node} Inserted node
-188 */
-189 insertText : function ( text ) {
-190 this.insertNode ( this.createTextNode ( text ) ) ;
-191 } ,
-192
-193 /**
-194 * Places given node nearby target.
-195 *
-196 * @param {Node} node Node to be inserted.
-197 * @param {Node} target Target node.
-198 * @param {String} where Possible values: "before", "start", "end", "after"
-199 * @param {boolean} performValidation Validate node if needed. For example when P placed into UL, its tag name automatically replaced with LI
-200 *
-201 * @returns {Node} Inserted node. It could be different with given node.
-202 */
-203 insertNodeAt : function ( node , target , where , performValidation ) {
-204 if (
-205 [ "HTML" , "HEAD" ] . include ( target.nodeName ) ||
-206 [ "BODY" ] . include ( target.nodeName ) && [ "before" , "after" ] . include ( where )
-207 ) throw "Illegal argument. Cannot move node[" + node.nodeName + "] to '" + where + "' of target[" + target.nodeName + "]"
-208
-209 var object ;
-210 var message ;
-211 var secondParam ;
-212
-213 switch ( where.toLowerCase ( ) ) {
-214 case "before" :
-215 object = target.parentNode ;
-216 message = 'insertBefore' ;
-217 secondParam = target ;
-218 break
-219 case "start" :
-220 if ( target.firstChild ) {
-221 object = target ;
-222 message = 'insertBefore' ;
-223 secondParam = target.firstChild ;
-224 } else {
-225 object = target ;
-226 message = 'appendChild' ;
-227 }
-228 break
-229 case "end" :
-230 object = target ;
-231 message = 'appendChild' ;
-232 break
-233 case "after" :
-234 if ( target.nextSibling ) {
-235 object = target.parentNode ;
-236 message = 'insertBefore' ;
-237 secondParam = target.nextSibling ;
-238 } else {
-239 object = target.parentNode ;
-240 message = 'appendChild' ;
-241 }
-242 break
-243 }
-244
-245 if ( performValidation && this.tree.isListContainer ( object ) && node.nodeName != "LI" ) {
-246 var li = this.createElement ( "LI" ) ;
-247 li.appendChild ( node ) ;
-248 node = li ;
-249 object [ message ] ( node , secondParam ) ;
-250 } else if ( performValidation && ! this.tree.isListContainer ( object ) && node.nodeName == "LI" ) {
-251 this.wrapAllInlineOrTextNodesAs ( "P" , node , true ) ;
-252 var div = this.createElement ( "DIV" ) ;
-253 this.moveChildNodes ( node , div ) ;
-254 this.deleteNode ( node ) ;
-255 object [ message ] ( div , secondParam ) ;
-256 node = this.unwrapElement ( div , true ) ;
-257 } else {
-258 object [ message ] ( node , secondParam ) ;
-259 }
-260
-261 return node ;
-262 } ,
-263
-264 /**
-265 * Creates textnode from given text and places given node nearby target.
-266 *
-267 * @param {String} text Text to be inserted.
-268 * @param {Node} target Target node.
-269 * @param {String} where Possible values: "before", "start", "end", "after"
-270 *
-271 * @returns {Node} Inserted node.
-272 */
-273 insertTextAt : function ( text , target , where ) {
-274 return this.insertNodeAt ( this.createTextNode ( text ) , target , where ) ;
-275 } ,
-276
-277 /**
-278 * Creates element from given HTML string and places given it nearby target.
-279 *
-280 * @param {String} html HTML to be inserted.
-281 * @param {Node} target Target node.
-282 * @param {String} where Possible values: "before", "start", "end", "after"
-283 *
-284 * @returns {Node} Inserted node.
-285 */
-286 insertHtmlAt : function ( html , target , where ) {
-287 return this.insertNodeAt ( this.createElementFromHtml ( html ) , target , where ) ;
-288 } ,
-289
-290 /**
-291 * Replaces element's tag by removing current element and creating new element by given tag name.
-292 *
-293 * @param {String} tag New tag name
-294 * @param {Element} element Target element
-295 *
-296 * @returns {Element} Replaced element
-297 */
-298 replaceTag : function ( tag , element ) {
-299 if ( element.nodeName == tag ) return null ;
-300 if ( this.tree.isTableCell ( element ) ) return null ;
-301
-302 var newElement = this.createElement ( tag ) ;
-303 this.moveChildNodes ( element , newElement ) ;
-304 this.copyAttributes ( element , newElement , true ) ;
-305 element.parentNode.replaceChild ( newElement , element ) ;
-306
-307 if ( ! newElement.hasChildNodes ( ) ) this.correctEmptyElement ( newElement ) ;
-308
-309 return newElement ;
-310 } ,
-311
-312 /**
-313 * Unwraps unnecessary paragraph.
-314 *
-315 * Unnecessary paragraph is P which is the only child of given container element.
-316 * For example, P which is contained by LI and is the only child is the unnecessary paragraph.
-317 * But if given container element is a block-only-container(BLOCKQUOTE, BODY), this method does nothing.
-318 *
-319 * @param {Element} element Container element
-320 * @returns {boolean} True if unwrap performed.
-321 */
-322 unwrapUnnecessaryParagraph : function ( element ) {
-323 if ( ! element ) return false ;
-324
-325 if ( ! this.tree.isBlockOnlyContainer ( element ) && element.childNodes.length == 1 && element.firstChild.nodeName == "P" && ! this.hasImportantAttributes ( element.firstChild ) ) {
-326 var p = element.firstChild ;
-327 this.moveChildNodes ( p , element ) ;
-328 this.deleteNode ( p ) ;
-329 return true ;
-330 }
-331 return false ;
-332 } ,
-333
-334 /**
-335 * Unwraps element by extracting all children out and removing the element.
-336 *
-337 * @param {Element} element Target element
-338 * @param {boolean} wrapInlineAndTextNodes Wrap all inline and text nodes with P before unwrap
-339 * @returns {Node} First child of unwrapped element
-340 */
-341 unwrapElement : function ( element , wrapInlineAndTextNodes ) {
-342 if ( wrapInlineAndTextNodes ) this.wrapAllInlineOrTextNodesAs ( "P" , element ) ;
-343
-344 var nodeToReturn = element.firstChild ;
-345
-346 while ( element.firstChild ) this.insertNodeAt ( element.firstChild , element , "before" ) ;
-347 this.deleteNode ( element ) ;
-348
-349 return nodeToReturn ;
-350 } ,
-351
-352 /**
-353 * Wraps element by given tag
-354 *
-355 * @param {String} tag tag name
-356 * @param {Element} element target element to wrap
-357 * @returns {Element} wrapper
-358 */
-359 wrapElement : function ( tag , element ) {
-360 var wrapper = this.insertNodeAt ( this.createElement ( tag ) , element , "before" ) ;
-361 wrapper.appendChild ( element ) ;
-362 return wrapper ;
-363 } ,
-364
-365 /**
-366 * Tests #smartWrap with given criteria but doesn't change anything
-367 */
-368 testSmartWrap : function ( endElement , criteria ) {
-369 return this.smartWrap ( endElement , null , criteria , true ) ;
-370 } ,
-371
-372 /**
-373 * Create inline element with given tag name and wraps nodes nearby endElement by given criteria
-374 *
-375 * @param {Element} endElement Boundary(end point, exclusive) of wrapper.
-376 * @param {String} tag Tag name of wrapper.
-377 * @param {Object} function which returns text index of start boundary.
-378 * @param {boolean} testOnly just test boundary and do not perform actual wrapping.
-379 *
-380 * @returns {Element} wrapper
-381 */
-382 smartWrap : function ( endElement , tag , criteria , testOnly ) {
-383 var block = this.getParentBlockElementOf ( endElement ) ;
-384
-385 tag = tag || "SPAN" ;
-386 criteria = criteria || function ( text ) { return - 1 } ;
-387
-388 // check for empty wrapper
-389 if ( ! testOnly && ( ! endElement.previousSibling || this.isEmptyBlock ( block ) ) ) {
-390 var wrapper = this.insertNodeAt ( this.createElement ( tag ) , endElement , "before" ) ;
-391 return wrapper ;
-392 }
-393
-394 // collect all textnodes
-395 var textNodes = this.tree.collectForward ( block , function ( node ) { return node == endElement } , function ( node ) { return node.nodeType == 3 } ) ;
-396
-397 // find textnode and break-point
-398 var nodeIndex = 0 ;
-399 var nodeValues = textNodes.pluck ( "nodeValue" ) ;
-400 var textToWrap = nodeValues.join ( "" ) ;
-401 var textIndex = criteria ( textToWrap )
-402 var breakPoint = textIndex ;
-403
-404 if ( breakPoint == - 1 ) {
-405 breakPoint = 0 ;
-406 } else {
-407 textToWrap = textToWrap.substring ( breakPoint ) ;
-408 }
-409
-410 for ( var i = 0 ; i < textNodes.length ; i ++ ) {
-411 if ( breakPoint > nodeValues [ i ] . length ) {
-412 breakPoint - = nodeValues [ i ] . length ;
-413 } else {
-414 nodeIndex = i ;
-415 break ;
-416 }
-417 }
-418
-419 if ( testOnly ) return { text : textToWrap , textIndex : textIndex , nodeIndex : nodeIndex , breakPoint : breakPoint } ;
-420
-421 // break textnode if necessary
-422 if ( breakPoint != 0 ) {
-423 var splitted = textNodes [ nodeIndex ] . splitText ( breakPoint ) ;
-424 nodeIndex ++ ;
-425 textNodes.splice ( nodeIndex , 0 , splitted ) ;
-426 }
-427 var startElement = textNodes [ nodeIndex ] || block.firstChild ;
-428
-429 // split inline elements up to parent block if necessary
-430 var family = this.tree.findCommonAncestorAndImmediateChildrenOf ( startElement , endElement ) ;
-431 var ca = family.parent ;
-432 if ( ca ) {
-433 if ( startElement.parentNode != ca ) startElement = this.splitElementUpto ( startElement , ca , true ) ;
-434 if ( endElement.parentNode != ca ) endElement = this.splitElementUpto ( endElement , ca , true ) ;
-435
-436 var prevStart = startElement.previousSibling ;
-437 var nextEnd = endElement.nextSibling ;
-438
-439 // remove empty inline elements
-440 if ( prevStart && prevStart.nodeType == 1 && this.isEmptyBlock ( prevStart ) ) this.deleteNode ( prevStart ) ;
-441 if ( nextEnd && nextEnd.nodeType == 1 && this.isEmptyBlock ( nextEnd ) ) this.deleteNode ( nextEnd ) ;
-442
-443 // wrap
-444 var wrapper = this.insertNodeAt ( this.createElement ( tag ) , startElement , "before" ) ;
-445 while ( wrapper.nextSibling != endElement ) wrapper.appendChild ( wrapper.nextSibling ) ;
-446 return wrapper ;
-447 } else {
-448 // wrap
-449 var wrapper = this.insertNodeAt ( this.createElement ( tag ) , endElement , "before" ) ;
-450 return wrapper ;
-451 }
-452 } ,
-453
-454 /**
-455 * Wraps all adjust inline elements and text nodes into block element.
-456 *
-457 * TODO: empty element should return empty array when it is not forced and (at least) single item array when forced
-458 *
-459 * @param {String} tag Tag name of wrapper
-460 * @param {Element} element Target element
-461 * @param {boolean} force Force wrapping. If it is set to false, this method do not makes unnecessary wrapper.
-462 *
-463 * @returns {Array} Array of wrappers. If nothing performed it returns empty array
-464 */
-465 wrapAllInlineOrTextNodesAs : function ( tag , element , force ) {
-466 var wrappers = [ ] ;
-467
-468 if ( ! force && ! this.tree.hasMixedContents ( element ) ) return wrappers ;
-469
-470 var node = element.firstChild ;
-471 while ( node ) {
-472 if ( this.tree.isTextOrInlineNode ( node ) ) {
-473 var wrapper = this.wrapInlineOrTextNodesAs ( tag , node ) ;
-474 wrappers.push ( wrapper ) ;
-475 node = wrapper.nextSibling ;
-476 } else {
-477 node = node.nextSibling ;
-478 }
-479 }
-480
-481 return wrappers ;
-482 } ,
-483
-484 /**
-485 * Wraps node and its adjust next siblings into an element
-486 */
-487 wrapInlineOrTextNodesAs : function ( tag , node ) {
-488 var wrapper = this.createElement ( tag ) ;
-489 var from = node ;
-490
-491 from.parentNode.replaceChild ( wrapper , from ) ;
-492 wrapper.appendChild ( from ) ;
-493
-494 // move nodes into wrapper
-495 while ( wrapper.nextSibling && this.tree.isTextOrInlineNode ( wrapper.nextSibling ) ) wrapper.appendChild ( wrapper.nextSibling ) ;
-496
-497 return wrapper ;
-498 } ,
-499
-500 /**
-501 * Turns block element into list item
-502 *
-503 * @param {Element} element Target element
-504 * @param {String} type One of "UL", "OL", "CODE". "CODE" is same with "OL" but it gives "OL" a class name "code"
-505 *
-506 * @return {Element} LI element
-507 */
-508 turnElementIntoListItem : function ( element , type ) {
-509 type = type.toUpperCase ( ) ;
-510
-511 var container = this.createElement ( type == "UL" ? "UL" : "OL" ) ;
-512 if ( type == "CODE" ) container.className = "code" ;
-513
-514 if ( this.tree.isTableCell ( element ) ) {
-515 var p = this.wrapAllInlineOrTextNodesAs ( "P" , element , true ) [ 0 ] ;
-516 container = this.insertNodeAt ( container , element , "start" ) ;
-517 var li = this.insertNodeAt ( this.createElement ( "LI" ) , container , "start" ) ;
-518 li.appendChild ( p ) ;
-519 } else {
-520 container = this.insertNodeAt ( container , element , "after" ) ;
-521 var li = this.insertNodeAt ( this.createElement ( "LI" ) , container , "start" ) ;
-522 li.appendChild ( element ) ;
-523 }
-524
-525 this.unwrapUnnecessaryParagraph ( li ) ;
-526 this.mergeAdjustLists ( container ) ;
-527
-528 return li ;
-529 } ,
-530
-531 /**
-532 * Extracts given element out from its parent element.
-533 *
-534 * @param {Element} element Target element
-535 */
-536 extractOutElementFromParent : function ( element ) {
-537 if ( element == this.root || this.root == element.parentNode || ! element.offsetParent ) return null ;
-538
-539 if ( element.nodeName == "LI" ) {
-540 this.wrapAllInlineOrTextNodesAs ( "P" , element , true ) ;
-541 element = element.firstChild ;
-542 }
-543
-544 var container = element.parentNode ;
-545 var nodeToReturn = null ;
-546
-547 if ( container.nodeName == "LI" && container.parentNode.parentNode.nodeName == "LI" ) {
-548 // nested list item
-549 if ( element.previousSibling ) {
-550 this.splitContainerOf ( element , true ) ;
-551 this.correctEmptyElement ( element ) ;
-552 }
-553
-554 this.outdentListItem ( element ) ;
-555 nodeToReturn = element ;
-556 } else if ( container.nodeName == "LI" ) {
-557 // not-nested list item
-558
-559 if ( this.tree.isListContainer ( element.nextSibling ) ) {
-560 // 1. split listContainer
-561 var listContainer = container.parentNode ;
-562 this.splitContainerOf ( container , true ) ;
-563 this.correctEmptyElement ( element ) ;
-564
-565 // 2. extract out LI's children
-566 nodeToReturn = container.firstChild ;
-567 while ( container.firstChild ) {
-568 this.insertNodeAt ( container.firstChild , listContainer , "before" ) ;
-569 }
-570
-571 // 3. remove listContainer and merge adjust lists
-572 var prevContainer = listContainer.previousSibling ;
-573 this.deleteNode ( listContainer ) ;
-574 if ( prevContainer && this.tree.isListContainer ( prevContainer ) ) this.mergeAdjustLists ( prevContainer ) ;
-575 } else {
-576 // 1. split LI
-577 this.splitContainerOf ( element , true ) ;
-578 this.correctEmptyElement ( element ) ;
-579
-580 // 2. split list container
-581 var listContainer = this.splitContainerOf ( container ) ;
-582
-583 // 3. extract out
-584 this.insertNodeAt ( element , listContainer.parentNode , "before" ) ;
-585 this.deleteNode ( listContainer.parentNode ) ;
-586
-587 nodeToReturn = element ;
-588 }
-589 } else if ( this.tree.isTableCell ( container ) || this.tree.isTableCell ( element ) ) {
-590 // do nothing
-591 } else {
-592 // normal block
-593 this.splitContainerOf ( element , true ) ;
-594 this.correctEmptyElement ( element ) ;
-595 nodeToReturn = this.insertNodeAt ( element , container , "before" ) ;
-596
-597 this.deleteNode ( container ) ;
-598 }
-599
-600 return nodeToReturn ;
-601 } ,
-602
-603 /**
-604 * Insert new block above or below given element.
-605 *
-606 * @param {Element} block Target block
-607 * @param {boolean} before Insert new block above(before) target block
-608 * @param {String} forceTag New block's tag name. If omitted, target block's tag name will be used.
-609 *
-610 * @returns {Element} Inserted block
-611 */
-612 insertNewBlockAround : function ( block , before , forceTag ) {
-613 var isListItem = block.nodeName == "LI" || block.parentNode.nodeName == "LI" ;
-614
-615 this.removeTrailingWhitespace ( block ) ;
-616 if ( this.isFirstLiWithNestedList ( block ) && ! forceTag && before ) {
-617 var li = this.getParentElementOf ( block , [ "LI" ] ) ;
-618 var newBlock = this._insertNewBlockAround ( li , before ) ;
-619 return newBlock ;
-620 } else if ( isListItem && ! forceTag ) {
-621 var li = this.getParentElementOf ( block , [ "LI" ] ) ;
-622 var newBlock = this._insertNewBlockAround ( block , before ) ;
-623 if ( li != block ) newBlock = this.splitContainerOf ( newBlock , false , "prev" ) ;
-624 return newBlock ;
-625 } else if ( this.tree.isBlockContainer ( block ) ) {
-626 this.wrapAllInlineOrTextNodesAs ( "P" , block , true ) ;
-627 return this._insertNewBlockAround ( block.firstChild , before , forceTag ) ;
-628 } else {
-629 return this._insertNewBlockAround ( block , before , this.tree.isHeading ( block ) ? "P" : forceTag ) ;
-630 }
-631 } ,
-632
-633 /**
-634 * @private
-635 *
-636 * TODO: Rename
-637 */
-638 _insertNewBlockAround : function ( element , before , tagName ) {
-639 var newElement = this.createElement ( tagName || element.nodeName ) ;
-640 this.copyAttributes ( element , newElement , false ) ;
-641 this.correctEmptyElement ( newElement ) ;
-642 newElement = this.insertNodeAt ( newElement , element , before ? "before" : "after" ) ;
-643 return newElement ;
-644 } ,
-645
-646 /**
-647 * Wrap or replace element with given tag name.
-648 *
-649 * @param {String} tag Tag name
-650 * @param {Element} element Target element
-651 *
-652 * @return {Element} wrapper element or replaced element.
-653 */
-654 applyTagIntoElement : function ( tag , element ) {
-655 if ( this.tree.isBlockOnlyContainer ( tag ) ) {
-656 return this.wrapBlock ( tag , element ) ;
-657 } else if ( this.tree.isBlockContainer ( element ) ) {
-658 var wrapper = this.createElement ( tag ) ;
-659 this.moveChildNodes ( element , wrapper ) ;
-660 return this.insertNodeAt ( wrapper , element , "start" ) ;
-661 } else {
-662 if ( this.tree.isBlockContainer ( tag ) && this.hasImportantAttributes ( element ) ) {
-663 return this.wrapBlock ( tag , element ) ;
-664 } else {
-665 return this.replaceTag ( tag , element ) ;
-666 }
-667 }
-668
-669 throw "IllegalArgumentException - [" + tag + ", " + element + "]" ;
-670 } ,
-671
-672 /**
-673 * Wrap or replace elements with given tag name.
-674 *
-675 * @param {String} tag Tag name
-676 * @param {Element} from Start boundary (inclusive)
-677 * @param {Element} to End boundary (inclusive)
-678 *
-679 * @returns {Array} Array of wrappers or replaced elements
-680 */
-681 applyTagIntoElements : function ( tagName , from , to ) {
-682 var applied = [ ] ;
-683
-684 if ( this.tree.isBlockContainer ( tagName ) ) {
-685 var family = this.tree.findCommonAncestorAndImmediateChildrenOf ( from , to ) ;
-686 var node = family.left ;
-687 var wrapper = this.insertNodeAt ( this.createElement ( tagName ) , node , "before" ) ;
-688
-689 var coveringWholeList =
-690 family.parent.nodeName == "LI" &&
-691 family.parent.parentNode.childNodes.length == 1 &&
-692 ! family.left.previousSilbing &&
-693 ! family.right.nextSibling ;
-694
-695 if ( coveringWholeList ) {
-696 var ul = node.parentNode.parentNode ;
-697 this.insertNodeAt ( wrapper , ul , "before" ) ;
-698 wrapper.appendChild ( ul ) ;
-699 } else {
-700 while ( node != family.right ) {
-701 next = node.nextSibling ;
-702 wrapper.appendChild ( node ) ;
-703 node = next ;
-704 }
-705 wrapper.appendChild ( family.right ) ;
-706 }
-707 applied.push ( wrapper ) ;
-708 } else {
-709 // is normal tagName
-710 var elements = this.getBlockElementsBetween ( from , to ) ;
-711 for ( var i = 0 ; i < elements.length ; i ++ ) {
-712 if ( this.tree.isBlockContainer ( elements [ i ] ) ) {
-713 applied.push ( this.wrapAllInlineOrTextNodesAs ( tagName , elements [ i ] , true ) ) ;
-714 } else {
-715 applied.push ( this.replaceTag ( tagName , elements [ i ] ) ) ;
-716 }
-717 }
-718 }
-719 return applied.flatten ( ) ;
-720 } ,
-721
-722 /**
-723 * Moves block up or down
-724 *
-725 * @param {Element} block Target block
-726 * @param {boolean} up Move up if true
-727 *
-728 * @returns {Element} Moved block. It could be different with given block.
-729 */
-730 moveBlock : function ( block , up ) {
-731 // if block is table cell or contained by table cell, select its row as mover
-732 block = this.getParentElementOf ( block , [ "TR" ] ) || block ;
-733
-734 // if block is only child, select its parent as mover
-735 while ( block.nodeName != "TR" && block.parentNode != this.getRoot ( ) && ! block.previousSibling && ! block.nextSibling && ! this.tree.isListContainer ( block.parentNode ) ) {
-736 block = block.parentNode ;
-737 }
-738
-739 // find target and where
-740 var target , where ;
-741 if ( up ) {
-742 target = block.previousSibling ;
-743
-744 if ( target ) {
-745 var singleNodeLi = target.nodeName == 'LI' && ( ( target.childNodes.length == 1 && this.tree.isBlock ( target.firstChild ) ) || ! this.tree.hasBlocks ( target ) ) ;
-746 var table = [ 'TABLE' , 'TR' ] . include ( target.nodeName ) ;
-747
-748 where = this.tree.isBlockContainer ( target ) && ! singleNodeLi && ! table ? "end" : "before" ;
-749 } else if ( block.parentNode != this.getRoot ( ) ) {
-750 target = block.parentNode ;
-751 where = "before" ;
-752 }
-753 } else {
-754 target = block.nextSibling ;
-755
-756 if ( target ) {
-757 var singleNodeLi = target.nodeName == 'LI' && ( ( target.childNodes.length == 1 && this.tree.isBlock ( target.firstChild ) ) || ! this.tree.hasBlocks ( target ) ) ;
-758 var table = [ 'TABLE' , 'TR' ] . include ( target.nodeName ) ;
-759
-760 where = this.tree.isBlockContainer ( target ) && ! singleNodeLi && ! table ? "start" : "after" ;
-761 } else if ( block.parentNode != this.getRoot ( ) ) {
-762 target = block.parentNode ;
-763 where = "after" ;
-764 }
-765 }
-766
-767
-768 // no way to go?
-769 if ( ! target ) return null ;
-770 if ( [ "TBODY" , "THEAD" ] . include ( target.nodeName ) ) return null ;
-771
-772 // normalize
-773 this.wrapAllInlineOrTextNodesAs ( "P" , target , true ) ;
-774
-775 // make placeholder if needed
-776 if ( this.isFirstLiWithNestedList ( block ) ) {
-777 this.insertNewBlockAround ( block , false , "P" ) ;
-778 }
-779
-780 // perform move
-781 var parent = block.parentNode ;
-782 var moved = this.insertNodeAt ( block , target , where , true ) ;
-783
-784 // cleanup
-785 if ( ! parent.hasChildNodes ( ) ) this.deleteNode ( parent , true ) ;
-786 this.unwrapUnnecessaryParagraph ( moved ) ;
-787 this.unwrapUnnecessaryParagraph ( target ) ;
-788
-789 // remove placeholder
-790 if ( up ) {
-791 if ( moved.previousSibling && this.isEmptyBlock ( moved.previousSibling ) && ! moved.previousSibling.previousSibling && moved.parentNode.nodeName == "LI" && this.tree.isListContainer ( moved.nextSibling ) ) {
-792 this.deleteNode ( moved.previousSibling ) ;
-793 }
-794 } else {
-795 if ( moved.nextSibling && this.isEmptyBlock ( moved.nextSibling ) && ! moved.previousSibling && moved.parentNode.nodeName == "LI" && this.tree.isListContainer ( moved.nextSibling.nextSibling ) ) {
-796 this.deleteNode ( moved.nextSibling ) ;
-797 }
-798 }
-799
-800 return moved ;
-801 } ,
-802
-803 /**
-804 * Remove given block
-805 *
-806 * @param {Element} block Target block
-807 * @returns {Element} Nearest block of remove element
-808 */
-809 removeBlock : function ( block ) {
-810 var blockToMove ;
-811
-812 // if block is only child, select its parent as mover
-813 while ( block.parentNode != this.getRoot ( ) && ! block.previousSibling && ! block.nextSibling && ! this.tree.isListContainer ( block.parentNode ) ) {
-814 block = block.parentNode ;
-815 }
-816
-817 var finder = function ( node ) { return this.tree.isBlock ( node ) && ! this.tree.isAtomic ( node ) && ! this.tree.isDescendantOf ( block , node ) && ! this.tree.hasBlocks ( node ) ; } . bind ( this ) ;
-818 var exitCondition = function ( node ) { return this.tree.isBlock ( node ) && ! this.tree.isDescendantOf ( this.getRoot ( ) , node ) } . bind ( this ) ;
-819
-820 if ( this.isFirstLiWithNestedList ( block ) ) {
-821 blockToMove = this.outdentListItem ( block.nextSibling.firstChild ) ;
-822 this.deleteNode ( blockToMove.previousSibling , true ) ;
-823 } else if ( this.tree.isTableCell ( block ) ) {
-824 var rtable = new xq.RichTable ( this , this.getParentElementOf ( block , [ "TABLE" ] ) ) ;
-825 blockToMove = rtable.getBelowCellOf ( block ) ;
-826
-827 // should not delete row when there's thead and the row is the only child of tbody
-828 if (
-829 block.parentNode.parentNode.nodeName == "TBODY" &&
-830 rtable.hasHeadingAtTop ( ) &&
-831 rtable.getDom ( ) . tBodies [ 0 ] . rows.length == 1 ) return blockToMove ;
-832
-833 blockToMove = blockToMove ||
-834 this.tree.findForward ( block , finder , exitCondition ) ||
-835 this.tree.findBackward ( block , finder , exitCondition ) ;
-836
-837 this.deleteNode ( block.parentNode , true ) ;
-838 } else {
-839 blockToMove = blockToMove ||
-840 this.tree.findForward ( block , finder , exitCondition ) ||
-841 this.tree.findBackward ( block , finder , exitCondition ) ;
-842
-843 if ( ! blockToMove ) blockToMove = this.insertNodeAt ( this.makeEmptyParagraph ( ) , block , "after" ) ;
-844
-845 this.deleteNode ( block , true ) ;
-846 }
-847 if ( ! this.getRoot ( ) . hasChildNodes ( ) ) {
-848 blockToMove = this.createElement ( "P" ) ;
-849 this.getRoot ( ) . appendChild ( blockToMove ) ;
-850 this.correctEmptyElement ( blockToMove ) ;
-851 }
-852
-853 return blockToMove ;
-854 } ,
-855
-856 /**
-857 * Removes trailing whitespaces of given block
-858 *
-859 * @param {Element} block Target block
-860 */
-861 removeTrailingWhitespace : function ( block ) { throw "Not implemented" } ,
-862
-863 /**
-864 * Extract given list item out and change its container's tag
-865 *
-866 * @param {Element} element LI or P which is a child of LI
-867 * @param {String} type "OL", "UL", or "CODE"
-868 *
-869 * @returns {Element} changed element
-870 */
-871 changeListTypeTo : function ( element , type ) {
-872 type = type.toUpperCase ( ) ;
-873
-874 var li = this.getParentElementOf ( element , [ "LI" ] ) ;
-875 if ( ! li ) throw "IllegalArgumentException" ;
-876
-877 var container = li.parentNode ;
-878
-879 this.splitContainerOf ( li ) ;
-880
-881 var newContainer = this.insertNodeAt ( this.createElement ( type == "UL" ? "UL" : "OL" ) , container , "before" ) ;
-882 if ( type == "CODE" ) newContainer.className = "code" ;
-883
-884 this.insertNodeAt ( li , newContainer , "start" ) ;
-885 this.deleteNode ( container ) ;
-886
-887 this.mergeAdjustLists ( newContainer ) ;
-888
-889 return element ;
-890 } ,
-891
-892 /**
-893 * Split container of element into (maxium) three pieces.
-894 */
-895 splitContainerOf : function ( element , preserveElementItself , dir ) {
-896 if ( [ element , element.parentNode ] . include ( this.getRoot ( ) ) ) return element ;
-897
-898 var container = element.parentNode ;
-899 if ( element.previousSibling && ( ! dir || dir.toLowerCase ( ) == "prev" ) ) {
-900 var prev = this.createElement ( container.nodeName ) ;
-901 this.copyAttributes ( container , prev ) ;
-902 while ( container.firstChild != element ) {
-903 prev.appendChild ( container.firstChild ) ;
-904 }
-905 this.insertNodeAt ( prev , container , "before" ) ;
-906 this.unwrapUnnecessaryParagraph ( prev ) ;
-907 }
-908
-909 if ( element.nextSibling && ( ! dir || dir.toLowerCase ( ) == "next" ) ) {
-910 var next = this.createElement ( container.nodeName ) ;
-911 this.copyAttributes ( container , next ) ;
-912 while ( container.lastChild != element ) {
-913 this.insertNodeAt ( container.lastChild , next , "start" ) ;
-914 }
-915 this.insertNodeAt ( next , container , "after" ) ;
-916 this.unwrapUnnecessaryParagraph ( next ) ;
-917 }
-918
-919 if ( ! preserveElementItself ) element = this.unwrapUnnecessaryParagraph ( container ) ? container : element ;
-920 return element ;
-921 } ,
-922
-923 /**
-924 * TODO: Add specs
-925 */
-926 splitParentElement : function ( seperator ) {
-927 var parent = seperator.parentNode ;
-928 if ( [ "HTML" , "HEAD" , "BODY" ] . include ( parent.nodeName ) ) throw "Illegal argument. Cannot seperate element[" + parent.nodeName + "]" ;
-929
-930 var previousSibling = seperator.previousSibling ;
-931 var nextSibling = seperator.nextSibling ;
-932
-933 var newElement = this.insertNodeAt ( this.createElement ( parent.nodeName ) , parent , "after" ) ;
-934
-935 var next ;
-936 while ( next = seperator.nextSibling ) newElement.appendChild ( next ) ;
-937
-938 this.insertNodeAt ( seperator , newElement , "start" ) ;
-939 this.copyAttributes ( parent , newElement ) ;
-940
-941 return newElement ;
-942 } ,
-943
-944 /**
-945 * TODO: Add specs
-946 */
-947 splitElementUpto : function ( seperator , element , excludeElement ) {
-948 while ( seperator.previousSibling != element ) {
-949 if ( excludeElement && seperator.parentNode == element ) break ;
-950 seperator = this.splitParentElement ( seperator ) ;
-951 }
-952 return seperator ;
-953 } ,
-954
-955 /**
-956 * Merges two adjust elements
-957 *
-958 * @param {Element} element base element
-959 * @param {boolean} withNext merge base element with next sibling
-960 * @param {boolean} skip skip merge steps
-961 */
-962 mergeElement : function ( element , withNext , skip ) {
-963 this.wrapAllInlineOrTextNodesAs ( "P" , element.parentNode , true ) ;
-964
-965 // find two block
-966 if ( withNext ) {
-967 var prev = element ;
-968 var next = this.tree.findForward (
-969 element ,
-970 function ( node ) { return this.tree.isBlock ( node ) && ! this.tree.isListContainer ( node ) && node != element.parentNode } . bind ( this )
-971 ) ;
-972 } else {
-973 var next = element ;
-974 var prev = this.tree.findBackward (
-975 element ,
-976 function ( node ) { return this.tree.isBlock ( node ) && ! this.tree.isListContainer ( node ) && node != element.parentNode } . bind ( this )
-977 ) ;
-978 }
-979
-980 // normalize next block
-981 if ( next && this.tree.isDescendantOf ( this.getRoot ( ) , next ) ) {
-982 var nextContainer = next.parentNode ;
-983 if ( this.tree.isBlockContainer ( next ) ) {
-984 nextContainer = next ;
-985 this.wrapAllInlineOrTextNodesAs ( "P" , nextContainer , true ) ;
-986 next = nextContainer.firstChild ;
-987 }
-988 } else {
-989 next = null ;
-990 }
-991
-992 // normalize prev block
-993 if ( prev && this.tree.isDescendantOf ( this.getRoot ( ) , prev ) ) {
-994 var prevContainer = prev.parentNode ;
-995 if ( this.tree.isBlockContainer ( prev ) ) {
-996 prevContainer = prev ;
-997 this.wrapAllInlineOrTextNodesAs ( "P" , prevContainer , true ) ;
-998 prev = prevContainer.lastChild ;
-999 }
-1000 } else {
-1001 prev = null ;
-1002 }
-1003
-1004 try {
-1005 var containersAreTableCell =
-1006 prevContainer && ( this.tree.isTableCell ( prevContainer ) || [ 'TR' , 'THEAD' , 'TBODY' ] . include ( prevContainer.nodeName ) ) &&
-1007 nextContainer && ( this.tree.isTableCell ( nextContainer ) || [ 'TR' , 'THEAD' , 'TBODY' ] . include ( nextContainer.nodeName ) ) ;
-1008
-1009 if ( containersAreTableCell && prevContainer != nextContainer ) return null ;
-1010
-1011 // if next has margin, perform outdent
-1012 if ( ( ! skip || ! prev ) && next && this.outdentElement ( next ) ) return element ;
-1013
-1014 // nextContainer is first li and next of it is list container
-1015 if ( nextContainer && nextContainer.nodeName == 'LI' && this.tree.isListContainer ( next.nextSibling ) ) {
-1016 this.extractOutElementFromParent ( nextContainer ) ;
-1017 return prev ;
-1018 }
-1019
-1020 // merge two list containers
-1021 if ( nextContainer && nextContainer.nodeName == 'LI' && this.tree.isListContainer ( nextContainer.parentNode.previousSibling ) ) {
-1022 this.mergeAdjustLists ( nextContainer.parentNode.previousSibling , true , "next" ) ;
-1023 return prev ;
-1024 }
-1025
-1026 if ( next && ! containersAreTableCell && prevContainer && prevContainer.nodeName == 'LI' && nextContainer && nextContainer.nodeName == 'LI' && prevContainer.parentNode.nextSibling == nextContainer.parentNode ) {
-1027 var nextContainerContainer = nextContainer.parentNode ;
-1028 this.moveChildNodes ( nextContainer.parentNode , prevContainer.parentNode ) ;
-1029 this.deleteNode ( nextContainerContainer ) ;
-1030 return prev ;
-1031 }
-1032
-1033 // merge two containers
-1034 if ( next && ! containersAreTableCell && prevContainer && prevContainer.nextSibling == nextContainer && ( ( skip && prevContainer.nodeName != "LI" ) || ( ! skip && prevContainer.nodeName == "LI" ) ) ) {
-1035 this.moveChildNodes ( nextContainer , prevContainer ) ;
-1036 return prev ;
-1037 }
-1038
-1039 // unwrap container
-1040 if ( nextContainer && nextContainer.nodeName != "LI" && ! this.getParentElementOf ( nextContainer , [ "TABLE" ] ) && ! this.tree.isListContainer ( nextContainer ) && nextContainer != this.getRoot ( ) && ! next.previousSibling ) {
-1041 return this.unwrapElement ( nextContainer , true ) ;
-1042 }
-1043
-1044 // delete table
-1045 if ( withNext && nextContainer && nextContainer.nodeName == "TABLE" ) {
-1046 this.deleteNode ( nextContainer , true ) ;
-1047 return prev ;
-1048 } else if ( ! withNext && prevContainer && this.tree.isTableCell ( prevContainer ) && ! this.tree.isTableCell ( nextContainer ) ) {
-1049 this.deleteNode ( this.getParentElementOf ( prevContainer , [ "TABLE" ] ) , true ) ;
-1050 return next ;
-1051 }
-1052
-1053 // if prev is same with next, do nothing
-1054 if ( prev == next ) return null ;
-1055
-1056 // if there is a null block, do nothing
-1057 if ( ! prev || ! next || ! prevContainer || ! nextContainer ) return null ;
-1058
-1059 // if two blocks are not in the same table cell, do nothing
-1060 if ( this.getParentElementOf ( prev , [ "TD" , "TH" ] ) != this.getParentElementOf ( next , [ "TD" , "TH" ] ) ) return null ;
-1061
-1062 var prevIsEmpty = false ;
-1063
-1064 // cleanup empty block before merge
-1065
-1066 // 1. cleanup prev node which ends with marker +
-1067 if (
-1068 xq.Browser.isTrident &&
-1069 prev.childNodes.length >= 2 &&
-1070 this.isMarker ( prev.lastChild.previousSibling ) &&
-1071 prev.lastChild.nodeType == 3 &&
-1072 prev.lastChild.nodeValue.length == 1 &&
-1073 prev.lastChild.nodeValue.charCodeAt ( 0 ) == 160
-1074 ) {
-1075 this.deleteNode ( prev.lastChild ) ;
-1076 }
-1077
-1078 // 2. cleanup prev node (if prev is empty, then replace prev's tag with next's)
-1079 this.removePlaceHoldersAndEmptyNodes ( prev ) ;
-1080 if ( this.isEmptyBlock ( prev ) ) {
-1081 // replace atomic block with normal block so that following code don't need to care about atomic block
-1082 if ( this.tree.isAtomic ( prev ) ) prev = this.replaceTag ( "P" , prev ) ;
-1083
-1084 prev = this.replaceTag ( next.nodeName , prev ) || prev ;
-1085 prev.innerHTML = "" ;
-1086 } else if ( prev.firstChild == prev.lastChild && this.isMarker ( prev.firstChild ) ) {
-1087 prev = this.replaceTag ( next.nodeName , prev ) || prev ;
-1088 }
-1089
-1090 // 3. cleanup next node
-1091 if ( this.isEmptyBlock ( next ) ) {
-1092 // replace atomic block with normal block so that following code don't need to care about atomic block
-1093 if ( this.tree.isAtomic ( next ) ) next = this.replaceTag ( "P" , next ) ;
-1094
-1095 next.innerHTML = "" ;
-1096 }
-1097
-1098 // perform merge
-1099 this.moveChildNodes ( next , prev ) ;
-1100 this.deleteNode ( next ) ;
-1101 return prev ;
-1102 } finally {
-1103 // cleanup
-1104 if ( prevContainer && this.isEmptyBlock ( prevContainer ) ) this.deleteNode ( prevContainer , true ) ;
-1105 if ( nextContainer && this.isEmptyBlock ( nextContainer ) ) this.deleteNode ( nextContainer , true ) ;
-1106
-1107 if ( prevContainer ) this.unwrapUnnecessaryParagraph ( prevContainer ) ;
-1108 if ( nextContainer ) this.unwrapUnnecessaryParagraph ( nextContainer ) ;
-1109 }
-1110 } ,
-1111
-1112 /**
-1113 * Merges adjust list containers which has same tag name
-1114 *
-1115 * @param {Element} container target list container
-1116 * @param {boolean} force force adjust list container even if they have different list type
-1117 * @param {String} dir Specify merge direction: PREV or NEXT. If not supplied it will be merged with both direction.
-1118 */
-1119 mergeAdjustLists : function ( container , force , dir ) {
-1120 var prev = container.previousSibling ;
-1121 var isPrevSame = prev && ( prev.nodeName == container.nodeName && prev.className == container.className ) ;
-1122 if ( ( ! dir || dir.toLowerCase ( ) == 'prev' ) && ( isPrevSame || ( force && this.tree.isListContainer ( prev ) ) ) ) {
-1123 while ( prev.lastChild ) {
-1124 this.insertNodeAt ( prev.lastChild , container , "start" ) ;
-1125 }
-1126 this.deleteNode ( prev ) ;
-1127 }
-1128
-1129 var next = container.nextSibling ;
-1130 var isNextSame = next && ( next.nodeName == container.nodeName && next.className == container.className ) ;
-1131 if ( ( ! dir || dir.toLowerCase ( ) == 'next' ) && ( isNextSame || ( force && this.tree.isListContainer ( next ) ) ) ) {
-1132 while ( next.firstChild ) {
-1133 this.insertNodeAt ( next.firstChild , container , "end" ) ;
-1134 }
-1135 this.deleteNode ( next ) ;
-1136 }
-1137 } ,
-1138
-1139 /**
-1140 * Moves child nodes from one element into another.
-1141 *
-1142 * @param {Elemet} from source element
-1143 * @param {Elemet} to target element
-1144 */
-1145 moveChildNodes : function ( from , to ) {
-1146 if ( this.tree.isDescendantOf ( from , to ) || [ "HTML" , "HEAD" ] . include ( to.nodeName ) )
-1147 throw "Illegal argument. Cannot move children of element[" + from.nodeName + "] to element[" + to.nodeName + "]" ;
-1148
-1149 if ( from == to ) return ;
-1150
-1151 while ( from.firstChild ) to.appendChild ( from.firstChild ) ;
-1152 } ,
-1153
-1154 /**
-1155 * Copies attributes from one element into another.
-1156 *
-1157 * @param {Element} from source element
-1158 * @param {Element} to target element
-1159 * @param {boolean} copyId copy ID attribute of source element
-1160 */
-1161 copyAttributes : function ( from , to , copyId ) {
-1162 // IE overrides this
-1163
-1164 var attrs = from.attributes ;
-1165 if ( ! attrs ) return ;
-1166
-1167 for ( var i = 0 ; i < attrs.length ; i ++ ) {
-1168 if ( attrs [ i ] . nodeName == "class" && attrs [ i ] . nodeValue ) {
-1169 to.className = attrs [ i ] . nodeValue ;
-1170 } else if ( ( copyId || ! [ "id" ] . include ( attrs [ i ] . nodeName ) ) && attrs [ i ] . nodeValue ) {
-1171 to.setAttribute ( attrs [ i ] . nodeName , attrs [ i ] . nodeValue ) ;
-1172 }
-1173 }
-1174 } ,
-1175
-1176 _indentElements : function ( node , blocks , affect ) {
-1177 for ( var i = 0 ; i < affect.length ; i ++ ) {
-1178 if ( affect [ i ] == node || this.tree.isDescendantOf ( affect [ i ] , node ) )
-1179 return ;
-1180 }
-1181 leaves = this.tree.getLeavesAtEdge ( node ) ;
-1182
-1183 if ( blocks.include ( leaves [ 0 ] ) ) {
-1184 var affected = this.indentElement ( node , true ) ;
-1185 if ( affected ) {
-1186 affect.push ( affected ) ;
-1187 return ;
-1188 }
-1189 }
-1190
-1191 if ( blocks.include ( node ) ) {
-1192 var affected = this.indentElement ( node , true ) ;
-1193 if ( affected ) {
-1194 affect.push ( affected ) ;
-1195 return ;
-1196 }
-1197 }
-1198
-1199 var children = $A ( node.childNodes ) ;
-1200 for ( var i = 0 ; i < children.length ; i ++ )
-1201 this._indentElements ( children [ i ] , blocks , affect ) ;
-1202 return ;
-1203 } ,
-1204
-1205 indentElements : function ( from , to ) {
-1206 var blocks = this.getBlockElementsBetween ( from , to ) ;
-1207 var top = this.tree.findCommonAncestorAndImmediateChildrenOf ( from , to ) ;
-1208
-1209 var affect = [ ] ;
-1210
-1211 leaves = this.tree.getLeavesAtEdge ( top.parent ) ;
-1212 if ( blocks.include ( leaves [ 0 ] ) ) {
-1213 var affected = this.indentElement ( top.parent ) ;
-1214 if ( affected )
-1215 return [ affected ] ;
-1216 }
-1217
-1218 var children = $A ( top.parent.childNodes ) ;
-1219 for ( var i = 0 ; i < children.length ; i ++ ) {
-1220 this._indentElements ( children [ i ] , blocks , affect ) ;
-1221 }
-1222
-1223 affect = affect.flatten ( )
-1224 return affect.length > 0 ? affect : blocks ;
-1225 } ,
-1226
-1227 outdentElementsCode : function ( node ) {
-1228 if ( node.tagName == 'LI' )
-1229 node = node.parentNode ;
-1230 if ( node.tagName == 'OL' && node.className == 'code' )
-1231 return true ;
-1232 return false ;
-1233 } ,
-1234
-1235 _outdentElements : function ( node , blocks , affect ) {
-1236 for ( var i = 0 ; i < affect.length ; i ++ ) {
-1237 if ( affect [ i ] == node || this.tree.isDescendantOf ( affect [ i ] , node ) )
-1238 return ;
-1239 }
-1240 leaves = this.tree.getLeavesAtEdge ( node ) ;
-1241
-1242 if ( blocks.include ( leaves [ 0 ] ) && ! this.outdentElementsCode ( leaves [ 0 ] ) ) {
-1243 var affected = this.outdentElement ( node , true ) ;
-1244 if ( affected ) {
-1245 affect.push ( affected ) ;
-1246 return ;
-1247 }
-1248 }
-1249
-1250 if ( blocks.include ( node ) ) {
-1251 var children = $A ( node.parentNode.childNodes ) ;
-1252 var isCode = this.outdentElementsCode ( node ) ;
-1253 var affected = this.outdentElement ( node , true , isCode ) ;
-1254 if ( affected ) {
-1255 if ( children.include ( affected ) && this.tree.isListContainer ( node.parentNode ) && ! isCode ) {
-1256 for ( var i = 0 ; i < children.length ; i ++ ) {
-1257 if ( blocks.include ( children [ i ] ) && ! affect.include ( children [ i ] ) )
-1258 affect.push ( children [ i ] ) ;
-1259 }
-1260 } else
-1261 affect.push ( affected ) ;
-1262 return ;
-1263 }
-1264 }
-1265
-1266 var children = $A ( node.childNodes ) ;
-1267 for ( var i = 0 ; i < children.length ; i ++ )
-1268 this._outdentElements ( children [ i ] , blocks , affect ) ;
-1269 return ;
-1270 } ,
-1271
-1272 outdentElements : function ( from , to ) {
-1273 var start , end ;
-1274
-1275 if ( from.parentNode.tagName == 'LI' ) start = from.parentNode ;
-1276 if ( to.parentNode.tagName == 'LI' ) end = to.parentNode ;
-1277
-1278 var blocks = this.getBlockElementsBetween ( from , to ) ;
-1279 var top = this.tree.findCommonAncestorAndImmediateChildrenOf ( from , to ) ;
-1280
-1281 var affect = [ ] ;
-1282
-1283 leaves = this.tree.getLeavesAtEdge ( top.parent ) ;
-1284 if ( blocks.include ( leaves [ 0 ] ) && ! this.outdentElementsCode ( top.parent ) ) {
-1285 var affected = this.outdentElement ( top.parent ) ;
-1286 if ( affected )
-1287 return [ affected ] ;
-1288 }
-1289
-1290 var children = $A ( top.parent.childNodes ) ;
-1291 for ( var i = 0 ; i < children.length ; i ++ ) {
-1292 this._outdentElements ( children [ i ] , blocks , affect ) ;
-1293 }
-1294
-1295 if ( from.offsetParent && to.offsetParent ) {
-1296 start = from ;
-1297 end = to ;
-1298 } else if ( blocks.first ( ) . offsetParent && blocks.last ( ) . offsetParent ) {
-1299 start = blocks.first ( ) ;
-1300 end = blocks.last ( ) ;
-1301 }
-1302
-1303 affect = affect.flatten ( )
-1304 if ( ! start || ! start.offsetParent )
-1305 start = affect.first ( ) ;
-1306 if ( ! end || ! end.offsetParent )
-1307 end = affect.last ( ) ;
-1308
-1309 return this.getBlockElementsBetween ( start , end ) ;
-1310 } ,
-1311
-1312 /**
-1313 * Performs indent by increasing element's margin-left
-1314 */
-1315 indentElement : function ( element , noParent , forceMargin ) {
-1316 if (
-1317 ! forceMargin &&
-1318 ( element.nodeName == "LI" || ( ! this.tree.isListContainer ( element ) && ! element.previousSibling && element.parentNode.nodeName == "LI" ) )
-1319 ) return this.indentListItem ( element , noParent ) ;
-1320
-1321 var root = this.getRoot ( ) ;
-1322 if ( ! element || element == root ) return null ;
-1323
-1324 if ( element.parentNode != root && ! element.previousSibling && ! noParent ) element = element.parentNode ;
-1325
-1326 var margin = element.style.marginLeft ;
-1327 var cssValue = margin ? this._getCssValue ( margin , "px" ) : { value : 0 , unit : "em" } ;
-1328
-1329 cssValue.value + = 2 ;
-1330 element.style.marginLeft = cssValue.value + cssValue.unit ;
-1331
-1332 return element ;
-1333 } ,
-1334
-1335 /**
-1336 * Performs outdent by decreasing element's margin-left
-1337 */
-1338 outdentElement : function ( element , noParent , forceMargin ) {
-1339 if ( ! forceMargin && element.nodeName == "LI" ) return this.outdentListItem ( element , noParent ) ;
-1340
-1341 var root = this.getRoot ( ) ;
-1342 if ( ! element || element == root ) return null ;
-1343
-1344 var margin = element.style.marginLeft ;
-1345
-1346 var cssValue = margin ? this._getCssValue ( margin , "px" ) : { value : 0 , unit : "em" } ;
-1347 if ( cssValue.value == 0 ) {
-1348 return element.previousSibling || forceMargin ?
-1349 null :
-1350 this.outdentElement ( element.parentNode , noParent ) ;
-1351 }
-1352
-1353 cssValue.value - = 2 ;
-1354 element.style.marginLeft = cssValue.value <= 0 ? "" : cssValue.value + cssValue.unit ;
-1355 if ( element.style.cssText == "" ) element.removeAttribute ( "style" ) ;
-1356
-1357 return element ;
-1358 } ,
-1359
-1360 /**
-1361 * Performs indent for list item
-1362 */
-1363 indentListItem : function ( element , treatListAsNormalBlock ) {
-1364 var li = this.getParentElementOf ( element , [ "LI" ] ) ;
-1365 var container = li.parentNode ;
-1366 var prev = li.previousSibling ;
-1367 if ( ! li.previousSibling ) return this.indentElement ( container ) ;
-1368
-1369 if ( li.parentNode.nodeName == "OL" && li.parentNode.className == "code" ) return this.indentElement ( li , treatListAsNormalBlock , true ) ;
-1370
-1371 if ( ! prev.lastChild ) prev.appendChild ( this.makePlaceHolder ( ) ) ;
-1372
-1373 var targetContainer =
-1374 this.tree.isListContainer ( prev.lastChild ) ?
-1375 // if there's existing list container, select it as target container
-1376 prev.lastChild :
-1377 // if there's nothing, create new one
-1378 this.insertNodeAt ( this.createElement ( container.nodeName ) , prev , "end" ) ;
-1379
-1380 this.wrapAllInlineOrTextNodesAs ( "P" , prev , true ) ;
-1381
-1382 // perform move
-1383 targetContainer.appendChild ( li ) ;
-1384
-1385 // flatten nested list
-1386 if ( ! treatListAsNormalBlock && li.lastChild && this.tree.isListContainer ( li.lastChild ) ) {
-1387 var childrenContainer = li.lastChild ;
-1388 var child ;
-1389 while ( child = childrenContainer.lastChild ) {
-1390 this.insertNodeAt ( child , li , "after" ) ;
-1391 }
-1392 this.deleteNode ( childrenContainer ) ;
-1393 }
-1394
-1395 this.unwrapUnnecessaryParagraph ( li ) ;
-1396
-1397 return li ;
-1398 } ,
-1399
-1400 /**
-1401 * Performs outdent for list item
-1402 *
-1403 * @return {Element} outdented list item or null if no outdent performed
-1404 */
-1405 outdentListItem : function ( element , treatListAsNormalBlock ) {
-1406 var li = this.getParentElementOf ( element , [ "LI" ] ) ;
-1407 var container = li.parentNode ;
-1408
-1409 if ( ! li.previousSibling ) {
-1410 var performed = this.outdentElement ( container ) ;
-1411 if ( performed ) return performed ;
-1412 }
-1413
-1414 if ( li.parentNode.nodeName == "OL" && li.parentNode.className == "code" ) return this.outdentElement ( li , treatListAsNormalBlock , true ) ;
-1415
-1416 var parentLi = container.parentNode ;
-1417 if ( parentLi.nodeName != "LI" ) return null ;
-1418
-1419 if ( treatListAsNormalBlock ) {
-1420 while ( container.lastChild != li ) {
-1421 this.insertNodeAt ( container.lastChild , parentLi , "after" ) ;
-1422 }
-1423 } else {
-1424 // make next siblings as children
-1425 if ( li.nextSibling ) {
-1426 var targetContainer =
-1427 li.lastChild && this.tree.isListContainer ( li.lastChild ) ?
-1428 // if there's existing list container, select it as target container
-1429 li.lastChild :
-1430 // if there's nothing, create new one
-1431 this.insertNodeAt ( this.createElement ( container.nodeName ) , li , "end" ) ;
-1432
-1433 this.copyAttributes ( container , targetContainer ) ;
-1434
-1435 var sibling ;
-1436 while ( sibling = li.nextSibling ) {
-1437 targetContainer.appendChild ( sibling ) ;
-1438 }
-1439 }
-1440 }
-1441
-1442 // move current LI into parent LI's next sibling
-1443 li = this.insertNodeAt ( li , parentLi , "after" ) ;
-1444
-1445 // remove empty container
-1446 if ( container.childNodes.length == 0 ) this.deleteNode ( container ) ;
-1447
-1448 if ( li.firstChild && this.tree.isListContainer ( li.firstChild ) ) {
-1449 this.insertNodeAt ( this.makePlaceHolder ( ) , li , "start" ) ;
-1450 }
-1451
-1452 this.wrapAllInlineOrTextNodesAs ( "P" , li ) ;
-1453 this.unwrapUnnecessaryParagraph ( parentLi ) ;
-1454
-1455 return li ;
-1456 } ,
-1457
-1458 /**
-1459 * Performs justification
-1460 *
-1461 * @param {Element} block target element
-1462 * @param {String} dir one of "LEFT", "CENTER", "RIGHT", "BOTH"
-1463 */
-1464 justifyBlock : function ( block , dir ) {
-1465 // if block is only child, select its parent as mover
-1466 while ( block.parentNode != this.getRoot ( ) && ! block.previousSibling && ! block.nextSibling && ! this.tree.isListContainer ( block.parentNode ) ) {
-1467 block = block.parentNode ;
-1468 }
-1469
-1470 var styleValue = dir.toLowerCase ( ) == "both" ? "justify" : dir ;
-1471 if ( styleValue == "left" ) {
-1472 block.style.textAlign = "" ;
-1473 if ( block.style.cssText == "" ) block.removeAttribute ( "style" ) ;
-1474 } else {
-1475 block.style.textAlign = styleValue ;
-1476 }
-1477 return block ;
-1478 } ,
-1479
-1480 justifyBlocks : function ( blocks , dir ) {
-1481 blocks.each ( function ( block ) {
-1482 this.justifyBlock ( block , dir ) ;
-1483 } . bind ( this ) ) ;
-1484
-1485 return blocks ;
-1486 } ,
-1487
-1488 /**
-1489 * Turn given element into list. If the element is a list already, it will be reversed into normal element.
-1490 *
-1491 * @param {Element} element target element
-1492 * @param {String} type one of "UL", "OL"
-1493 * @returns {Element} affected element
-1494 */
-1495 applyList : function ( element , type ) {
-1496 type = type.toUpperCase ( ) ;
-1497 var containerTag = type == "UL" ? "UL" : "OL" ;
-1498
-1499 if ( element.nodeName == "LI" || ( element.parentNode.nodeName == "LI" && ! element.previousSibling ) ) {
-1500 var element = this.getParentElementOf ( element , [ "LI" ] ) ;
-1501 var container = element.parentNode ;
-1502 if ( container.nodeName == containerTag ) {
-1503 return this.extractOutElementFromParent ( element ) ;
-1504 } else {
-1505 return this.changeListTypeTo ( element , type ) ;
-1506 }
-1507 } else {
-1508 return this.turnElementIntoListItem ( element , type ) ;
-1509 }
-1510 } ,
-1511
-1512 applyLists : function ( from , to , type ) {
-1513 type = type.toUpperCase ( ) ;
-1514 var containerTag = type == "UL" ? "UL" : "OL" ;
-1515 var blocks = this.getBlockElementsBetween ( from , to ) ;
-1516
-1517 // LIs or Non-containing blocks
-1518 var whole = blocks.findAll ( function ( e ) {
-1519 return e.nodeName == "LI" || ! this.tree.isBlockContainer ( e ) ;
-1520 } . bind ( this ) ) ;
-1521
-1522 // LIs
-1523 var listItems = whole.findAll ( function ( e ) { return e.nodeName == "LI" } . bind ( this ) ) ;
-1524
-1525 // Non-containing blocks which is not a descendant of any LIs selected above(listItems).
-1526 var normalBlocks = whole.findAll ( function ( e ) {
-1527 return e.nodeName != "LI" &&
-1528 ! ( e.parentNode.nodeName == "LI" && ! e.previousSibling && ! e.nextSibling ) &&
-1529 ! this.tree.isDescendantOf ( listItems , e )
-1530 } . bind ( this ) ) ;
-1531
-1532 var diffListItems = listItems.findAll ( function ( e ) {
-1533 return e.parentNode.nodeName != containerTag ;
-1534 } . bind ( this ) ) ;
-1535
-1536 // Conditions needed to determine mode
-1537 var hasNormalBlocks = normalBlocks.length > 0 ;
-1538 var hasDifferentListStyle = diffListItems.length > 0 ;
-1539
-1540 var blockToHandle = null ;
-1541
-1542 if ( hasNormalBlocks ) {
-1543 blockToHandle = normalBlocks ;
-1544 } else if ( hasDifferentListStyle ) {
-1545 blockToHandle = diffListItems ;
-1546 } else {
-1547 blockToHandle = listItems ;
-1548 }
-1549
-1550 // perform operation
-1551 for ( var i = 0 ; i < blockToHandle.length ; i ++ ) {
-1552 var block = blockToHandle [ i ] ;
-1553
-1554 // preserve original index to restore selection
-1555 var originalIndex = blocks.indexOf ( block ) ;
-1556 blocks [ originalIndex ] = this.applyList ( block , type ) ;
-1557 }
-1558
-1559 return blocks ;
-1560 } ,
-1561
-1562 /**
-1563 * Insert place-holder for given empty element. Empty element does not displayed and causes many editing problems.
-1564 *
-1565 * @param {Element} element empty element
-1566 */
-1567 correctEmptyElement : function ( element ) { throw "Not implemented" } ,
-1568
-1569 /**
-1570 * Corrects current block-only-container to do not take any non-block element or node.
-1571 */
-1572 correctParagraph : function ( ) { throw "Not implemented" } ,
-1573
-1574 /**
-1575 * Makes place-holder for empty element.
-1576 *
-1577 * @returns {Node} Platform specific place holder
-1578 */
-1579 makePlaceHolder : function ( ) { throw "Not implemented" } ,
-1580
-1581 /**
-1582 * Makes place-holder string.
-1583 *
-1584 * @returns {String} Platform specific place holder string
-1585 */
-1586 makePlaceHolderString : function ( ) { throw "Not implemented" } ,
-1587
-1588 /**
-1589 * Makes empty paragraph which contains only one place-holder
-1590 */
-1591 makeEmptyParagraph : function ( ) { throw "Not implemented" } ,
-1592
-1593 /**
-1594 * Applies background color to selected area
-1595 *
-1596 * @param {Object} color valid CSS color value
-1597 */
-1598 applyBackgroundColor : function ( color ) { throw "Not implemented" ; } ,
-1599
-1600 /**
-1601 * Applies foreground color to selected area
-1602 *
-1603 * @param {Object} color valid CSS color value
-1604 */
-1605 applyForegroundColor : function ( color ) {
-1606 this.execCommand ( "forecolor" , color ) ;
-1607 } ,
-1608
-1609 execCommand : function ( commandId , param ) { throw "Not implemented" ; } ,
-1610
-1611 applyRemoveFormat : function ( ) { throw "Not implemented" ; } ,
-1612 applyEmphasis : function ( ) { throw "Not implemented" ; } ,
-1613 applyStrongEmphasis : function ( ) { throw "Not implemented" ; } ,
-1614 applyStrike : function ( ) { throw "Not implemented" ; } ,
-1615 applyUnderline : function ( ) { throw "Not implemented" ; } ,
-1616 applySuperscription : function ( ) {
-1617 this.execCommand ( "superscript" ) ;
-1618 } ,
-1619 applySubscription : function ( ) {
-1620 this.execCommand ( "subscript" ) ;
-1621 } ,
-1622 indentBlock : function ( element , treatListAsNormalBlock ) {
-1623 return ( ! element.previousSibling && element.parentNode.nodeName == "LI" ) ?
-1624 this.indentListItem ( element , treatListAsNormalBlock ) :
-1625 this.indentElement ( element ) ;
-1626 } ,
-1627 outdentBlock : function ( element , treatListAsNormalBlock ) {
-1628 while ( true ) {
-1629 if ( ! element.previousSibling && element.parentNode.nodeName == "LI" ) {
-1630 element = this.outdentListItem ( element , treatListAsNormalBlock ) ;
-1631 return element ;
-1632 } else {
-1633 var performed = this.outdentElement ( element ) ;
-1634 if ( performed ) return performed ;
-1635
-1636 // first-child can outdent container
-1637 if ( ! element.previousSibling ) {
-1638 element = element.parentNode ;
-1639 } else {
-1640 break ;
-1641 }
-1642 }
-1643 }
-1644
-1645 return null ;
-1646 } ,
-1647 wrapBlock : function ( tag , start , end ) {
-1648 if ( ! this.tree._blockTags.include ( tag ) ) throw "Unsuppored block container: [" + tag + "]" ;
-1649 if ( ! start ) start = this.getCurrentBlockElement ( ) ;
-1650 if ( ! end ) end = start ;
-1651
-1652 // Check if the selection captures valid fragement
-1653 var validFragment = false ;
-1654
-1655 if ( start == end ) {
-1656 // are they same block?
-1657 validFragment = true ;
-1658 } else if ( start.parentNode == end.parentNode && ! start.previousSibling && ! end.nextSibling ) {
-1659 // are they covering whole parent?
-1660 validFragment = true ;
-1661 start = end = start.parentNode ;
-1662 } else {
-1663 // are they siblings of non-LI blocks?
-1664 validFragment =
-1665 ( start.parentNode == end.parentNode ) &&
-1666 ( start.nodeName != "LI" ) ;
-1667 }
-1668
-1669 if ( ! validFragment ) return null ;
-1670
-1671 var wrapper = this.createElement ( tag ) ;
-1672
-1673 if ( start == end ) {
-1674 // They are same.
-1675 if ( this.tree.isBlockContainer ( start ) && ! this.tree.isListContainer ( start ) ) {
-1676 // It's a block container. Wrap its contents.
-1677 if ( this.tree.isBlockOnlyContainer ( wrapper ) ) {
-1678 this.correctEmptyElement ( start ) ;
-1679 this.wrapAllInlineOrTextNodesAs ( "P" , start , true ) ;
-1680 }
-1681 this.moveChildNodes ( start , wrapper ) ;
-1682 start.appendChild ( wrapper ) ;
-1683 } else {
-1684 // It's not a block container. Wrap itself.
-1685 wrapper = this.insertNodeAt ( wrapper , start , "after" ) ;
-1686 wrapper.appendChild ( start ) ;
-1687 }
-1688
-1689 this.correctEmptyElement ( wrapper ) ;
-1690 } else {
-1691 // They are siblings. Wrap'em all.
-1692 wrapper = this.insertNodeAt ( wrapper , start , "before" ) ;
-1693 var node = start ;
-1694
-1695 while ( node != end ) {
-1696 next = node.nextSibling ;
-1697 wrapper.appendChild ( node ) ;
-1698 node = next ;
-1699 }
-1700 wrapper.appendChild ( node ) ;
-1701 }
-1702
-1703 return wrapper ;
-1704 } ,
-1705
-1706
-1707
-1708 /////////////////////////////////////////////
-1709 // Focus/Caret/Selection
-1710
-1711 /**
-1712 * Gives focus to root element's window
-1713 */
-1714 focus : function ( ) { throw "Not implemented" ; } ,
-1715
-1716 /**
-1717 * Returns selection object
-1718 */
-1719 sel : function ( ) { throw "Not implemented" ; } ,
-1720
-1721 /**
-1722 * Returns range object
-1723 */
-1724 rng : function ( ) { throw "Not implemented" ; } ,
-1725
-1726 /**
-1727 * Returns true if DOM has selection
-1728 */
-1729 hasSelection : function ( ) { throw "Not implemented" ; } ,
-1730
-1731 /**
-1732 * Returns true if root element's window has selection
-1733 */
-1734 hasFocus : function ( ) {
-1735 var cur = this.getCurrentElement ( ) ;
-1736 return ( cur && cur.ownerDocument == this.getDoc ( ) ) ;
-1737 } ,
-1738
-1739 /**
-1740 * Adjust scrollbar to make the element visible in current viewport.
-1741 *
-1742 * @param {Element} element Target element
-1743 * @param {boolean} toTop Align element to top of the viewport
-1744 * @param {boolean} moveCaret Move caret to the element
-1745 */
-1746 scrollIntoView : function ( element , toTop , moveCaret ) {
-1747 element.scrollIntoView ( toTop ) ;
-1748 if ( moveCaret ) this.placeCaretAtStartOf ( element ) ;
-1749 } ,
-1750
-1751 /**
-1752 * Select all document
-1753 */
-1754 selectAll : function ( ) {
-1755 return this.execCommand ( 'selectall' ) ;
-1756 } ,
-1757
-1758 /**
-1759 * Select specified element.
-1760 *
-1761 * @param {Element} element element to select
-1762 * @param {boolean} entireElement true to select entire element, false to select inner content of element
-1763 */
-1764 selectElement : function ( node , entireElement ) { throw "Not implemented" } ,
-1765
-1766 /**
-1767 * Select all elements between two blocks(inclusive).
-1768 *
-1769 * @param {Element} start start of selection
-1770 * @param {Element} end end of selection
-1771 */
-1772 selectBlocksBetween : function ( start , end ) { throw "Not implemented" } ,
-1773
-1774 /**
-1775 * Delete selected area
-1776 */
-1777 deleteSelection : function ( ) { throw "Not implemented" } ,
-1778
-1779 /**
-1780 * Collapses current selection.
-1781 *
-1782 * @param {boolean} toStart true to move caret to start of selected area.
-1783 */
-1784 collapseSelection : function ( toStart ) { throw "Not implemented" } ,
-1785
-1786 /**
-1787 * Returns selected area as HTML string
-1788 */
-1789 getSelectionAsHtml : function ( ) { throw "Not implemented" } ,
-1790
-1791 /**
-1792 * Returns selected area as text string
-1793 */
-1794 getSelectionAsText : function ( ) { throw "Not implemented" } ,
-1795
-1796 /**
-1797 * Places caret at start of the element
-1798 *
-1799 * @param {Element} element Target element
-1800 */
-1801 placeCaretAtStartOf : function ( element ) { throw "Not implemented" } ,
-1802
-1803 /**
-1804 * Checks if the node is empty-text-node or not
-1805 */
-1806 isEmptyTextNode : function ( node ) {
-1807 return node.nodeType == 3 && node.nodeValue.length == 0 ;
-1808 } ,
-1809
-1810 /**
-1811 * Checks if the caret is place in empty block element
-1812 */
-1813 isCaretAtEmptyBlock : function ( ) {
-1814 return this.isEmptyBlock ( this.getCurrentBlockElement ( ) ) ;
-1815 } ,
-1816
-1817 /**
-1818 * Checks if the caret is place at start of the block
-1819 */
-1820 isCaretAtBlockStart : function ( ) { throw "Not implemented" } ,
-1821
-1822 /**
-1823 * Checks if the caret is place at end of the block
-1824 */
-1825 isCaretAtBlockEnd : function ( ) { throw "Not implemented" } ,
-1826
-1827 /**
-1828 * Saves current selection info
-1829 *
-1830 * @returns {Object} Bookmark for selection
-1831 */
-1832 saveSelection : function ( ) { throw "Not implemented" } ,
-1833
-1834 /**
-1835 * Restores current selection info
-1836 *
-1837 * @param {Object} bookmark Bookmark
-1838 */
-1839 restoreSelection : function ( bookmark ) { throw "Not implemented" } ,
-1840
-1841 /**
-1842 * Create marker
-1843 */
-1844 createMarker : function ( ) {
-1845 var marker = this.createElement ( "SPAN" ) ;
-1846 marker.id = "xquared_marker_" + ( this._lastMarkerId ++ ) ;
-1847 marker.className = "xquared_marker" ;
-1848 return marker ;
-1849 } ,
-1850
-1851 /**
-1852 * Create and insert marker into current caret position.
-1853 * Marker is an inline element which has no child nodes. It can be used with many purposes.
-1854 * For example, You can push marker to mark current caret position.
-1855 *
-1856 * @returns {Element} marker
-1857 */
-1858 pushMarker : function ( ) {
-1859 var marker = this.createMarker ( ) ;
-1860 return this.insertNode ( marker ) ;
-1861 } ,
-1862
-1863 /**
-1864 * Removes last marker
-1865 *
-1866 * @params {boolean} moveCaret move caret into marker before delete.
-1867 */
-1868 popMarker : function ( moveCaret ) {
-1869 var id = "xquared_marker_" + ( -- this._lastMarkerId ) ;
-1870 var marker = this.$ ( id ) ;
-1871 if ( ! marker ) return ;
-1872
-1873 if ( moveCaret ) {
-1874 this.selectElement ( marker , true ) ;
-1875 this.collapseSelection ( false ) ;
-1876 }
-1877
-1878 this.deleteNode ( marker ) ;
-1879 } ,
-1880
-1881
-1882
-1883 /////////////////////////////////////////////
-1884 // Query methods
-1885
-1886 isMarker : function ( node ) {
-1887 return ( node.nodeType == 1 && node.nodeName == "SPAN" && node.className == "xquared_marker" ) ;
-1888 } ,
-1889
-1890 isFirstBlockOfBody : function ( block ) {
-1891 var root = this.getRoot ( ) ;
-1892 var found = this.tree.findBackward (
-1893 block ,
-1894 function ( node ) { return ( node == root ) || node.previousSibling ; } . bind ( this )
-1895 ) ;
-1896
-1897 return found == root ;
-1898 } ,
-1899
-1900 /**
-1901 * Returns outer HTML of given element
-1902 */
-1903 getOuterHTML : function ( element ) { throw "Not implemented" } ,
-1904
-1905 /**
-1906 * Returns inner text of given element
-1907 *
-1908 * @param {Element} element Target element
-1909 * @returns {String} Text string
-1910 */
-1911 getInnerText : function ( element ) {
-1912 return element.innerHTML.stripTags ( ) ;
-1913 } ,
-1914
-1915 /**
-1916 * Checks if given node is place holder or not.
-1917 *
-1918 * @param {Node} node DOM node
-1919 */
-1920 isPlaceHolder : function ( node ) { throw "Not implemented" } ,
-1921
-1922 /**
-1923 * Checks if given block is the first LI whose next sibling is a nested list.
-1924 *
-1925 * @param {Element} block Target block
-1926 */
-1927 isFirstLiWithNestedList : function ( block ) {
-1928 return ! block.previousSibling &&
-1929 block.parentNode.nodeName == "LI" &&
-1930 this.tree.isListContainer ( block.nextSibling ) ;
-1931 } ,
-1932
-1933 /**
-1934 * Search all links within given element
-1935 *
-1936 * @param {Element} [element] Container element. If not given, the root element will be used.
-1937 * @param {Array} [found] if passed, links will be appended into this array.
-1938 * @returns {Array} Array of anchors. It returns empty array if there's no links.
-1939 */
-1940 searchAnchors : function ( element , found ) {
-1941 if ( ! element ) element = this.getRoot ( ) ;
-1942 if ( ! found ) found = [ ] ;
-1943
-1944 var anchors = element.getElementsByTagName ( "A" ) ;
-1945 for ( var i = 0 ; i < anchors.length ; i ++ ) {
-1946 found.push ( anchors [ i ] ) ;
-1947 }
-1948
-1949 return found ;
-1950 } ,
-1951
-1952 /**
-1953 * Search all headings within given element
-1954 *
-1955 * @param {Element} [element] Container element. If not given, the root element will be used.
-1956 * @param {Array} [found] if passed, headings will be appended into this array.
-1957 * @returns {Array} Array of headings. It returns empty array if there's no headings.
-1958 */
-1959 searchHeadings : function ( element , found ) {
-1960 if ( ! element ) element = this.getRoot ( ) ;
-1961 if ( ! found ) found = [ ] ;
-1962
-1963 var regexp = /^h[1-6]/ig ;
-1964
-1965 if ( ! element.childNodes ) return [ ] ;
-1966 $A ( element.childNodes ) . each ( function ( child ) {
-1967 var isContainer = child && this.tree._blockContainerTags.include ( child.nodeName ) ;
-1968 var isHeading = child && child.nodeName.match ( regexp ) ;
-1969
-1970 if ( isContainer ) {
-1971 this.searchHeadings ( child , found ) ;
-1972 } else if ( isHeading ) {
-1973 found.push ( child ) ;
-1974 }
-1975 } . bind ( this ) ) ;
-1976
-1977 return found ;
-1978 } ,
-1979
-1980 /**
-1981 * Collect structure and style informations of given element.
-1982 *
-1983 * @param {Element} element target element
-1984 * @returns {Object} object that contains information: {em: true, strong: false, block: "p", list: "ol", ...}
-1985 */
-1986 collectStructureAndStyle : function ( element ) {
-1987 if ( ! element || element.nodeName == "#document" ) return { } ;
-1988
-1989 var block = this.getParentBlockElementOf ( element ) ;
-1990 var parents = this.tree.collectParentsOf ( element , true , function ( node ) { return block.parentNode == node } ) ;
-1991 var blockName = block.nodeName ;
-1992
-1993 var info = { } ;
-1994
-1995 var doc = this.getDoc ( ) ;
-1996 var em = doc.queryCommandState ( "Italic" ) ;
-1997 var strong = doc.queryCommandState ( "Bold" ) ;
-1998 var strike = doc.queryCommandState ( "Strikethrough" ) ;
-1999 var underline = doc.queryCommandState ( "Underline" ) && ! this.getParentElementOf ( element , [ "A" ] ) ;
-2000 var superscription = doc.queryCommandState ( "superscript" ) ;
-2001 var subscription = doc.queryCommandState ( "subscript" ) ;
-2002
-2003 // if block is only child, select its parent
-2004 while ( block.parentNode && block.parentNode != this.getRoot ( ) && ! block.previousSibling && ! block.nextSibling && ! this.tree.isListContainer ( block.parentNode ) ) {
-2005 block = block.parentNode ;
-2006 }
-2007
-2008 var list = false ;
-2009 if ( block.nodeName == "LI" ) {
-2010 var parent = block.parentNode ;
-2011 var isCode = parent.nodeName == "OL" && parent.className == "code" ;
-2012 list = isCode ? "CODE" : parent.nodeName ;
-2013 }
-2014
-2015 var justification = block.style.textAlign || "left" ;
-2016
-2017 return {
-2018 block : blockName ,
-2019 em : em ,
-2020 strong : strong ,
-2021 strike : strike ,
-2022 underline : underline ,
-2023 superscription : superscription ,
-2024 subscription : subscription ,
-2025 list : list ,
-2026 justification : justification
-2027 } ;
-2028 } ,
-2029
-2030 /**
-2031 * Find elements by CSS selector.
-2032 *
-2033 * WARNING: Use this method carefully since prototype.js doesn't work well with designMode DOM.
-2034 */
-2035 findBySelector : function ( selector ) {
-2036 return Element.getElementsBySelector ( this.root , selector ) ;
-2037 } ,
-2038
-2039 /**
-2040 * Find elements by attribute.
-2041 *
-2042 * This method will be deprecated when findBySelector get stabilized.
-2043 */
-2044 findByAttribute : function ( name , value ) {
-2045 var nodes = [ ] ;
-2046 this._findByAttribute ( nodes , this.root , name , value ) ;
-2047 return nodes ;
-2048 } ,
-2049
-2050 /** @private */
-2051 _findByAttribute : function ( nodes , element , name , value ) {
-2052 if ( element.getAttribute ( name ) == value ) nodes.push ( element ) ;
-2053 if ( ! element.hasChildNodes ( ) ) return ;
-2054
-2055 var children = element.childNodes ;
-2056 for ( var i = 0 ; i < children.length ; i ++ ) {
-2057 if ( children [ i ] . nodeType == 1 ) this._findByAttribute ( nodes , children [ i ] , name , value ) ;
-2058 }
-2059 } ,
-2060
-2061 /**
-2062 * Checks if the element has one or more important attributes: id, class, style
-2063 *
-2064 * @param {Element} element Target element
-2065 */
-2066 hasImportantAttributes : function ( element ) { throw "Not implemented" } ,
-2067
-2068 /**
-2069 * Checks if the element is empty or not. Place-holder is not counted as a child.
-2070 *
-2071 * @param {Element} element Target element
-2072 */
-2073 isEmptyBlock : function ( element ) { throw "Not implemented" } ,
-2074
-2075 /**
-2076 * Returns element that contains caret.
-2077 */
-2078 getCurrentElement : function ( ) { throw "Not implemented" } ,
-2079
-2080 /**
-2081 * Returns block element that contains caret.
-2082 */
-2083 getCurrentBlockElement : function ( ) {
-2084 var cur = this.getCurrentElement ( ) ;
-2085 if ( ! cur ) return null ;
-2086
-2087 var block = this.getParentBlockElementOf ( cur ) ;
-2088 if ( ! block ) return null ;
-2089
-2090 return ( block.nodeName == "BODY" ) ? null : block ;
-2091 } ,
-2092
-2093 /**
-2094 * Returns parent block element of parameter.
-2095 * If the parameter itself is a block, it will be returned.
-2096 *
-2097 * @param {Element} element Target element
-2098 *
-2099 * @returns {Element} Element or null
-2100 */
-2101 getParentBlockElementOf : function ( element ) {
-2102 while ( element ) {
-2103 if ( this.tree._blockTags.include ( element.nodeName ) ) return element ;
-2104 element = element.parentNode ;
-2105 }
-2106 return null ;
-2107 } ,
-2108
-2109 /**
-2110 * Returns parent element of parameter which has one of given tag name.
-2111 * If the parameter itself has the same tag name, it will be returned.
-2112 *
-2113 * @param {Element} element Target element
-2114 * @param {Array} tagNames Array of string which contains tag names
-2115 *
-2116 * @returns {Element} Element or null
-2117 */
-2118 getParentElementOf : function ( element , tagNames ) {
-2119 while ( element ) {
-2120 if ( tagNames.include ( element.nodeName ) ) return element ;
-2121 element = element.parentNode ;
-2122 }
-2123 return null ;
-2124 } ,
-2125
-2126 /**
-2127 * Collects all block elements between two elements
-2128 *
-2129 * @param {Element} from Start element(inclusive)
-2130 * @param {Element} to End element(inclusive)
-2131 */
-2132 getBlockElementsBetween : function ( from , to ) {
-2133 return this.tree.collectNodesBetween ( from , to , function ( node ) {
-2134 return node.nodeType == 1 && this.tree.isBlock ( node ) ;
-2135 } . bind ( this ) ) ;
-2136 } ,
-2137
-2138 /**
-2139 * Returns block element that contains selection start.
-2140 *
-2141 * This method will return exactly same result with getCurrentBlockElement method
-2142 * when there's no selection.
-2143 */
-2144 getBlockElementAtSelectionStart : function ( ) { throw "Not implemented" } ,
-2145
-2146 /**
-2147 * Returns block element that contains selection end.
-2148 *
-2149 * This method will return exactly same result with getCurrentBlockElement method
-2150 * when there's no selection.
-2151 */
-2152 getBlockElementAtSelectionEnd : function ( ) { throw "Not implemented" } ,
-2153
-2154 /**
-2155 * Returns blocks at each edge of selection(start and end).
-2156 *
-2157 * TODO: implement ignoreEmptyEdges for FF
-2158 *
-2159 * @param {boolean} naturalOrder Mak the start element always comes before the end element
-2160 * @param {boolean} ignoreEmptyEdges Prevent some browser(Gecko) from selecting one more block than expected
-2161 */
-2162 getBlockElementsAtSelectionEdge : function ( naturalOrder , ignoreEmptyEdges ) { throw "Not implemented" } ,
-2163
-2164 /**
-2165 * Returns array of selected block elements
-2166 */
-2167 getSelectedBlockElements : function ( ) {
-2168 var selectionEdges = this.getBlockElementsAtSelectionEdge ( true , true ) ;
-2169 var start = selectionEdges [ 0 ] ;
-2170 var end = selectionEdges [ 1 ] ;
-2171
-2172 return this.tree.collectNodesBetween ( start , end , function ( node ) {
-2173 return node.nodeType == 1 && this.tree.isBlock ( node ) ;
-2174 } . bind ( this ) ) ;
-2175 } ,
-2176
-2177 /**
-2178 * Get element by ID
-2179 *
-2180 * @param {String} id Element's ID
-2181 * @returns {Element} element or null
-2182 */
-2183 getElementById : function ( id ) { return this.doc.getElementById ( id ) } ,
-2184
-2185 /**
-2186 * Shortcut for #getElementById
-2187 */
-2188 $ : function ( id ) { return this.getElementById ( id ) } ,
-2189
-2190 /**
-2191 * Returns first "valid" child of given element. It ignores empty textnodes.
-2192 *
-2193 * @param {Element} element Target element
-2194 * @returns {Node} first child node or null
-2195 */
-2196 getFirstChild : function ( element ) {
-2197 if ( ! element ) return null ;
-2198
-2199 var nodes = $A ( element.childNodes ) ;
-2200 for ( var i = 0 ; i < nodes.length ; i ++ ) {
-2201 if ( ! this.isEmptyTextNode ( nodes [ i ] ) ) return nodes [ i ] ;
-2202 }
-2203 return null ;
-2204 } ,
-2205
-2206 /**
-2207 * Returns last "valid" child of given element. It ignores empty textnodes and place-holders.
-2208 *
-2209 * @param {Element} element Target element
-2210 * @returns {Node} last child node or null
-2211 */
-2212 getLastChild : function ( element ) { throw "Not implemented" } ,
-2213
-2214 getNextSibling : function ( node ) {
-2215 while ( node = node.nextSibling ) {
-2216 if ( node.nodeType != 3 || node.nodeValue.strip ( ) != "" ) break ;
-2217 }
-2218 return node ;
-2219 } ,
-2220
-2221 getBottommostFirstChild : function ( node ) {
-2222 while ( node.firstChild && node.nodeType == 1 ) node = node.firstChild ;
-2223 return node ;
-2224 } ,
-2225
-2226 getBottommostLastChild : function ( node ) {
-2227 while ( node.lastChild && node.nodeType == 1 ) node = node.lastChild ;
-2228 return node ;
-2229 } ,
-2230
-2231 /** @private */
-2232 _getCssValue : function ( str , defaultUnit ) {
-2233 if ( ! str || str.length == 0 ) return { value : 0 , unit : defaultUnit } ;
-2234
-2235 var tokens = str.match ( /(\d+)(.*)/ ) ;
-2236 return {
-2237 value : parseInt ( tokens [ 1 ] ) ,
-2238 unit : tokens [ 2 ] || defaultUnit
-2239 } ;
-2240 }
-2241 } ) ;
-2242
-2243 /**
-2244 * Creates and returns instance of browser specific implementation.
-2245 */
-2246 xq.RichDom.createInstance = function ( ) {
-2247 if ( xq.Browser.isTrident ) {
-2248 return new xq.RichDomTrident ( ) ;
-2249 } else if ( xq.Browser.isWebkit ) {
-2250 return new xq.RichDomWebkit ( ) ;
-2251 } else {
-2252 return new xq.RichDomGecko ( ) ;
-2253 }
-2254 }
-2255
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_07.html b/modules/editor/skins/xquared/doc/api/src_07.html
deleted file mode 100644
index 6b89ca0d2..000000000
--- a/modules/editor/skins/xquared/doc/api/src_07.html
+++ /dev/null
@@ -1,54 +0,0 @@
- 1 /**
- 2 * RichDom for Gecko
- 3 */
- 4 xq.RichDomGecko = Class.create ( xq.RichDomW3 , {
- 5 makePlaceHolder : function ( ) {
- 6 var holder = this.createElement ( "BR" ) ;
- 7 holder.setAttribute ( "type" , "_moz" ) ;
- 8 return holder ;
- 9 } ,
- 10
- 11 makePlaceHolderString : function ( ) {
- 12 return '<br type="_moz" />' ;
- 13 } ,
- 14
- 15 makeEmptyParagraph : function ( ) {
- 16 return this.createElementFromHtml ( '<p><br type="_moz" /></p>' ) ;
- 17 } ,
- 18
- 19 isPlaceHolder : function ( node ) {
- 20 if ( node.nodeType != 1 ) return false ;
- 21
- 22 var typeMatches = node.nodeName == "BR" && node.getAttribute ( "type" ) == "_moz" ;
- 23 if ( typeMatches ) return true ;
- 24
- 25 var positionMatches = node.nodeName == "BR" && ! this.getNextSibling ( node ) ;
- 26 if ( positionMatches ) return true ;
- 27
- 28 return false ;
- 29 } ,
- 30
- 31 selectElement : function ( element , entireElement ) {
- 32 if ( ! element ) throw "[element] is null" ;
- 33 if ( element.nodeType != 1 ) throw "[element] is not an element" ;
- 34
- 35 // required to avoid Windows FF selection bug.
- 36 try {
- 37 if ( ! xq.Browser.isMac ) this.doc.execCommand ( "SelectAll" , false , null ) ;
- 38 } catch ( ignored ) { }
- 39
- 40 if ( entireElement ) {
- 41 this.rng ( ) . selectNode ( element ) ;
- 42 } else {
- 43 this.rng ( ) . selectNodeContents ( element ) ;
- 44 }
- 45 }
- 46 } ) ;
- 47
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_08.html b/modules/editor/skins/xquared/doc/api/src_08.html
deleted file mode 100644
index ce19b8514..000000000
--- a/modules/editor/skins/xquared/doc/api/src_08.html
+++ /dev/null
@@ -1,369 +0,0 @@
- 1 /**
- 2 * RichDom for Internet Explorer 6 and 7
- 3 */
- 4 xq.RichDomTrident = Class.create ( xq.RichDom , {
- 5 makePlaceHolder : function ( ) {
- 6 return this.createTextNode ( " " ) ;
- 7 } ,
- 8
- 9 makePlaceHolderString : function ( ) {
- 10 return ' ' ;
- 11 } ,
- 12
- 13 makeEmptyParagraph : function ( ) {
- 14 return this.createElementFromHtml ( "<p> </p>" ) ;
- 15 } ,
- 16
- 17 isPlaceHolder : function ( node ) {
- 18 return false ;
- 19 } ,
- 20
- 21 getOuterHTML : function ( element ) {
- 22 return element.outerHTML ;
- 23 } ,
- 24
- 25 insertNode : function ( node ) {
- 26 if ( this.hasSelection ( ) ) this.collapseSelection ( true ) ;
- 27
- 28 this.rng ( ) . pasteHTML ( '<span id="xquared_temp"></span>' ) ;
- 29 var marker = this.$ ( 'xquared_temp' ) ;
- 30 if ( node.id == 'xquared_temp' ) return marker ;
- 31
- 32 marker.replaceNode ( node ) ;
- 33 return node ;
- 34 } ,
- 35
- 36 removeTrailingWhitespace : function ( block ) {
- 37 if ( ! block ) return ;
- 38
- 39 // TODO: reimplement to handle atomic tags and so on. (use DomTree)
- 40 if ( this.tree.isBlockContainer ( block ) ) return ;
- 41 if ( this.isEmptyBlock ( block ) ) return ;
- 42
- 43 var text = block.innerText ;
- 44 var lastCharCode = text.charCodeAt ( text.length - 1 ) ;
- 45 if ( text.length <= 1 || ! [ 32 , 160 ] . include ( lastCharCode ) ) return ;
- 46
- 47 var node = block ;
- 48
- 49 while ( node && node.nodeType != 3 ) node = node.lastChild ;
- 50
- 51 if ( ! node ) return ;
- 52
- 53 // DO NOT REMOVE OR MODIFY FOLLOWING CODE:
- 54 //
- 55 // Modifying following code crash IE7
- 56 var nodeValue = node.nodeValue ;
- 57 if ( nodeValue.length <= 1 ) {
- 58 this.deleteNode ( node , true ) ;
- 59 } else {
- 60 node.nodeValue = nodeValue.substring ( 0 , nodeValue.length - 1 ) ;
- 61 }
- 62 } ,
- 63
- 64 correctEmptyElement : function ( element ) {
- 65 if ( ! element || element.nodeType != 1 || this.tree.isAtomic ( element ) ) return ;
- 66
- 67 if ( element.firstChild ) {
- 68 this.correctEmptyElement ( element.firstChild ) ;
- 69 } else {
- 70 element.innerHTML = " " ;
- 71 }
- 72 } ,
- 73
- 74 copyAttributes : function ( from , to , copyId ) {
- 75 to.mergeAttributes ( from , ! copyId ) ;
- 76 } ,
- 77
- 78 correctParagraph : function ( ) {
- 79 if ( ! this.hasFocus ( ) ) return false ;
- 80 if ( this.hasSelection ( ) ) return false ;
- 81
- 82 var block = this.getCurrentElement ( ) ;
- 83
- 84 if ( block.nodeName == "BODY" ) {
- 85 // check for atomic block element such as HR
- 86 block = this.insertNode ( this.makeEmptyParagraph ( ) ) ;
- 87 var next = block.nextSibling ;
- 88 if ( this.tree.isAtomic ( next ) ) {
- 89 block = this.insertNodeAt ( block , next , "after" ) ;
- 90 this.placeCaretAtStartOf ( block ) ;
- 91
- 92 var nextBlock = this.tree.findForward (
- 93 block ,
- 94 function ( node ) { return this.tree.isBlock ( node ) && ! this.tree.isBlockOnlyContainer ( node ) } . bind ( this )
- 95 ) ;
- 96 if ( nextBlock ) {
- 97 this.deleteNode ( block ) ;
- 98 this.placeCaretAtStartOf ( nextBlock ) ;
- 99 }
-100 return true ;
-101 } else {
-102 var nextBlock = this.tree.findForward (
-103 block ,
-104 function ( node ) { return this.tree.isBlock ( node ) && ! this.tree.isBlockOnlyContainer ( node ) } . bind ( this )
-105 ) ;
-106 if ( nextBlock ) {
-107 this.deleteNode ( block ) ;
-108 this.placeCaretAtStartOf ( nextBlock ) ;
-109 }
-110 return true ;
-111 }
-112 } else {
-113 block = this.getCurrentBlockElement ( ) ;
-114 if ( block.nodeType == 3 ) block = block.parentNode ;
-115
-116 if ( this.tree.hasMixedContents ( block ) ) {
-117 var marker = this.pushMarker ( ) ;
-118 this.wrapAllInlineOrTextNodesAs ( "P" , block , true ) ;
-119 this.popMarker ( true ) ;
-120 return true ;
-121 } else if ( ( this.tree.isTextOrInlineNode ( block.previousSibling ) || this.tree.isTextOrInlineNode ( block.nextSibling ) ) && this.tree.hasMixedContents ( block.parentNode ) ) {
-122 // IE?서??Block?Inline/Text??접??경우 getCurrentElement ?이 ?작?한??
-123 // ?라???재 Block 주?까? ?번???아주어???다.
-124 this.wrapAllInlineOrTextNodesAs ( "P" , block.parentNode , true ) ;
-125 return true ;
-126 } else {
-127 return false ;
-128 }
-129 }
-130 } ,
-131
-132
-133
-134 //////
-135 // Commands
-136 execCommand : function ( commandId , param ) {
-137 return this.doc.execCommand ( commandId , false , param ) ;
-138 } ,
-139
-140 applyBackgroundColor : function ( color ) {
-141 this.execCommand ( "BackColor" , color ) ;
-142 } ,
-143
-144 applyEmphasis : function ( ) {
-145 // Generate <i> tag. It will be replaced with <emphasis> tag during cleanup phase.
-146 this.execCommand ( "Italic" ) ;
-147 } ,
-148 applyStrongEmphasis : function ( ) {
-149 // Generate <b> tag. It will be replaced with <strong> tag during cleanup phase.
-150 this.execCommand ( "Bold" ) ;
-151 } ,
-152 applyStrike : function ( ) {
-153 // Generate <strike> tag. It will be replaced with <style class="strike"> tag during cleanup phase.
-154 this.execCommand ( "strikethrough" ) ;
-155 } ,
-156 applyUnderline : function ( ) {
-157 // Generate <u> tag. It will be replaced with <em class="underline"> tag during cleanup phase.
-158 this.execCommand ( "underline" ) ;
-159 } ,
-160 applyRemoveFormat : function ( ) {
-161 this.execCommand ( "RemoveFormat" ) ;
-162 this.execCommand ( "Unlink" ) ;
-163 } ,
-164 execHeading : function ( level ) {
-165 this.execCommand ( "FormatBlock" , "<H" + level + ">" ) ;
-166 } ,
-167
-168
-169
-170 //////
-171 // Focus/Caret/Selection
-172
-173 focus : function ( ) {
-174 this.win.focus ( ) ;
-175
-176 // ?게 ?으?초기??caret??P 밖에 ?치?면?? // getCurrentElement??면 P?리턴?는 기이???상??발생.
-177 if ( ! this._focusedBefore ) {
-178 this.correctParagraph ( ) ;
-179 this.placeCaretAtStartOf ( this.getCurrentBlockElement ( ) ) ;
-180 this._focusedBefore = true ;
-181 }
-182 } ,
-183
-184 sel : function ( ) {
-185 return this.doc.selection ;
-186 } ,
-187
-188 rng : function ( ) {
-189 try {
-190 var sel = this.sel ( ) ;
-191 return ( sel == null ) ? null : sel.createRange ( ) ;
-192 } catch ( ignored ) {
-193 // IE often fails
-194 return null ;
-195 }
-196 } ,
-197
-198 hasSelection : function ( ) {
-199 var selectionType = this.sel ( ) . type.toLowerCase ( ) ;
-200 if ( "none" == selectionType ) return false ;
-201 if ( "text" == selectionType && this.getSelectionAsHtml ( ) . length == 0 ) return false ;
-202 return true ;
-203 } ,
-204 deleteSelection : function ( ) {
-205 if ( this.getSelectionAsText ( ) != "" ) this.sel ( ) . clear ( ) ;
-206 } ,
-207
-208 placeCaretAtStartOf : function ( element ) {
-209 // If there's no empty span, caret sometimes moves into a previous node.
-210 var ph = this.insertNodeAt ( this.createElement ( "SPAN" ) , element , "start" ) ;
-211 this.selectElement ( ph ) ;
-212 this.collapseSelection ( false ) ;
-213 this.deleteNode ( ph ) ;
-214 } ,
-215
-216 selectElement : function ( element , entireElement ) {
-217 if ( ! element ) throw "[element] is null" ;
-218 if ( element.nodeType != 1 ) throw "[element] is not an element" ;
-219
-220 var rng = this.rng ( ) ;
-221 rng.moveToElementText ( element ) ;
-222 rng.select ( ) ;
-223 } ,
-224
-225 selectBlocksBetween : function ( start , end ) {
-226 var rng = this.rng ( ) ;
-227 var rngTemp = this.rng ( ) ;
-228
-229 rngTemp.moveToElementText ( start ) ;
-230 rng.setEndPoint ( "StartToStart" , rngTemp ) ;
-231
-232 rngTemp.moveToElementText ( end ) ;
-233 rng.setEndPoint ( "EndToEnd" , rngTemp ) ;
-234
-235 rng.select ( ) ;
-236 } ,
-237
-238 collapseSelection : function ( toStart ) {
-239 var rng = this.rng ( ) ;
-240 rng.collapse ( toStart ) ;
-241 rng.select ( ) ;
-242 } ,
-243
-244 getSelectionAsHtml : function ( ) {
-245 var rng = this.rng ( )
-246 return rng && rng.htmlText ? rng.htmlText : ""
-247 } ,
-248
-249 getSelectionAsText : function ( ) {
-250 var rng = this.rng ( ) ;
-251 return rng && rng.text ? rng.text : "" ;
-252 } ,
-253
-254 hasImportantAttributes : function ( element ) {
-255 return ! ! ( element.id || element.className || element.style.cssText ) ;
-256 } ,
-257
-258 isEmptyBlock : function ( element ) {
-259 if ( ! element.hasChildNodes ( ) ) return true ;
-260 if ( element.nodeType == 3 && ! element.nodeValue ) return true ;
-261 if ( [ " " , " " , "" ] . include ( element.innerHTML ) ) return true ;
-262
-263 return false ;
-264 } ,
-265
-266 getLastChild : function ( element ) {
-267 if ( ! element || ! element.hasChildNodes ( ) ) return null ;
-268
-269 var nodes = $A ( element.childNodes ) . reverse ( ) ;
-270
-271 for ( var i = 0 ; i < nodes.length ; i ++ ) {
-272 if ( nodes [ i ] . nodeType != 3 || nodes [ i ] . nodeValue.length != 0 ) return nodes [ i ] ;
-273 }
-274
-275 return null ;
-276 } ,
-277
-278 getCurrentElement : function ( ) {
-279 if ( this.sel ( ) . type.toLowerCase ( ) == "control" ) return this.rng ( ) . item ( 0 ) ;
-280 return this.rng ( ) . parentElement ( ) ;
-281 } ,
-282
-283 getBlockElementAtSelectionStart : function ( ) {
-284 var rng = this.rng ( ) ;
-285 var dup = rng.duplicate ( ) ;
-286 dup.collapse ( true ) ;
-287
-288 var result = this.getParentBlockElementOf ( dup.parentElement ( ) ) ;
-289 if ( result.nodeName == "BODY" ) result = result.firstChild ;
-290
-291 return result ;
-292 } ,
-293
-294 getBlockElementAtSelectionEnd : function ( ) {
-295 var rng = this.rng ( ) ;
-296 var dup = rng.duplicate ( ) ;
-297 dup.collapse ( false ) ;
-298
-299 var result = this.getParentBlockElementOf ( dup.parentElement ( ) ) ;
-300 if ( result.nodeName == "BODY" ) result = result.lastChild ;
-301
-302 return result ;
-303 } ,
-304
-305 getBlockElementsAtSelectionEdge : function ( naturalOrder , ignoreEmptyEdges ) {
-306 return [
-307 this.getBlockElementAtSelectionStart ( ) ,
-308 this.getBlockElementAtSelectionEnd ( )
-309 ] ;
-310 } ,
-311
-312 isCaretAtBlockStart : function ( ) {
-313 if ( this.isCaretAtEmptyBlock ( ) ) return true ;
-314 if ( this.hasSelection ( ) ) return false ;
-315 var node = this.getCurrentBlockElement ( ) ;
-316 var marker = this.pushMarker ( ) ;
-317
-318 var isTrue = false ;
-319 while ( node = this.getFirstChild ( node ) ) {
-320 if ( node == marker ) {
-321 isTrue = true ;
-322 break ;
-323 }
-324 }
-325
-326 this.popMarker ( ) ;
-327
-328 return isTrue ;
-329 } ,
-330 isCaretAtBlockEnd : function ( ) {
-331 if ( this.isCaretAtEmptyBlock ( ) ) return true ;
-332 if ( this.hasSelection ( ) ) return false ;
-333 var node = this.getCurrentBlockElement ( ) ;
-334 var marker = this.pushMarker ( ) ;
-335 var isTrue = false ;
-336 while ( node = this.getLastChild ( node ) ) {
-337 var nodeValue = node.nodeValue ;
-338
-339 if ( node == marker ) {
-340 isTrue = true ;
-341 break ;
-342 } else if (
-343 node.nodeType == 3 &&
-344 node.previousSibling == marker &&
-345 ( nodeValue == " " || ( nodeValue.length == 1 && nodeValue.charCodeAt ( 0 ) == 160 ) )
-346 ) {
-347 isTrue = true ;
-348 break ;
-349 }
-350 }
-351
-352 this.popMarker ( ) ;
-353 return isTrue ;
-354 } ,
-355 saveSelection : function ( ) {
-356 return this.rng ( ) ;
-357 } ,
-358 restoreSelection : function ( bookmark ) {
-359 bookmark.select ( ) ;
-360 }
-361 } ) ;
-362
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_09.html b/modules/editor/skins/xquared/doc/api/src_09.html
deleted file mode 100644
index 030d7b252..000000000
--- a/modules/editor/skins/xquared/doc/api/src_09.html
+++ /dev/null
@@ -1,382 +0,0 @@
- 1 /**
- 2 * RichDom for W3C Standard Engine
- 3 */
- 4 xq.RichDomW3 = Class.create ( xq.RichDom , {
- 5 insertNode : function ( node ) {
- 6 var rng = this.rng ( ) ;
- 7 rng.insertNode ( node ) ;
- 8 rng.selectNode ( node ) ;
- 9 rng.collapse ( false ) ;
- 10 return node ;
- 11 } ,
- 12
- 13 removeTrailingWhitespace : function ( block ) {
- 14 // TODO: do nothing
- 15 } ,
- 16
- 17 getOuterHTML : function ( element ) {
- 18 var div = element.ownerDocument.createElement ( "div" ) ;
- 19 div.appendChild ( element.cloneNode ( true ) ) ;
- 20 return div.innerHTML ;
- 21 } ,
- 22
- 23 correctEmptyElement : function ( element ) {
- 24 if ( ! element || element.nodeType != 1 || this.tree.isAtomic ( element ) ) return ;
- 25
- 26 if ( element.firstChild )
- 27 this.correctEmptyElement ( element.firstChild ) ;
- 28 else
- 29 element.appendChild ( this.makePlaceHolder ( ) ) ;
- 30 } ,
- 31
- 32 correctParagraph : function ( ) {
- 33 if ( this.hasSelection ( ) ) return false ;
- 34
- 35 var block = this.getCurrentElement ( ) ;
- 36 var modified = false ;
- 37
- 38 if ( this.tree.isBlockOnlyContainer ( block ) ) {
- 39 this.execCommand ( "InsertParagraph" ) ;
- 40
- 41 // check for atomic block element such as HR
- 42 var newBlock = this.getCurrentElement ( ) ;
- 43 if ( this.tree.isAtomic ( newBlock.previousSibling ) ) {
- 44 var nextBlock = this.tree.findForward (
- 45 newBlock ,
- 46 function ( node ) { return this.tree.isBlock ( node ) && ! this.tree.isBlockOnlyContainer ( node ) } . bind ( this )
- 47 ) ;
- 48 if ( nextBlock ) {
- 49 this.deleteNode ( newBlock ) ;
- 50 this.placeCaretAtStartOf ( nextBlock ) ;
- 51 }
- 52 }
- 53 modified = true ;
- 54 } else if ( this.tree.hasMixedContents ( block ) ) {
- 55 this.wrapAllInlineOrTextNodesAs ( "P" , block , true ) ;
- 56 modified = true ;
- 57 }
- 58
- 59 block = this.getCurrentElement ( ) ;
- 60 if ( this.tree.isBlock ( block ) && ! this._hasPlaceHolderAtEnd ( block ) ) {
- 61 block.appendChild ( this.makePlaceHolder ( ) ) ;
- 62 modified = true ;
- 63 }
- 64
- 65 if ( this.tree.isBlock ( block ) ) {
- 66 var parentsLastChild = block.parentNode.lastChild ;
- 67 if ( this.isPlaceHolder ( parentsLastChild ) ) {
- 68 this.deleteNode ( parentsLastChild ) ;
- 69 modified = true ;
- 70 }
- 71 }
- 72
- 73 return modified ;
- 74 } ,
- 75
- 76 _hasPlaceHolderAtEnd : function ( block ) {
- 77 if ( ! block.hasChildNodes ( ) ) return false ;
- 78 return this.isPlaceHolder ( block.lastChild ) || this._hasPlaceHolderAtEnd ( block.lastChild ) ;
- 79 } ,
- 80
- 81 applyBackgroundColor : function ( color ) {
- 82 this.execCommand ( "styleWithCSS" , "true" ) ;
- 83 this.execCommand ( "hilitecolor" , color ) ;
- 84 this.execCommand ( "styleWithCSS" , "false" ) ;
- 85
- 86 // 0. Save current selection
- 87 var bookmark = this.saveSelection ( ) ;
- 88
- 89 // 1. Get selected blocks
- 90 var blocks = this.getSelectedBlockElements ( ) ;
- 91 if ( blocks.length == 0 ) return ;
- 92
- 93 // 2. Apply background-color to all adjust inline elements
- 94 // 3. Remove background-color from blocks
- 95 for ( var i = 0 ; i < blocks.length ; i ++ ) {
- 96 if ( ( i == 0 || i == blocks.length - 1 ) && ! blocks [ i ] . style.backgroundColor ) continue ;
- 97
- 98 var spans = this.wrapAllInlineOrTextNodesAs ( "SPAN" , blocks [ i ] , true ) ;
- 99 for ( var j = 0 ; j < spans.length ; j ++ ) {
-100 spans [ j ] . style.backgroundColor = color ;
-101 }
-102 blocks [ i ] . style.backgroundColor = "" ;
-103 }
-104
-105 // 4. Restore selection
-106 this.restoreSelection ( bookmark ) ;
-107 } ,
-108
-109
-110
-111
-112 //////
-113 // Commands
-114 execCommand : function ( commandId , param ) {
-115 return this.doc.execCommand ( commandId , false , param || null ) ;
-116 } ,
-117
-118 saveSelection : function ( ) {
-119 var rng = this.rng ( ) ;
-120 return [ rng.startContainer , rng.startOffset , rng.endContainer , rng.endOffset ] ;
-121 } ,
-122
-123 restoreSelection : function ( bookmark ) {
-124 var rng = this.rng ( ) ;
-125 rng.setStart ( bookmark [ 0 ] , bookmark [ 1 ] ) ;
-126 rng.setEnd ( bookmark [ 2 ] , bookmark [ 3 ] ) ;
-127 } ,
-128
-129 applyRemoveFormat : function ( ) {
-130 this.execCommand ( "RemoveFormat" ) ;
-131 this.execCommand ( "Unlink" ) ;
-132 } ,
-133 applyEmphasis : function ( ) {
-134 // Generate <i> tag. It will be replaced with <emphasis> tag during cleanup phase.
-135 this.execCommand ( "styleWithCSS" , "false" ) ;
-136 this.execCommand ( "italic" ) ;
-137 } ,
-138 applyStrongEmphasis : function ( ) {
-139 // Generate <b> tag. It will be replaced with <strong> tag during cleanup phase.
-140 this.execCommand ( "styleWithCSS" , "false" ) ;
-141 this.execCommand ( "bold" ) ;
-142 } ,
-143 applyStrike : function ( ) {
-144 // Generate <strike> tag. It will be replaced with <style class="strike"> tag during cleanup phase.
-145 this.execCommand ( "styleWithCSS" , "false" ) ;
-146 this.execCommand ( "strikethrough" ) ;
-147 } ,
-148 applyUnderline : function ( ) {
-149 // Generate <u> tag. It will be replaced with <em class="underline"> tag during cleanup phase.
-150 this.execCommand ( "styleWithCSS" , "false" ) ;
-151 this.execCommand ( "underline" ) ;
-152 } ,
-153 execHeading : function ( level ) {
-154 this.execCommand ( "Heading" , "H" + level ) ;
-155 } ,
-156
-157
-158
-159 //////
-160 // Focus/Caret/Selection
-161
-162 focus : function ( ) {
-163 setTimeout ( this._focus.bind ( this ) , 0 ) ;
-164 } ,
-165
-166 /** @private */
-167 _focus : function ( ) {
-168 this.win.focus ( ) ;
-169 if ( ! this.hasSelection ( ) && this.getCurrentElement ( ) . nodeName == "HTML" ) {
-170 this.selectElement ( this.doc.body.firstChild ) ;
-171 this.collapseSelection ( true ) ;
-172 }
-173 } ,
-174
-175 sel : function ( ) {
-176 return this.win.getSelection ( ) ;
-177 } ,
-178
-179 rng : function ( ) {
-180 var sel = this.sel ( ) ;
-181 return ( sel == null || sel.rangeCount == 0 ) ? null : sel.getRangeAt ( 0 ) ;
-182 } ,
-183
-184 hasSelection : function ( ) {
-185 var sel = this.sel ( ) ;
-186 return sel && ! sel.isCollapsed ;
-187 } ,
-188
-189 deleteSelection : function ( ) {
-190 this.rng ( ) . deleteContents ( ) ;
-191 this.sel ( ) . collapseToStart ( ) ;
-192 } ,
-193
-194 selectElement : function ( element , entireElement ) { throw "Not implemented yet" } ,
-195
-196 selectBlocksBetween : function ( start , end ) {
-197 // required to avoid FF selection bug.
-198 try {
-199 if ( ! xq.Browser.isMac ) this.doc.execCommand ( "SelectAll" , false , null ) ;
-200 } catch ( ignored ) { }
-201
-202 var rng = this.rng ( ) ;
-203 rng.setStart ( start.firstChild , 0 ) ;
-204 rng.setEnd ( end , end.childNodes.length ) ;
-205 } ,
-206
-207 collapseSelection : function ( toStart ) {
-208 this.rng ( ) . collapse ( toStart ) ;
-209 } ,
-210
-211 placeCaretAtStartOf : function ( element ) {
-212 while ( this.tree.isBlock ( element.firstChild ) ) {
-213 element = element.firstChild ;
-214 }
-215 this.selectElement ( element , false ) ;
-216 this.collapseSelection ( true ) ;
-217 } ,
-218
-219 getSelectionAsHtml : function ( ) {
-220 var container = document.createElement ( "div" ) ;
-221 container.appendChild ( this.rng ( ) . cloneContents ( ) ) ;
-222 return container.innerHTML ;
-223 } ,
-224
-225 getSelectionAsText : function ( ) {
-226 return this.rng ( ) . toString ( )
-227 } ,
-228
-229 hasImportantAttributes : function ( element ) {
-230 return ! ! ( element.id || element.className || element.style.cssText ) ;
-231 } ,
-232
-233 isEmptyBlock : function ( element ) {
-234 if ( ! element.hasChildNodes ( ) ) return true ;
-235 var children = element.childNodes ;
-236 for ( var i = 0 ; i < children.length ; i ++ ) {
-237 if ( ! this.isPlaceHolder ( children [ i ] ) && ! this.isEmptyTextNode ( children [ i ] ) ) return false ;
-238 }
-239 return true ;
-240 } ,
-241
-242 getLastChild : function ( element ) {
-243 if ( ! element || ! element.hasChildNodes ( ) ) return null ;
-244
-245 var nodes = $A ( element.childNodes ) . reverse ( ) ;
-246
-247 for ( var i = 0 ; i < nodes.length ; i ++ ) {
-248 if ( ! this.isPlaceHolder ( nodes [ i ] ) && ! this.isEmptyTextNode ( nodes [ i ] ) ) return nodes [ i ] ;
-249 }
-250 return null ;
-251 } ,
-252
-253 getCurrentElement : function ( ) {
-254 var rng = this.rng ( ) ;
-255 if ( ! rng ) return null ;
-256
-257 var container = rng.startContainer ;
-258 return container.nodeType == 3 ? container.parentNode : container ;
-259 } ,
-260
-261 getBlockElementsAtSelectionEdge : function ( naturalOrder , ignoreEmptyEdges ) {
-262 var start = this.getBlockElementAtSelectionStart ( ) ;
-263 var end = this.getBlockElementAtSelectionEnd ( ) ;
-264
-265 var reversed = false ;
-266
-267 if ( naturalOrder && start != end && this.tree.checkTargetBackward ( start , end ) ) {
-268 var temp = start ;
-269 start = end ;
-270 end = temp ;
-271
-272 reversed = true ;
-273 }
-274
-275 if ( ignoreEmptyEdges && start != end ) {
-276 // TODO - Firefox sometimes selects one more block.
-277 /*
-278
-279 var sel = this.sel();
-280 if(reversed) {
-281 if(sel.focusNode.nodeType == 1) start = start.nextSibling;
-282 if(sel.anchorNode.nodeType == 3 && sel.focusOffset == 0) end = end.previousSibling;
-283 } else {
-284 if(sel.anchorNode.nodeType == 1) start = start.nextSibling;
-285 if(sel.focusNode.nodeType == 3 && sel.focusOffset == 0) end = end.previousSibling;
-286 }
-287 */
-288 }
-289
-290 return [ start , end ] ;
-291 } ,
-292
-293 getBlockElementAtSelectionStart : function ( ) {
-294 var block = this.getParentBlockElementOf ( this.sel ( ) . anchorNode ) ;
-295
-296 // find bottom-most first block child
-297 while ( this.tree.isBlockContainer ( block ) && block.firstChild && this.tree.isBlock ( block.firstChild ) ) {
-298 block = block.firstChild ;
-299 }
-300
-301 return block ;
-302 } ,
-303
-304 getBlockElementAtSelectionEnd : function ( ) {
-305 var block = this.getParentBlockElementOf ( this.sel ( ) . focusNode ) ;
-306
-307 // find bottom-most last block child
-308 while ( this.tree.isBlockContainer ( block ) && block.lastChild && this.tree.isBlock ( block.lastChild ) ) {
-309 block = block.lastChild ;
-310 }
-311
-312 return block ;
-313 } ,
-314
-315 isCaretAtBlockStart : function ( ) {
-316 if ( this.isCaretAtEmptyBlock ( ) ) return true ;
-317 if ( this.hasSelection ( ) ) return false ;
-318 var rng = this.rng ( ) ;
-319 var node = this.getCurrentBlockElement ( ) ;
-320 var isTrue = false ;
-321
-322 if ( node == rng.startContainer ) {
-323 var marker = this.pushMarker ( ) ;
-324 while ( node = this.getFirstChild ( node ) ) {
-325 if ( node == marker ) {
-326 isTrue = true ;
-327 break ;
-328 }
-329 }
-330 this.popMarker ( ) ;
-331 } else {
-332 while ( node = node.firstChild ) {
-333 if ( node == rng.startContainer && rng.startOffset == 0 ) {
-334 isTrue = true ;
-335 break ;
-336 }
-337 }
-338 }
-339
-340 return isTrue ;
-341 } ,
-342
-343 isCaretAtBlockEnd : function ( ) {
-344 if ( this.isCaretAtEmptyBlock ( ) ) return true ;
-345 if ( this.hasSelection ( ) ) return false ;
-346
-347 var rng = this.rng ( ) ;
-348 var node = this.getCurrentBlockElement ( ) ;
-349 var isTrue = false ;
-350
-351 if ( node == rng.startContainer ) {
-352 var marker = this.pushMarker ( ) ;
-353 while ( node = this.getLastChild ( node ) ) {
-354 if ( ( node == marker ) || ( this.isPlaceHolder ( node ) && node.previousSibling == marker ) ) {
-355 isTrue = true ;
-356 break ;
-357 }
-358 }
-359 this.popMarker ( ) ;
-360 } else {
-361 while ( node = this.getLastChild ( node ) ) {
-362 if ( node == rng.endContainer && rng.endContainer.nodeType == 1 ) {
-363 isTrue = true ;
-364 break ;
-365 } else if ( node == rng.endContainer && rng.endOffset == node.nodeValue.length ) {
-366 isTrue = true ;
-367 break ;
-368 }
-369 }
-370 }
-371
-372 return isTrue ;
-373 }
-374 } ) ;
-375
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_10.html b/modules/editor/skins/xquared/doc/api/src_10.html
deleted file mode 100644
index 9eb4955a5..000000000
--- a/modules/editor/skins/xquared/doc/api/src_10.html
+++ /dev/null
@@ -1,91 +0,0 @@
- 1 /**
- 2 * RichDom for Webkit
- 3 */
- 4 xq.RichDomWebkit = Class.create ( xq.RichDomW3 , {
- 5 makePlaceHolder : function ( ) {
- 6 var holder = this.createElement ( "BR" ) ;
- 7 holder.className = "webkit-block-placeholder" ;
- 8 return holder ;
- 9 } ,
- 10
- 11 makePlaceHolderString : function ( ) {
- 12 return '<br class="webkit-block-placeholder" />' ;
- 13 } ,
- 14
- 15 makeEmptyParagraph : function ( ) {
- 16 return this.createElementFromHtml ( '<p><br class="webkit-block-placeholder" /></p>' ) ;
- 17 } ,
- 18
- 19 isPlaceHolder : function ( node ) {
- 20 return node.nodeName == "BR" && node.className == "webkit-block-placeholder" ;
- 21 } ,
- 22
- 23 rng : function ( ) {
- 24 var sel = this.sel ( ) ;
- 25 var rng = this.doc.createRange ( ) ;
- 26 if ( ! this._rng ||
- 27 this._anchorNode != sel.anchorNode ||
- 28 this._anchorOffset != sel.anchorOffset ||
- 29 this._focusNode != sel.focusNode ||
- 30 this._focusOffset != sel.focusOffset ) {
- 31
- 32 if ( sel.type != 'None' ) {
- 33 rng.setStart ( sel.anchorNode , sel.anchorOffset ) ;
- 34 rng.setEnd ( sel.focusNode , sel.focusOffset ) ;
- 35 }
- 36 this._anchorNode = sel.anchorNode ;
- 37 this._anchorOffset = sel.anchorOffset ;
- 38 this._focusNode = sel.focusNode ;
- 39 this._focusOffset = sel.focusOffset ;
- 40 this._rng = rng ;
- 41 }
- 42 return this._rng ;
- 43 } ,
- 44
- 45 selectElement : function ( element , entireElement ) {
- 46 if ( ! element ) throw "[element] is null" ;
- 47 if ( element.nodeType != 1 ) throw "[element] is not an element" ;
- 48
- 49 var rng = this.rng ( ) ;
- 50 if ( entireElement ) {
- 51 rng.selectNode ( element ) ;
- 52 } else {
- 53 rng.selectNodeContents ( element ) ;
- 54 }
- 55 this._setSelectionByRange ( rng ) ;
- 56 } ,
- 57
- 58 deleteSelection : function ( ) {
- 59 this.rng ( ) . deleteContents ( ) ;
- 60 } ,
- 61
- 62 collapseSelection : function ( toStart ) {
- 63 var rng = this.rng ( ) ;
- 64 rng.collapse ( toStart ) ;
- 65 this._setSelectionByRange ( rng ) ;
- 66 } ,
- 67
- 68 getSelectionAsHtml : function ( ) {
- 69 var container = this.createElement ( "div" ) ;
- 70 var rng = this.rng ( ) ;
- 71 var contents = this.rng ( ) . cloneContents ( ) ;
- 72 if ( contents ) container.appendChild ( contents ) ;
- 73 return container.innerHTML ;
- 74 } ,
- 75
- 76 _setSelectionByRange : function ( rng ) {
- 77 var sel = this.sel ( ) ;
- 78 sel.setBaseAndExtent ( rng.startContainer , rng.startOffset , rng.endContainer , rng.endOffset ) ;
- 79 this._anchorNode = sel.anchorNode ;
- 80 this._anchorOffset = sel.anchorOffset ;
- 81 this._focusNode = sel.focusNode ;
- 82 this._focusOffset = sel.focusOffset ;
- 83 }
- 84 } ) ;
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_11.html b/modules/editor/skins/xquared/doc/api/src_11.html
deleted file mode 100644
index 58f5fb053..000000000
--- a/modules/editor/skins/xquared/doc/api/src_11.html
+++ /dev/null
@@ -1,209 +0,0 @@
- 1 xq.RichTable = Class.create ( {
- 2 initialize : function ( rdom , table ) {
- 3 this.rdom = rdom ;
- 4 this.table = table ;
- 5 } ,
- 6 insertNewRowAt : function ( tr , where ) {
- 7 var row = this.rdom.createElement ( "TR" ) ;
- 8 var cells = tr.cells ;
- 9 for ( var i = 0 ; i < cells.length ; i ++ ) {
- 10 var cell = this.rdom.createElement ( cells [ i ] . nodeName ) ;
- 11 this.rdom.correctEmptyElement ( cell ) ;
- 12 row.appendChild ( cell ) ;
- 13 }
- 14 return this.rdom.insertNodeAt ( row , tr , where ) ;
- 15 } ,
- 16 insertNewCellAt : function ( cell , where ) {
- 17 // collect cells;
- 18 var cells = [ ] ;
- 19 var x = this.getXIndexOf ( cell ) ;
- 20 var y = 0 ;
- 21 while ( true ) {
- 22 var cur = this.getCellAt ( x , y ) ;
- 23 if ( ! cur ) break ;
- 24 cells.push ( cur ) ;
- 25 y ++ ;
- 26 }
- 27
- 28 // insert new cells
- 29 for ( var i = 0 ; i < cells.length ; i ++ ) {
- 30 var cell = this.rdom.createElement ( cells [ i ] . nodeName ) ;
- 31 this.rdom.correctEmptyElement ( cell ) ;
- 32 this.rdom.insertNodeAt ( cell , cells [ i ] , where ) ;
- 33 }
- 34 } ,
- 35 deleteRow : function ( tr ) {
- 36 return this.rdom.removeBlock ( tr ) ;
- 37 } ,
- 38 deleteCell : function ( cell ) {
- 39 if ( ! cell.previousSibling && ! cell.nextSibling ) {
- 40 this.rdom.deleteNode ( this.table ) ;
- 41 return ;
- 42 }
- 43
- 44 // collect cells;
- 45 var cells = [ ] ;
- 46 var x = this.getXIndexOf ( cell ) ;
- 47 var y = 0 ;
- 48 while ( true ) {
- 49 var cur = this.getCellAt ( x , y ) ;
- 50 if ( ! cur ) break ;
- 51 cells.push ( cur ) ;
- 52 y ++ ;
- 53 }
- 54
- 55 for ( var i = 0 ; i < cells.length ; i ++ ) {
- 56 this.rdom.deleteNode ( cells [ i ] ) ;
- 57 }
- 58 } ,
- 59 getPreviousCellOf : function ( cell ) {
- 60 if ( cell.previousSibling ) return cell.previousSibling ;
- 61 var adjRow = this.getPreviousRowOf ( cell.parentNode ) ;
- 62 if ( adjRow ) return adjRow.lastChild ;
- 63 return null ;
- 64 } ,
- 65 getNextCellOf : function ( cell ) {
- 66 if ( cell.nextSibling ) return cell.nextSibling ;
- 67 var adjRow = this.getNextRowOf ( cell.parentNode ) ;
- 68 if ( adjRow ) return adjRow.firstChild ;
- 69 return null ;
- 70 } ,
- 71 getPreviousRowOf : function ( row ) {
- 72 if ( row.previousSibling ) return row.previousSibling ;
- 73 var rowContainer = row.parentNode ;
- 74 if ( rowContainer.previousSibling && rowContainer.previousSibling.lastChild ) return rowContainer.previousSibling.lastChild ;
- 75 return null ;
- 76 } ,
- 77 getNextRowOf : function ( row ) {
- 78 if ( row.nextSibling ) return row.nextSibling ;
- 79 var rowContainer = row.parentNode ;
- 80 if ( rowContainer.nextSibling && rowContainer.nextSibling.firstChild ) return rowContainer.nextSibling.firstChild ;
- 81 return null ;
- 82 } ,
- 83 getAboveCellOf : function ( cell ) {
- 84 var row = this.getPreviousRowOf ( cell.parentNode ) ;
- 85 if ( ! row ) return null ;
- 86
- 87 var x = this.getXIndexOf ( cell ) ;
- 88 return row.cells [ x ] ;
- 89 } ,
- 90 getBelowCellOf : function ( cell ) {
- 91 var row = this.getNextRowOf ( cell.parentNode ) ;
- 92 if ( ! row ) return null ;
- 93
- 94 var x = this.getXIndexOf ( cell ) ;
- 95 return row.cells [ x ] ;
- 96 } ,
- 97 getXIndexOf : function ( cell ) {
- 98 var row = cell.parentNode ;
- 99 for ( var i = 0 ; i < row.cells.length ; i ++ ) {
-100 if ( row.cells [ i ] == cell ) return i ;
-101 }
-102
-103 return - 1 ;
-104 } ,
-105 getYIndexOf : function ( cell ) {
-106 var y = - 1 ;
-107
-108 // find y
-109 var group = row.parentNode ;
-110 for ( var i = 0 ; i < group.rows.length ; i ++ ) {
-111 if ( group.rows [ i ] == row ) {
-112 y = i ;
-113 break ;
-114 }
-115 }
-116 if ( this.hasHeadingAtTop ( ) && group.nodeName == "TBODY" ) y = y + 1 ;
-117
-118 return y ;
-119 } ,
-120 /**
-121 * TODO: Not used. Delete or not?
-122 */
-123 getLocationOf : function ( cell ) {
-124 var x = this.getXIndexOf ( cell ) ;
-125 var y = this.getYIndexOf ( cell ) ;
-126 return { x : x , y : y } ;
-127 } ,
-128 getCellAt : function ( col , row ) {
-129 var row = this.getRowAt ( row ) ;
-130 return ( row && row.cells.length > col ) ? row.cells [ col ] : null ;
-131 } ,
-132 getRowAt : function ( index ) {
-133 if ( this.hasHeadingAtTop ( ) ) {
-134 return index == 0 ? this.table.tHead.rows [ 0 ] : this.table.tBodies [ 0 ] . rows [ index - 1 ] ;
-135 } else {
-136 var rows = this.table.tBodies [ 0 ] . rows ;
-137 return ( rows.length > index ) ? rows [ index ] : null ;
-138 }
-139 } ,
-140 getDom : function ( ) {
-141 return this.table ;
-142 } ,
-143 hasHeadingAtTop : function ( ) {
-144 return ! ! ( this.table.tHead && this.table.tHead.rows [ 0 ] ) ;
-145 } ,
-146 hasHeadingAtLeft : function ( ) {
-147 return this.table.tBodies [ 0 ] . rows [ 0 ] . cells [ 0 ] . nodeName == "TH" ;
-148 } ,
-149 correctEmptyCells : function ( ) {
-150 var cells = $A ( this.table.getElementsByTagName ( "TH" ) ) ;
-151 cells.push ( $A ( this.table.getElementsByTagName ( "TD" ) ) ) ;
-152 cells = cells.flatten ( ) ;
-153
-154 for ( var i = 0 ; i < cells.length ; i ++ ) {
-155 if ( this.rdom.isEmptyBlock ( cells [ i ] ) ) this.rdom.correctEmptyElement ( cells [ i ] )
-156 }
-157 }
-158 } ) ;
-159
-160 xq.RichTable.create = function ( rdom , cols , rows , headerPositions ) {
-161 if ( [ "t" , "tl" , "lt" ] . include ( headerPositions ) ) var headingAtTop = true
-162 if ( [ "l" , "tl" , "lt" ] . include ( headerPositions ) ) var headingAtLeft = true
-163
-164 var sb = [ ]
-165 sb.push ( '<table class="datatable">' )
-166
-167 // thead
-168 if ( headingAtTop ) {
-169 sb.push ( '<thead><tr>' )
-170 for ( var i = 0 ; i < cols ; i ++ ) sb.push ( '<th></th>' )
-171 sb.push ( '</tr></thead>' )
-172 rows - = 1
-173 }
-174
-175 // tbody
-176 sb.push ( '<tbody>' )
-177 for ( var i = 0 ; i < rows ; i ++ ) {
-178 sb.push ( '<tr>' )
-179
-180 for ( var j = 0 ; j < cols ; j ++ ) {
-181 if ( headingAtLeft && j == 0 ) {
-182 sb.push ( '<th></th>' )
-183 } else {
-184 sb.push ( '<td></td>' )
-185 }
-186 }
-187
-188 sb.push ( '</tr>' )
-189 }
-190 sb.push ( '</tbody>' )
-191
-192 sb.push ( '</table>' )
-193
-194 // create DOM element
-195 var container = rdom.createElement ( "div" ) ;
-196 container.innerHTML = sb.join ( "" ) ;
-197
-198 // correct empty cells and return
-199 var rtable = new xq.RichTable ( rdom , container.firstChild ) ;
-200 rtable.correctEmptyCells ( ) ;
-201 return rtable ;
-202 }
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_12.html b/modules/editor/skins/xquared/doc/api/src_12.html
deleted file mode 100644
index 72b700cd4..000000000
--- a/modules/editor/skins/xquared/doc/api/src_12.html
+++ /dev/null
@@ -1,135 +0,0 @@
- 1 xq.Shortcut = Class.create ( {
- 2 initialize : function ( keymapOrExpression ) {
- 3 this.keymap = ( typeof keymapOrExpression == "string" ) ?
- 4 xq.Shortcut.interprete ( keymapOrExpression ) . keymap :
- 5 keymapOrExpression ;
- 6 } ,
- 7 matches : function ( e ) {
- 8 var which = xq.Browser.isGecko && xq.Browser.isMac ? ( e.keyCode + "_" + e.charCode ) : e.keyCode ;
- 9
- 10 var keyMatches =
- 11 ( this.keymap.which == which ) ||
- 12 ( this.keymap.which == 32 && which == 25 ) ; // 25 is SPACE in Type-3 keyboard.
- 13
- 14 if ( typeof e.metaKey == "undefined" ) e.metaKey = false ;
- 15
- 16 var modifierMatches =
- 17 ( typeof this.keymap.shiftKey == "undefined" || this.keymap.shiftKey == e.shiftKey ) &&
- 18 ( typeof this.keymap.altKey == "undefined" || this.keymap.altKey == e.altKey ) &&
- 19 ( typeof this.keymap.ctrlKey == "undefined" || this.keymap.ctrlKey == e.ctrlKey ) &&
- 20 ( typeof this.keymap.metaKey == "undefined" || this.keymap.metaKey == e.metaKey )
- 21
- 22 return modifierMatches && keyMatches ;
- 23 }
- 24 } ) ;
- 25
- 26 xq.Shortcut.interprete = function ( expression ) {
- 27 expression = expression.toUpperCase ( ) ;
- 28
- 29 var which = xq.Shortcut._interpreteWhich ( expression.split ( "+" ) . pop ( ) ) ;
- 30 var ctrlKey = xq.Shortcut._interpreteModifier ( expression , "CTRL" ) ;
- 31 var altKey = xq.Shortcut._interpreteModifier ( expression , "ALT" ) ;
- 32 var shiftKey = xq.Shortcut._interpreteModifier ( expression , "SHIFT" ) ;
- 33 var metaKey = xq.Shortcut._interpreteModifier ( expression , "META" ) ;
- 34
- 35 var keymap = { } ;
- 36
- 37 keymap.which = which ;
- 38 if ( typeof ctrlKey != "undefined" ) keymap.ctrlKey = ctrlKey ;
- 39 if ( typeof altKey != "undefined" ) keymap.altKey = altKey ;
- 40 if ( typeof shiftKey != "undefined" ) keymap.shiftKey = shiftKey ;
- 41 if ( typeof metaKey != "undefined" ) keymap.metaKey = metaKey ;
- 42
- 43 return new xq.Shortcut ( keymap ) ;
- 44 }
- 45
- 46 xq.Shortcut._interpreteModifier = function ( expression , modifierName ) {
- 47 return expression.match ( "\\(" + modifierName + "\\)" ) ?
- 48 undefined :
- 49 expression.match ( modifierName ) ?
- 50 true : false ;
- 51 }
- 52 xq.Shortcut._interpreteWhich = function ( keyName ) {
- 53 var which = keyName.length == 1 ?
- 54 ( ( xq.Browser.isMac && xq.Browser.isGecko ) ? "0_" + keyName.toLowerCase ( ) . charCodeAt ( 0 ) : keyName.charCodeAt ( 0 ) ) :
- 55 xq.Shortcut._keyNames [ keyName ] ;
- 56
- 57 if ( typeof which == "undefined" ) throw "Unknown special key name: [" + keyName + "]"
- 58
- 59 return which ;
- 60 }
- 61 xq.Shortcut._keyNames =
- 62 xq.Browser.isMac && xq.Browser.isGecko ?
- 63 {
- 64 BACKSPACE : "8_0" ,
- 65 TAB : "9_0" ,
- 66 RETURN : "13_0" ,
- 67 ENTER : "13_0" ,
- 68 ESC : "27_0" ,
- 69 SPACE : "0_32" ,
- 70 LEFT : "37_0" ,
- 71 UP : "38_0" ,
- 72 RIGHT : "39_0" ,
- 73 DOWN : "40_0" ,
- 74 DELETE : "46_0" ,
- 75 HOME : "36_0" ,
- 76 END : "35_0" ,
- 77 PAGEUP : "33_0" ,
- 78 PAGEDOWN : "34_0" ,
- 79 COMMA : "0_44" ,
- 80 HYPHEN : "0_45" ,
- 81 EQUAL : "0_61" ,
- 82 PERIOD : "0_46" ,
- 83 SLASH : "0_47" ,
- 84 F1 : "112_0" ,
- 85 F2 : "113_0" ,
- 86 F3 : "114_0" ,
- 87 F4 : "115_0" ,
- 88 F5 : "116_0" ,
- 89 F6 : "117_0" ,
- 90 F7 : "118_0" ,
- 91 F8 : "119_0"
- 92 }
- 93 :
- 94 {
- 95 BACKSPACE : 8 ,
- 96 TAB : 9 ,
- 97 RETURN : 13 ,
- 98 ENTER : 13 ,
- 99 ESC : 27 ,
-100 SPACE : 32 ,
-101 LEFT : 37 ,
-102 UP : 38 ,
-103 RIGHT : 39 ,
-104 DOWN : 40 ,
-105 DELETE : 46 ,
-106 HOME : 36 ,
-107 END : 35 ,
-108 PAGEUP : 33 ,
-109 PAGEDOWN : 34 ,
-110 COMMA : 188 ,
-111 HYPHEN : xq.Browser.isTrident ? 189 : 109 ,
-112 EQUAL : xq.Browser.isTrident ? 187 : 61 ,
-113 PERIOD : 190 ,
-114 SLASH : 191 ,
-115 F1 : 112 ,
-116 F2 : 113 ,
-117 F3 : 114 ,
-118 F4 : 115 ,
-119 F5 : 116 ,
-120 F6 : 117 ,
-121 F7 : 118 ,
-122 F8 : 119 ,
-123 F9 : 120 ,
-124 F10 : 121 ,
-125 F11 : 122 ,
-126 F12 : 123
-127 }
-128
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_13.html b/modules/editor/skins/xquared/doc/api/src_13.html
deleted file mode 100644
index e2311e8a9..000000000
--- a/modules/editor/skins/xquared/doc/api/src_13.html
+++ /dev/null
@@ -1,235 +0,0 @@
- 1 /**
- 2 * Validates and invalidates designmode contents
- 3 */
- 4 xq.Validator = Class.create ( {
- 5 initialize : function ( curUrl , urlValidationMode , allowedTags , allowedAttrs ) {
- 6 this.allowedTags = ( allowedTags || [ 'a' , 'abbr' , 'acronym' , 'address' , 'blockquote' , 'br' , 'caption' , 'cite' , 'code' , 'dd' , 'dfn' , 'div' , 'dl' , 'dt' , 'em' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'hr' , 'img' , 'kbd' , 'li' , 'ol' , 'p' , 'pre' , 'q' , 'samp' , 'span' , 'sup' , 'sub' , 'strong' , 'table' , 'thead' , 'tbody' , 'td' , 'th' , 'tr' , 'ul' , 'var' ] ) . join ( ' ' ) + ' ' ;
- 7 this.allowedAttrs = ( allowedAttrs || [ 'alt' , 'cite' , 'class' , 'datetime' , 'height' , 'href' , 'id' , 'rel' , 'rev' , 'src' , 'style' , 'title' , 'width' ] ) . join ( ' ' ) + ' ' ;
- 8
- 9 this.curUrl = curUrl ;
- 10 this.curUrlParts = curUrl ? curUrl.parseURL ( ) : null ;
- 11 this.urlValidationMode = urlValidationMode ;
- 12 } ,
- 13
- 14 /**
- 15 * Perform validation on given element
- 16 *
- 17 * @param {Element} element Target element. It is not affected by validation.
- 18 * @param {boolean} fullValidation Perform full validation. If you just want to use the result to assign innerHTML, set it false
- 19 *
- 20 * @returns {String} Validated HTML string
- 21 */
- 22 validate : function ( element , fullValidation ) { throw "Not implemented" } ,
- 23
- 24 /**
- 25 * Perform invalidation on given element to make the designmode works well.
- 26 *
- 27 * @param {Element} element Target element.
- 28 * @returns {String} Invalidated HTML string
- 29 */
- 30 invalidate : function ( element ) { throw "Not implemented" } ,
- 31
- 32 validateStrike : function ( content ) {
- 33 content = content.replace ( /<strike(>|\s+[^>]*>)/ig , "<span class=\"strike\"$1" ) ;
- 34 content = content.replace ( /<\/strike>/ig , "</span>" ) ;
- 35 return content ;
- 36 } ,
- 37
- 38 validateUnderline : function ( content ) {
- 39 content = content.replace ( /<u(>|\s+[^>]*>)/ig , "<em class=\"underline\"$1" ) ;
- 40 content = content.replace ( /<\/u>/ig , "</em>" ) ;
- 41 return content ;
- 42 } ,
- 43
- 44 replaceTag : function ( content , from , to ) {
- 45 return content.replace ( new RegExp ( "(</?)" + from + "(>|\\s+[^>]*>)" , "ig" ) , "$1" + to + "$2" ) ;
- 46 } ,
- 47
- 48 validateSelfClosingTags : function ( content ) {
- 49 return content.replace ( /<(br|hr|img)([^>]*?)>/img , function ( str , tag , attrs ) {
- 50 return "<" + tag + attrs + " />"
- 51 } ) ;
- 52 } ,
- 53
- 54 removeComments : function ( content ) {
- 55 return content.replace ( /<!--.*?-->/img , '' ) ;
- 56 } ,
- 57
- 58 removeDangerousElements : function ( element ) {
- 59 var scripts = $A ( element.getElementsByTagName ( 'SCRIPT' ) ) . reverse ( ) ;
- 60 for ( var i = 0 ; i < scripts.length ; i ++ ) {
- 61 scripts [ i ] . parentNode.removeChild ( scripts [ i ] ) ;
- 62 }
- 63 } ,
- 64
- 65 // TODO: very slow
- 66 applyWhitelist : function ( content ) {
- 67 var allowedTags = this.allowedTags ;
- 68 var allowedAttrs = this.allowedAttrs ;
- 69
- 70 return content.replace ( new RegExp ( "(</?)([^>]+?)(>|\\s+([^>]*?)(\\s?/?)>)" , "g" ) , function ( str , head , tag , tail , attrs , selfClosing ) {
- 71 if ( allowedTags.indexOf ( tag ) == - 1 ) return '' ;
- 72
- 73 if ( attrs ) {
- 74 attrs = attrs.replace ( /(^|\s")([^"=]+)(\s|$)/g , '$1$2="$2"$3' ) ; // for IE
- 75
- 76 var sb = [ ] ;
- 77 var m = attrs.match ( /([^=]+)="[^"]*?"/g ) ;
- 78 for ( var i = 0 ; i < m.length ; i ++ ) {
- 79 m [ i ] = m [ i ] . strip ( ) ;
- 80 var name = m [ i ] . split ( '=' ) [ 0 ] ;
- 81 if ( allowedAttrs.indexOf ( name ) != - 1 ) sb.push ( m [ i ] ) ;
- 82 }
- 83 attrs = sb.join ( ' ' ) ;
- 84 if ( attrs != '' ) attrs = ' ' + attrs ;
- 85 return head + tag + attrs + selfClosing + '>' ;
- 86 } else {
- 87 return str ;
- 88 }
- 89 } ) ;
- 90 } ,
- 91
- 92 makeUrlsRelative : function ( content ) {
- 93 var curUrl = this.curUrl ;
- 94 var urlParts = this.curUrlParts ;
- 95
- 96 // 1. find attributes and...
- 97 return content.replace ( /(<\w+\s+)(\/|([^>]+?)(\/?))>/g , function ( str , head , ignored , attrs , tail ) {
- 98 if ( attrs ) {
- 99 // 2. validate URL part
-100 attrs = attrs.replace ( /(href|src)="([^"]+)"/g , function ( str , name , url ) {
-101 // 3. first, make it absolute
-102 var abs = null ;
-103 if ( url.charAt ( 0 ) == '#' ) {
-104 abs = urlParts.includeQuery + url ;
-105 } else if ( url.charAt ( 0 ) == '?' ) {
-106 abs = urlParts.includePath + url ;
-107 } else if ( url.charAt ( 0 ) == '/' ) {
-108 abs = urlParts.includeHost + url ;
-109 } else if ( url.match ( /^\w+:\/\// ) ) {
-110 abs = url ;
-111 } else {
-112 abs = urlParts.includeBase + url ;
-113 }
-114
-115 // 4. make it relative by removing same part
-116 var rel = abs ;
-117
-118 if ( abs.indexOf ( urlParts.includeQuery ) == 0 ) {
-119 rel = abs.substring ( urlParts.includeQuery.length ) ;
-120 } else if ( abs.indexOf ( urlParts.includePath ) == 0 ) {
-121 rel = abs.substring ( urlParts.includePath.length ) ;
-122 } else if ( abs.indexOf ( urlParts.includeBase ) == 0 ) {
-123 rel = abs.substring ( urlParts.includeBase.length ) ;
-124 } else if ( abs.indexOf ( urlParts.includeHost ) == 0 ) {
-125 rel = abs.substring ( urlParts.includeHost.length ) ;
-126 }
-127 if ( rel == '' ) rel = '#' ;
-128
-129 return name + '="' + rel + '"' ;
-130 } ) ;
-131
-132 return head + attrs + tail + '>' ;
-133 } else {
-134 return str ;
-135 }
-136 } ) ;
-137
-138 return content ;
-139 } ,
-140
-141 makeUrlsHostRelative : function ( content ) {
-142 var curUrl = this.curUrl ;
-143 var urlParts = this.curUrlParts ;
-144
-145 // 1. find attributes and...
-146 return content.replace ( /(<\w+\s+)(\/|([^>]+?)(\/?))>/g , function ( str , head , ignored , attrs , tail ) {
-147 if ( attrs ) {
-148 // 2. validate URL part
-149 attrs = attrs.replace ( /(href|src)="([^"]+)"/g , function ( str , name , url ) {
-150 // 3. first, make it absolute
-151 var abs = null ;
-152 if ( url.charAt ( 0 ) == '#' ) {
-153 abs = urlParts.includeQuery + url ;
-154 } else if ( url.charAt ( 0 ) == '?' ) {
-155 abs = urlParts.includePath + url ;
-156 } else if ( url.charAt ( 0 ) == '/' ) {
-157 abs = urlParts.includeHost + url ;
-158 } else if ( url.match ( /^\w+:\/\// ) ) {
-159 abs = url ;
-160 } else {
-161 abs = urlParts.includeBase + url ;
-162 }
-163
-164 // 4. make it relative by removing same part
-165 var rel = abs ;
-166 if ( abs.indexOf ( urlParts.includeHost ) == 0 ) {
-167 rel = abs.substring ( urlParts.includeHost.length ) ;
-168 }
-169 if ( rel == '' ) rel = '#' ;
-170
-171 return name + '="' + rel + '"' ;
-172 } ) ;
-173
-174 return head + attrs + tail + '>' ;
-175 } else {
-176 return str ;
-177 }
-178 } ) ;
-179
-180 return content ;
-181 } ,
-182
-183 makeUrlsAbsolute : function ( content ) {
-184 var curUrl = this.curUrl ;
-185 var urlParts = this.curUrlParts ;
-186
-187 // 1. find attributes and...
-188 return content.replace ( /(<\w+\s+)(\/|([^>]+?)(\/?))>/g , function ( str , head , ignored , attrs , tail ) {
-189 if ( attrs ) {
-190 // 2. validate URL part
-191 attrs = attrs.replace ( /(href|src)="([^"]+)"/g , function ( str , name , url ) {
-192 var abs = null ;
-193 if ( url.charAt ( 0 ) == '#' ) {
-194 abs = urlParts.includeQuery + url ;
-195 } else if ( url.charAt ( 0 ) == '?' ) {
-196 abs = urlParts.includePath + url ;
-197 } else if ( url.charAt ( 0 ) == '/' ) {
-198 abs = urlParts.includeHost + url ;
-199 } else if ( url.match ( /^\w+:\/\// ) ) {
-200 abs = url ;
-201 } else {
-202 abs = urlParts.includeBase + url ;
-203 }
-204
-205 return name + '="' + abs + '"' ;
-206 } ) ;
-207
-208 return head + attrs + tail + '>' ;
-209 } else {
-210 return str ;
-211 }
-212 } ) ;
-213 }
-214 } ) ;
-215
-216 /**
-217 * Creates and returns instance of browser specific implementation.
-218 */
-219 xq.Validator.createInstance = function ( curUrl , urlValidationMode , allowedTags , allowedAttrs ) {
-220 if ( xq.Browser.isTrident ) {
-221 return new xq.ValidatorTrident ( curUrl , urlValidationMode , allowedTags , allowedAttrs ) ;
-222 } else if ( xq.Browser.isWebkit ) {
-223 return new xq.ValidatorWebkit ( curUrl , urlValidationMode , allowedTags , allowedAttrs ) ;
-224 } else {
-225 return new xq.ValidatorGecko ( curUrl , urlValidationMode , allowedTags , allowedAttrs ) ;
-226 }
-227 }
-228
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_14.html b/modules/editor/skins/xquared/doc/api/src_14.html
deleted file mode 100644
index 9de6a044d..000000000
--- a/modules/editor/skins/xquared/doc/api/src_14.html
+++ /dev/null
@@ -1,12 +0,0 @@
- 1 /**
- 2 * Validator for Gecko Engine
- 3 */
- 4 xq.ValidatorGecko = Class.create ( xq.ValidatorW3 , {
- 5 } ) ;
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_15.html b/modules/editor/skins/xquared/doc/api/src_15.html
deleted file mode 100644
index a67012aa6..000000000
--- a/modules/editor/skins/xquared/doc/api/src_15.html
+++ /dev/null
@@ -1,147 +0,0 @@
- 1 /**
- 2 * Validator for Internet Explorer 6 and 7
- 3 */
- 4 xq.ValidatorTrident = Class.create ( xq.Validator , {
- 5 validate : function ( element , fullValidation ) {
- 6 element = element.cloneNode ( true ) ;
- 7
- 8 this.removeDangerousElements ( element ) ;
- 9 this.validateFontColor ( element ) ;
- 10 this.validateBackgroundColor ( element ) ;
- 11
- 12 var content = element.innerHTML ;
- 13
- 14 try {
- 15 content = this.validateStrike ( content ) ;
- 16 content = this.validateUnderline ( content ) ;
- 17
- 18 if ( fullValidation ) content = this.performFullValidation ( content ) ;
- 19 } catch ( ignored ) { }
- 20
- 21 return content ;
- 22 } ,
- 23
- 24 invalidate : function ( element ) {
- 25 var rdom = xq.RichDom.createInstance ( ) ;
- 26 rdom.setRoot ( element ) ;
- 27
- 28 this.invalidateFontColor ( element ) ;
- 29 this.invalidateBackgroundColor ( element ) ;
- 30
- 31 // <span class="strike"> -> <strike>
- 32 var strikes = rdom.findByAttribute ( "className" , "strike" ) ;
- 33 for ( var i = 0 ; i < strikes.length ; i ++ ) {
- 34 if ( "SPAN" == strikes [ i ] . nodeName ) rdom.replaceTag ( "strike" , strikes [ i ] ) . removeAttribute ( "className" ) ;
- 35 }
- 36
- 37 // <em|i class="underline"> -> <u>
- 38 var underlines = rdom.findByAttribute ( "className" , "underline" ) ;
- 39 for ( var i = 0 ; i < underlines.length ; i ++ ) {
- 40 if ( [ "EM" , "I" ] . include ( underlines [ i ] . nodeName ) ) rdom.replaceTag ( "u" , underlines [ i ] ) . removeAttribute ( "className" ) ;
- 41 }
- 42
- 43 var content = rdom.getRoot ( ) . innerHTML ;
- 44
- 45 content = this.removeComments ( content ) ;
- 46
- 47 return content ;
- 48 } ,
- 49
- 50 performFullValidation : function ( content ) {
- 51 content = this.lowerTagNamesAndUniformizeQuotation ( content ) ;
- 52 content = this.validateSelfClosingTags ( content ) ;
- 53 content = this.applyWhitelist ( content ) ;
- 54
- 55 if ( this.urlValidationMode == 'relative' ) {
- 56 content = this.makeUrlsRelative ( content ) ;
- 57 } else if ( this.urlValidationMode == 'host_relative' ) {
- 58 content = this.makeUrlsHostRelative ( content ) ;
- 59 } else if ( this.urlValidationMode == 'absolute' ) {
- 60 // Trident always use absolute URL so we don't need to do anything.
- 61 //
- 62 // content = this.makeUrlsAbsolute(content);
- 63 }
- 64
- 65 return content ;
- 66 } ,
- 67
- 68 validateFontColor : function ( element ) {
- 69 var rdom = xq.RichDom.createInstance ( ) ;
- 70 rdom.setRoot ( element ) ;
- 71
- 72 // It should be reversed to deal with nested elements
- 73 var fonts = $A ( element.getElementsByTagName ( 'FONT' ) ) . reverse ( ) ;
- 74 for ( var i = 0 ; i < fonts.length ; i ++ ) {
- 75 var font = fonts [ i ] ;
- 76 var color = font.getAttribute ( 'color' ) ;
- 77
- 78 if ( color ) {
- 79 var span = rdom.replaceTag ( "span" , font ) ;
- 80 span.removeAttribute ( 'color' ) ;
- 81 span.style.color = color ;
- 82 }
- 83 }
- 84 } ,
- 85
- 86 invalidateFontColor : function ( element ) {
- 87 var rdom = xq.RichDom.createInstance ( ) ;
- 88 rdom.setRoot ( element ) ;
- 89
- 90 var spans = $A ( element.getElementsByTagName ( 'SPAN' ) ) . reverse ( ) ;
- 91 for ( var i = 0 ; i < spans.length ; i ++ ) {
- 92 var span = spans [ i ] ;
- 93 var color = span.style.color ;
- 94
- 95 if ( color ) {
- 96 var font = rdom.replaceTag ( "font" , span ) ;
- 97 font.style.color = "" ;
- 98 font.setAttribute ( 'color' , color ) ;
- 99 }
-100 }
-101 } ,
-102
-103 validateBackgroundColor : function ( element ) {
-104 var rdom = xq.RichDom.createInstance ( ) ;
-105 rdom.setRoot ( element ) ;
-106
-107 // It should be reversed to deal with nested elements
-108 var fonts = $A ( element.getElementsByTagName ( 'FONT' ) ) . reverse ( ) ;
-109 for ( var i = 0 ; i < fonts.length ; i ++ ) {
-110 if ( fonts [ i ] . style.color || fonts [ i ] . style.backgroundColor ) rdom.replaceTag ( "span" , fonts [ i ] ) ;
-111 }
-112 } ,
-113
-114 invalidateBackgroundColor : function ( element ) {
-115 var rdom = xq.RichDom.createInstance ( ) ;
-116 rdom.setRoot ( element ) ;
-117
-118 // It should be reversed to deal with nested elements
-119 var spans = $A ( element.getElementsByTagName ( 'SPAN' ) ) . reverse ( ) ;
-120 for ( var i = 0 ; i < spans.length ; i ++ ) {
-121 if ( spans [ i ] . style.color || spans [ i ] . style.backgroundColor ) rdom.replaceTag ( "font" , spans [ i ] ) ;
-122 }
-123 } ,
-124
-125 lowerTagNamesAndUniformizeQuotation : function ( content ) {
-126 // Uniformize quotation, turn tag names and attribute names into lower case
-127 content = content.replace ( /<(\/?)(\w+)([^>]*?)>/img , function ( str , closingMark , tagName , attrs ) {
-128 return "<" + closingMark + tagName.toLowerCase ( ) + this.correctHtmlAttrQuotation ( attrs ) + ">" ;
-129 } . bind ( this ) ) ;
-130
-131 return content ;
-132 } ,
-133
-134 correctHtmlAttrQuotation : function ( html ) {
-135 html = html.replace ( /\s(\w+?)=\s+"([^"]+)"/mg , function ( str , name , value ) { return " " + name.toLowerCase ( ) + '=' + '"' + value + '"' } ) ;
-136 html = html.replace ( /\s(\w+?)=([^ "]+)/mg , function ( str , name , value ) { return " " + name.toLowerCase ( ) + '=' + '"' + value + '"' } ) ;
-137 return html ;
-138 }
-139 } ) ;
-140
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_16.html b/modules/editor/skins/xquared/doc/api/src_16.html
deleted file mode 100644
index eacdef1b9..000000000
--- a/modules/editor/skins/xquared/doc/api/src_16.html
+++ /dev/null
@@ -1,112 +0,0 @@
- 1 /**
- 2 * Validator for W3C Standard Engine
- 3 */
- 4 xq.ValidatorW3 = Class.create ( xq.Validator , {
- 5 validate : function ( element , fullValidation ) {
- 6 element = element.cloneNode ( true ) ;
- 7
- 8 var rdom = xq.RichDom.createInstance ( ) ;
- 9 rdom.setRoot ( element ) ;
- 10 rdom.removePlaceHoldersAndEmptyNodes ( element ) ;
- 11 this.removeDangerousElements ( element ) ;
- 12 this.validateFontColor ( element ) ;
- 13
- 14 var content = element.innerHTML ;
- 15
- 16 try {
- 17 content = this.replaceTag ( content , "b" , "strong" ) ;
- 18 content = this.replaceTag ( content , "i" , "em" ) ;
- 19
- 20 content = this.validateStrike ( content ) ;
- 21 content = this.validateUnderline ( content ) ;
- 22 content = this.addNbspToEmptyBlocks ( content ) ;
- 23
- 24 if ( fullValidation ) content = this.performFullValidation ( content ) ;
- 25 } catch ( ignored ) { }
- 26
- 27 // insert newline between block-tags
- 28 var blocks = rdom.tree.getBlockTags ( ) . join ( "|" ) ;
- 29 var regex = new RegExp ( "</(" + blocks + ")>([^\n])" , "img" ) ;
- 30 content = content.replace ( regex , '</$1>\n$2' ) ;
- 31
- 32 return content ;
- 33 } ,
- 34 invalidate : function ( element ) {
- 35 var rdom = xq.RichDom.createInstance ( ) ;
- 36 rdom.setRoot ( element ) ;
- 37
- 38 // <span class="strike"> -> <strike>
- 39 var strikes = rdom.findByAttribute ( "class" , "strike" ) ;
- 40 for ( var i = 0 ; i < strikes.length ; i ++ ) {
- 41 if ( "SPAN" == strikes [ i ] . nodeName ) rdom.replaceTag ( "strike" , strikes [ i ] ) . removeAttribute ( "class" ) ;
- 42 }
- 43
- 44 // <em|i class="underline"> -> <u>
- 45 var underlines = rdom.findByAttribute ( "class" , "underline" ) ;
- 46 for ( var i = 0 ; i < underlines.length ; i ++ ) {
- 47 if ( [ "EM" , "I" ] . include ( underlines [ i ] . nodeName ) ) rdom.replaceTag ( "u" , underlines [ i ] ) . removeAttribute ( "class" ) ;
- 48 }
- 49
- 50 var content = rdom.getRoot ( ) . innerHTML ;
- 51
- 52 content = this.replaceTag ( content , "strong" , "b" ) ;
- 53 content = this.replaceTag ( content , "em" , "i" ) ;
- 54 content = this.removeComments ( content ) ;
- 55 content = this.replaceNbspToBr ( content ) ;
- 56
- 57 return content ;
- 58 } ,
- 59
- 60 performFullValidation : function ( content ) {
- 61 content = this.validateSelfClosingTags ( content ) ;
- 62 content = this.applyWhitelist ( content ) ;
- 63
- 64 if ( this.urlValidationMode == 'relative' ) {
- 65 content = this.makeUrlsRelative ( content ) ;
- 66 } else if ( this.urlValidationMode == 'host_relative' ) {
- 67 content = this.makeUrlsHostRelative ( content ) ;
- 68 } else if ( this.urlValidationMode == 'absolute' ) {
- 69 content = this.makeUrlsAbsolute ( content ) ;
- 70 }
- 71
- 72 return content ;
- 73 } ,
- 74
- 75 validateFontColor : function ( element ) {
- 76 var rdom = xq.RichDom.createInstance ( ) ;
- 77 rdom.setRoot ( element ) ;
- 78
- 79 var fonts = $A ( element.getElementsByTagName ( 'FONT' ) ) . reverse ( ) ;
- 80 for ( var i = 0 ; i < fonts.length ; i ++ ) {
- 81 var font = fonts [ i ] ;
- 82 var color = font.getAttribute ( 'color' ) ;
- 83
- 84 if ( color ) {
- 85 var span = rdom.replaceTag ( "span" , font ) ;
- 86 span.removeAttribute ( 'color' ) ;
- 87 span.style.color = color ;
- 88 }
- 89 }
- 90 } ,
- 91
- 92 addNbspToEmptyBlocks : function ( content ) {
- 93 var blocks = new xq.DomTree ( ) . getBlockTags ( ) . join ( "|" ) ;
- 94 var regex = new RegExp ( "<(" + blocks + ")>\\s*?</(" + blocks + ")>" , "img" ) ;
- 95 return content.replace ( regex , '<$1> </$2>' ) ;
- 96 } ,
- 97
- 98 replaceNbspToBr : function ( content ) {
- 99 var blocks = new xq.DomTree ( ) . getBlockTags ( ) . join ( "|" ) ;
-100 var regex = new RegExp ( "<(" + blocks + ")>( )?</(" + blocks + ")>" , "img" ) ;
-101 var rdom = xq.RichDom.createInstance ( ) ;
-102 return content.replace ( regex , '<$1>' + rdom.makePlaceHolderString ( ) + '</$3>' ) ;
-103 }
-104 } ) ;
-105
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_17.html b/modules/editor/skins/xquared/doc/api/src_17.html
deleted file mode 100644
index b07ebbc67..000000000
--- a/modules/editor/skins/xquared/doc/api/src_17.html
+++ /dev/null
@@ -1,21 +0,0 @@
- 1 /**
- 2 * Validator for Webkit
- 3 */
- 4 xq.ValidatorWebkit = Class.create ( xq.ValidatorW3 , {
- 5 } ) ;
- 6
- 7 /*
- 8 if(node.nodeName == "SPAN" && node.className == "Apple-style-span" && node.style.fontStyle == "italic") em = true;
- 9 if(node.nodeName == "SPAN" && node.className == "Apple-style-span" && node.style.fontWeight == "bold") strong = true;
- 10 if(node.nodeName == "SPAN" && node.className == "Apple-style-span" && node.style.textDecoration == "line-through") strike = true;
- 11 if(node.nodeName == "SPAN" && node.className == "Apple-style-span" && node.style.textDecoration == "underline") underline = true;
- 12 if(node.nodeName == "SPAN" && node.className == "Apple-style-span" && node.style.cssText.indexOf("vertical-align: super;") != -1) superscription = true;
- 13 if(node.nodeName == "SPAN" && node.className == "Apple-style-span" && node.style.cssText.indexOf("vertical-align: sub;") != -1) subscription = true;
- 14 */
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_18.html b/modules/editor/skins/xquared/doc/api/src_18.html
deleted file mode 100644
index 5fa6b1885..000000000
--- a/modules/editor/skins/xquared/doc/api/src_18.html
+++ /dev/null
@@ -1,157 +0,0 @@
- 1 /**
- 2 * Namespace for entire Xquared classes
- 3 */
- 4 var xq = {
- 5 majorVersion : '0.1' ,
- 6 minorVersion : '2007119'
- 7 } ;
- 8
- 9 /**
- 10 * Make given object as event source
- 11 *
- 12 * @param {Object} object target object
- 13 * @param {String} prefix prefix for generated functions
- 14 * @param {Array} events array of string which contains name of events
- 15 */
- 16 xq.asEventSource = function ( object , prefix , events ) {
- 17 object._listeners = [ ]
- 18 object._registerEventFirer = function ( prefix , name ) {
- 19 this [ "_fireOn" + name ] = function ( ) {
- 20 for ( var i = 0 ; i < this._listeners.length ; i ++ ) {
- 21 var listener = this._listeners [ i ] ;
- 22 var func = listener [ "on" + prefix + name ] ;
- 23 if ( func ) func.apply ( listener , $A ( arguments ) ) ;
- 24 }
- 25 }
- 26 }
- 27 object.addListener = function ( l ) {
- 28 this._listeners.push ( l ) ;
- 29 }
- 30
- 31 for ( var i = 0 ; i < events.length ; i ++ ) {
- 32 object._registerEventFirer ( prefix , events [ i ] ) ;
- 33 }
- 34 }
- 35
- 36 /**
- 37 * Returns the index of given element
- 38 *
- 39 * @returns {Number} index or -1
- 40 */
- 41 Array.prototype.indexOf = function ( n ) {
- 42 for ( var i = 0 ; i < this.length ; i ++ ) {
- 43 if ( this [ i ] == n ) return i ;
- 44 }
- 45
- 46 return - 1 ;
- 47 }
- 48
- 49 Date.preset = null ;
- 50 Date.pass = function ( msec ) {
- 51 if ( Date.preset == null ) return ;
- 52 Date.preset = new Date ( Date.preset.getTime ( ) + msec ) ;
- 53 }
- 54 Date.get = function ( ) {
- 55 return Date.preset == null ? new Date ( ) : Date.preset ;
- 56 }
- 57 Date.prototype.elapsed = function ( msec ) {
- 58 return Date.get ( ) . getTime ( ) - this.getTime ( ) >= msec ;
- 59 }
- 60
- 61 String.prototype.merge = function ( data ) {
- 62 var newString = this ;
- 63 for ( k in data ) {
- 64 newString = newString.replace ( "{" + k + "}" , data [ k ] ) ;
- 65 }
- 66 return newString ;
- 67 }
- 68
- 69 String.prototype.parseURL = function ( ) {
- 70 var m = this.match ( /((((\w+):\/\/(((([^@:]+)(:([^@]+))?)@)?([^:\/\?#]+)?(:(\d+))?))?([^\?#]+)?)(\?([^#]+))?)(#(.+))?/ ) ;
- 71
- 72 var includeAnchor = m [ 0 ] ;
- 73 var includeQuery = m [ 1 ] || undefined ;
- 74 var includePath = m [ 2 ] || undefined ;
- 75 var includeHost = m [ 3 ] || undefined ;
- 76 var includeBase = null ;
- 77 var protocol = m [ 4 ] || undefined ;
- 78 var user = m [ 8 ] || undefined ;
- 79 var password = m [ 10 ] || undefined ;
- 80 var domain = m [ 11 ] || undefined ;
- 81 var port = m [ 13 ] || undefined ;
- 82 var path = m [ 14 ] || undefined ;
- 83 var query = m [ 16 ] || undefined ;
- 84 var anchor = m [ 18 ] || undefined ;
- 85
- 86 if ( ! path || path == '/' ) {
- 87 includeBase = includeHost + '/' ;
- 88 } else {
- 89 var index = path.lastIndexOf ( '/' ) ;
- 90 includeBase = includeHost + path.substring ( 0 , index + 1 ) ;
- 91 }
- 92
- 93 return {
- 94 includeAnchor : includeAnchor ,
- 95 includeQuery : includeQuery ,
- 96 includePath : includePath ,
- 97 includeBase : includeBase ,
- 98 includeHost : includeHost ,
- 99 protocol : protocol ,
-100 user : user ,
-101 password : password ,
-102 domain : domain ,
-103 port : port ,
-104 path : path ,
-105 query : query ,
-106 anchor : anchor
-107 } ;
-108 }
-109
-110 xq.findXquaredScript = function ( ) {
-111 return $A ( document.getElementsByTagName ( "script" ) ) . find ( function ( script ) {
-112 return script.src && script.src.match ( /xquared\.js/i ) ;
-113 } ) ;
-114 }
-115 xq.shouldLoadOthers = function ( ) {
-116 var script = xq.findXquaredScript ( ) ;
-117 return script && ! ! script.src.match ( /xquared\.js\?load_others=1/i ) ;
-118 }
-119 xq.loadScript = function ( url ) {
-120 document.write ( '<script type="text/javascript" src="' + url + '"></script>' ) ;
-121 }
-122 xq.loadOthers = function ( ) {
-123 var script = xq.findXquaredScript ( ) ;
-124 var basePath = script.src.match ( /(.*\/)xquared\.js.*/i ) [ 1 ] ;
-125 var others = [
-126 'Editor.js' ,
-127 'Browser.js' ,
-128 'Shortcut.js' ,
-129 'DomTree.js' ,
-130 'RichDom.js' ,
-131 'RichDomW3.js' ,
-132 'RichDomGecko.js' ,
-133 'RichDomWebkit.js' ,
-134 'RichDomTrident.js' ,
-135 'RichTable.js' ,
-136 'Validator.js' ,
-137 'ValidatorW3.js' ,
-138 'ValidatorGecko.js' ,
-139 'ValidatorWebkit.js' ,
-140 'ValidatorTrident.js' ,
-141 'EditHistory.js' ,
-142 'Controls.js' ,
-143 '_ui_templates.js'
-144 ] ;
-145 others.each ( function ( name ) {
-146 xq.loadScript ( basePath + name ) ;
-147 } ) ;
-148 }
-149
-150 if ( xq.shouldLoadOthers ( ) ) xq.loadOthers ( ) ;
\ No newline at end of file
diff --git a/modules/editor/skins/xquared/doc/api/src_19.html b/modules/editor/skins/xquared/doc/api/src_19.html
deleted file mode 100644
index feb2f6a4e..000000000
--- a/modules/editor/skins/xquared/doc/api/src_19.html
+++ /dev/null
@@ -1,16 +0,0 @@
- 1 if ( ! xq ) xq = { } ;
- 2 if ( ! xq.ui_templates ) xq.ui_templates = { } ;
- 3
- 4 xq.ui_templates.basicColorPickerDialog = '<form action="#" class="xqFormDialog xqBasicColorPickerDialog">\n <div>\n <label>\n <input type="radio" class="initialFocus" name="color" value="black" checked="checked" />\n <span style="color: black;">Black</span>\n </label>\n <label>\n <input type="radio" name="color" value="red" />\n <span style="color: red;">Red</span>\n </label>\n <input type="radio" name="color" value="yellow" />\n <span style="color: yellow;">Yellow</span>\n </label>\n </label>\n <input type="radio" name="color" value="pink" />\n <span style="color: pink;">Pink</span>\n </label>\n <label>\n <input type="radio" name="color" value="blue" />\n <span style="color: blue;">Blue</span>\n </label>\n <label>\n <input type="radio" name="color" value="green" />\n <span style="color: green;">Green</span>\n </label>\n \n <input type="submit" value="Ok" />\n <input type="button" class="cancel" value="Cancel" />\n </div>\n </form>' ;
- 5 if ( ! xq ) xq = { } ;
- 6 if ( ! xq.ui_templates ) xq.ui_templates = { } ;
- 7
- 8 xq.ui_templates.basicLinkDialog = '<form action="#" class="xqFormDialog xqBasicLinkDialog">\n <h3>Link</h3>\n <div>\n <input type="text" class="initialFocus" name="text" value="" />\n <input type="text" name="url" value="http://" />\n \n <input type="submit" value="Ok" />\n <input type="button" class="cancel" value="Cancel" />\n </div>\n </form>' ;
- 9
\ No newline at end of file