]>
Commit | Line | Data |
---|---|---|
3b35bd27 IB |
1 | /** |
2 | * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. | |
7adcb81e IB |
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license |
4 | */ | |
5 | ||
6 | /** | |
7 | * @fileOverview Defines the {@link CKEDITOR.dom.document} class which | |
8 | * represents a DOM document. | |
9 | */ | |
10 | ||
11 | /** | |
12 | * Represents a DOM document. | |
13 | * | |
14 | * var document = new CKEDITOR.dom.document( document ); | |
15 | * | |
16 | * @class | |
17 | * @extends CKEDITOR.dom.domObject | |
18 | * @constructor Creates a document class instance. | |
19 | * @param {Object} domDocument A native DOM document. | |
20 | */ | |
21 | CKEDITOR.dom.document = function( domDocument ) { | |
22 | CKEDITOR.dom.domObject.call( this, domDocument ); | |
23 | }; | |
24 | ||
25 | // PACKAGER_RENAME( CKEDITOR.dom.document ) | |
26 | ||
27 | CKEDITOR.dom.document.prototype = new CKEDITOR.dom.domObject(); | |
28 | ||
29 | CKEDITOR.tools.extend( CKEDITOR.dom.document.prototype, { | |
30 | /** | |
31 | * The node type. This is a constant value set to {@link CKEDITOR#NODE_DOCUMENT}. | |
32 | * | |
33 | * @readonly | |
34 | * @property {Number} [=CKEDITOR.NODE_DOCUMENT] | |
35 | */ | |
36 | type: CKEDITOR.NODE_DOCUMENT, | |
37 | ||
38 | /** | |
39 | * Appends a CSS file to the document. | |
40 | * | |
41 | * CKEDITOR.document.appendStyleSheet( '/mystyles.css' ); | |
42 | * | |
43 | * @param {String} cssFileUrl The CSS file URL. | |
44 | */ | |
45 | appendStyleSheet: function( cssFileUrl ) { | |
46 | if ( this.$.createStyleSheet ) | |
47 | this.$.createStyleSheet( cssFileUrl ); | |
48 | else { | |
49 | var link = new CKEDITOR.dom.element( 'link' ); | |
50 | link.setAttributes( { | |
51 | rel: 'stylesheet', | |
52 | type: 'text/css', | |
53 | href: cssFileUrl | |
54 | } ); | |
55 | ||
56 | this.getHead().append( link ); | |
57 | } | |
58 | }, | |
59 | ||
60 | /** | |
61 | * Creates a CSS stylesheet and inserts it into the document. | |
62 | * | |
63 | * @param cssStyleText {String} CSS style text. | |
64 | * @returns {Object} The created DOM native stylesheet object. | |
65 | */ | |
66 | appendStyleText: function( cssStyleText ) { | |
67 | if ( this.$.createStyleSheet ) { | |
68 | var styleSheet = this.$.createStyleSheet( '' ); | |
69 | styleSheet.cssText = cssStyleText; | |
70 | } else { | |
71 | var style = new CKEDITOR.dom.element( 'style', this ); | |
72 | style.append( new CKEDITOR.dom.text( cssStyleText, this ) ); | |
73 | this.getHead().append( style ); | |
74 | } | |
75 | ||
76 | return styleSheet || style.$.sheet; | |
77 | }, | |
78 | ||
79 | /** | |
80 | * Creates a {@link CKEDITOR.dom.element} instance in this document. | |
81 | * | |
82 | * @param {String} name The name of the element. | |
83 | * @param {Object} [attributesAndStyles] | |
84 | * @param {Object} [attributesAndStyles.attributes] Attributes that will be set. | |
85 | * @param {Object} [attributesAndStyles.styles] Styles that will be set. | |
86 | * @returns {CKEDITOR.dom.element} | |
87 | */ | |
88 | createElement: function( name, attribsAndStyles ) { | |
89 | var element = new CKEDITOR.dom.element( name, this ); | |
90 | ||
91 | if ( attribsAndStyles ) { | |
92 | if ( attribsAndStyles.attributes ) | |
93 | element.setAttributes( attribsAndStyles.attributes ); | |
94 | ||
95 | if ( attribsAndStyles.styles ) | |
96 | element.setStyles( attribsAndStyles.styles ); | |
97 | } | |
98 | ||
99 | return element; | |
100 | }, | |
101 | ||
102 | /** | |
103 | * Creates a {@link CKEDITOR.dom.text} instance in this document. | |
104 | * | |
105 | * @param {String} text Value of the text node. | |
106 | * @returns {CKEDITOR.dom.element} | |
107 | */ | |
108 | createText: function( text ) { | |
109 | return new CKEDITOR.dom.text( text, this ); | |
110 | }, | |
111 | ||
112 | /** | |
113 | * Moves the selection focus to this document's window. | |
114 | */ | |
115 | focus: function() { | |
116 | this.getWindow().focus(); | |
117 | }, | |
118 | ||
119 | /** | |
120 | * Returns the element that is currently designated as the active element in the document. | |
121 | * | |
122 | * **Note:** Only one element can be active at a time in a document. | |
123 | * An active element does not necessarily have focus, | |
124 | * but an element with focus is always the active element in a document. | |
125 | * | |
126 | * @returns {CKEDITOR.dom.element} Active element or `null` if an IE8-9 bug is encountered. | |
127 | * See [#10030](http://dev.ckeditor.com/ticket/10030). | |
128 | */ | |
129 | getActive: function() { | |
130 | var $active; | |
131 | try { | |
132 | $active = this.$.activeElement; | |
133 | } catch ( e ) { | |
134 | return null; | |
135 | } | |
136 | return new CKEDITOR.dom.element( $active ); | |
137 | }, | |
138 | ||
139 | /** | |
140 | * Gets an element based on its ID. | |
141 | * | |
142 | * var element = CKEDITOR.document.getById( 'myElement' ); | |
143 | * alert( element.getId() ); // 'myElement' | |
144 | * | |
145 | * @param {String} elementId The element ID. | |
146 | * @returns {CKEDITOR.dom.element} The element instance, or `null` if not found. | |
147 | */ | |
148 | getById: function( elementId ) { | |
149 | var $ = this.$.getElementById( elementId ); | |
150 | return $ ? new CKEDITOR.dom.element( $ ) : null; | |
151 | }, | |
152 | ||
153 | /** | |
154 | * Gets a node based on its address. See {@link CKEDITOR.dom.node#getAddress}. | |
155 | * | |
156 | * @param {Array} address | |
157 | * @param {Boolean} [normalized=false] | |
158 | */ | |
159 | getByAddress: function( address, normalized ) { | |
160 | var $ = this.$.documentElement; | |
161 | ||
162 | for ( var i = 0; $ && i < address.length; i++ ) { | |
163 | var target = address[ i ]; | |
164 | ||
165 | if ( !normalized ) { | |
166 | $ = $.childNodes[ target ]; | |
167 | continue; | |
168 | } | |
169 | ||
170 | var currentIndex = -1; | |
171 | ||
172 | for ( var j = 0; j < $.childNodes.length; j++ ) { | |
173 | var candidate = $.childNodes[ j ]; | |
174 | ||
175 | if ( normalized === true && candidate.nodeType == 3 && candidate.previousSibling && candidate.previousSibling.nodeType == 3 ) | |
176 | continue; | |
177 | ||
178 | currentIndex++; | |
179 | ||
180 | if ( currentIndex == target ) { | |
181 | $ = candidate; | |
182 | break; | |
183 | } | |
184 | } | |
185 | } | |
186 | ||
187 | return $ ? new CKEDITOR.dom.node( $ ) : null; | |
188 | }, | |
189 | ||
190 | /** | |
191 | * Gets elements list based on a given tag name. | |
192 | * | |
193 | * @param {String} tagName The element tag name. | |
194 | * @returns {CKEDITOR.dom.nodeList} The nodes list. | |
195 | */ | |
196 | getElementsByTag: function( tagName, namespace ) { | |
197 | if ( !( CKEDITOR.env.ie && ( document.documentMode <= 8 ) ) && namespace ) | |
198 | tagName = namespace + ':' + tagName; | |
199 | return new CKEDITOR.dom.nodeList( this.$.getElementsByTagName( tagName ) ); | |
200 | }, | |
201 | ||
202 | /** | |
203 | * Gets the `<head>` element for this document. | |
204 | * | |
205 | * var element = CKEDITOR.document.getHead(); | |
206 | * alert( element.getName() ); // 'head' | |
207 | * | |
208 | * @returns {CKEDITOR.dom.element} The `<head>` element. | |
209 | */ | |
210 | getHead: function() { | |
211 | var head = this.$.getElementsByTagName( 'head' )[ 0 ]; | |
212 | if ( !head ) | |
213 | head = this.getDocumentElement().append( new CKEDITOR.dom.element( 'head' ), true ); | |
214 | else | |
215 | head = new CKEDITOR.dom.element( head ); | |
216 | ||
217 | return head; | |
218 | }, | |
219 | ||
220 | /** | |
221 | * Gets the `<body>` element for this document. | |
222 | * | |
223 | * var element = CKEDITOR.document.getBody(); | |
224 | * alert( element.getName() ); // 'body' | |
225 | * | |
226 | * @returns {CKEDITOR.dom.element} The `<body>` element. | |
227 | */ | |
228 | getBody: function() { | |
229 | return new CKEDITOR.dom.element( this.$.body ); | |
230 | }, | |
231 | ||
232 | /** | |
233 | * Gets the DOM document element for this document. | |
234 | * | |
235 | * @returns {CKEDITOR.dom.element} The DOM document element. | |
236 | */ | |
237 | getDocumentElement: function() { | |
238 | return new CKEDITOR.dom.element( this.$.documentElement ); | |
239 | }, | |
240 | ||
241 | /** | |
242 | * Gets the window object that stores this document. | |
243 | * | |
244 | * @returns {CKEDITOR.dom.window} The window object. | |
245 | */ | |
246 | getWindow: function() { | |
247 | return new CKEDITOR.dom.window( this.$.parentWindow || this.$.defaultView ); | |
248 | }, | |
249 | ||
250 | /** | |
251 | * Defines the document content through `document.write`. Note that the | |
252 | * previous document content will be lost (cleaned). | |
253 | * | |
254 | * document.write( | |
255 | * '<html>' + | |
256 | * '<head><title>Sample Document</title></head>' + | |
257 | * '<body>Document content created by code.</body>' + | |
258 | * '</html>' | |
259 | * ); | |
260 | * | |
261 | * @since 3.5 | |
262 | * @param {String} html The HTML defining the document content. | |
263 | */ | |
264 | write: function( html ) { | |
265 | // Don't leave any history log in IE. (#5657) | |
266 | this.$.open( 'text/html', 'replace' ); | |
267 | ||
268 | // Support for custom document.domain in IE. | |
269 | // | |
270 | // The script must be appended because if placed before the | |
271 | // doctype, IE will go into quirks mode and mess with | |
272 | // the editable, e.g. by changing its default height. | |
273 | if ( CKEDITOR.env.ie ) | |
274 | html = html.replace( /(?:^\s*<!DOCTYPE[^>]*?>)|^/i, '$&\n<script data-cke-temp="1">(' + CKEDITOR.tools.fixDomain + ')();</script>' ); | |
275 | ||
276 | this.$.write( html ); | |
277 | this.$.close(); | |
278 | }, | |
279 | ||
280 | /** | |
281 | * Wrapper for `querySelectorAll`. Returns a list of elements within this document that match | |
282 | * the specified `selector`. | |
283 | * | |
284 | * **Note:** The returned list is not a live collection (like the result of native `querySelectorAll`). | |
285 | * | |
286 | * @since 4.3 | |
287 | * @param {String} selector | |
288 | * @returns {CKEDITOR.dom.nodeList} | |
289 | */ | |
290 | find: function( selector ) { | |
291 | return new CKEDITOR.dom.nodeList( this.$.querySelectorAll( selector ) ); | |
292 | }, | |
293 | ||
294 | /** | |
295 | * Wrapper for `querySelector`. Returns the first element within this document that matches | |
296 | * the specified `selector`. | |
297 | * | |
298 | * @since 4.3 | |
299 | * @param {String} selector | |
300 | * @returns {CKEDITOR.dom.element} | |
301 | */ | |
302 | findOne: function( selector ) { | |
303 | var el = this.$.querySelector( selector ); | |
304 | ||
305 | return el ? new CKEDITOR.dom.element( el ) : null; | |
306 | }, | |
307 | ||
308 | /** | |
309 | * Internet Explorer 8 only method. It returns a document fragment which has all HTML5 elements enabled. | |
310 | * | |
311 | * @since 4.3 | |
312 | * @private | |
313 | * @returns DocumentFragment | |
314 | */ | |
315 | _getHtml5ShivFrag: function() { | |
316 | var $frag = this.getCustomData( 'html5ShivFrag' ); | |
317 | ||
318 | if ( !$frag ) { | |
319 | $frag = this.$.createDocumentFragment(); | |
320 | CKEDITOR.tools.enableHtml5Elements( $frag, true ); | |
321 | this.setCustomData( 'html5ShivFrag', $frag ); | |
322 | } | |
323 | ||
324 | return $frag; | |
325 | } | |
326 | } ); |