diff options
-rwxr-xr-x | js/document/document-html.js | 229 |
1 files changed, 13 insertions, 216 deletions
diff --git a/js/document/document-html.js b/js/document/document-html.js index ec59c3e2..deca9f83 100755 --- a/js/document/document-html.js +++ b/js/document/document-html.js | |||
@@ -30,6 +30,11 @@ exports.HtmlDocument = Montage.create(Component, { | |||
30 | }, | 30 | }, |
31 | //////////////////////////////////////////////////////////////////// | 31 | //////////////////////////////////////////////////////////////////// |
32 | // | 32 | // |
33 | _observer: { | ||
34 | value: null | ||
35 | }, | ||
36 | //////////////////////////////////////////////////////////////////// | ||
37 | // | ||
33 | _document: { | 38 | _document: { |
34 | value: null //TODO: Figure out if this will be needed, probably not | 39 | value: null //TODO: Figure out if this will be needed, probably not |
35 | }, | 40 | }, |
@@ -80,7 +85,7 @@ exports.HtmlDocument = Montage.create(Component, { | |||
80 | this.model.views.design.show(); | 85 | this.model.views.design.show(); |
81 | this.model.views.design.iframe.style.opacity = 0; | 86 | this.model.views.design.iframe.style.opacity = 0; |
82 | this.model.views.design.content = this.model.file.content; | 87 | this.model.views.design.content = this.model.file.content; |
83 | // | 88 | //TODO: Clean up |
84 | this.model.views.design.render(function () { | 89 | this.model.views.design.render(function () { |
85 | //TODO: Identify and remove usage of '_document' | 90 | //TODO: Identify and remove usage of '_document' |
86 | this._document = this.model.views.design.document; | 91 | this._document = this.model.views.design.document; |
@@ -90,8 +95,9 @@ exports.HtmlDocument = Montage.create(Component, { | |||
90 | this._liveNodeList = this.documentRoot.getElementsByTagName('*'); | 95 | this._liveNodeList = this.documentRoot.getElementsByTagName('*'); |
91 | //Initiliazing document model | 96 | //Initiliazing document model |
92 | document.application.njUtils.makeElementModel(this.documentRoot, "Body", "body"); | 97 | document.application.njUtils.makeElementModel(this.documentRoot, "Body", "body"); |
93 | //Adding event to know when template is ready | 98 | //Adding observer to know when template is ready |
94 | this.model.views.design.document.head.addEventListener('DOMSubtreeModified', this.handleTemplateReady.bind(this), false); | 99 | this._observer = new WebKitMutationObserver(this.handleTemplateReady.bind(this)); |
100 | this._observer.observe(this.model.views.design.document.head, {childList: true}); | ||
95 | }.bind(this)); | 101 | }.bind(this)); |
96 | } else { | 102 | } else { |
97 | //TODO: Identify default view (probably code) | 103 | //TODO: Identify default view (probably code) |
@@ -102,226 +108,17 @@ exports.HtmlDocument = Montage.create(Component, { | |||
102 | // | 108 | // |
103 | handleTemplateReady: { | 109 | handleTemplateReady: { |
104 | value: function (e) { | 110 | value: function (e) { |
105 | //Removing event listener, a must for this type of event | 111 | //Removing observer, only needed on initial load |
106 | this.model.views.design.document.head.removeEventListener('DOMSubtreeModified', this.handleTemplateReady.bind(this), false); | 112 | this._observer.disconnect(); |
113 | this._observer = null; | ||
107 | //Making callback after view is loaded | 114 | //Making callback after view is loaded |
108 | this.loaded.callback.call(this.loaded.context, this); | 115 | this.loaded.callback.call(this.loaded.context, this); |
109 | //Setting opacity to be viewable after load | 116 | //Setting opacity to be viewable after load |
110 | this.model.views.design.iframe.style.opacity = 1; | 117 | this.model.views.design.iframe.style.opacity = 1; |
111 | } | 118 | } |
112 | }, | 119 | } |
113 | //////////////////////////////////////////////////////////////////// | 120 | //////////////////////////////////////////////////////////////////// |
114 | //////////////////////////////////////////////////////////////////// | 121 | //////////////////////////////////////////////////////////////////// |
115 | |||
116 | |||
117 | |||
118 | |||
119 | |||
120 | |||
121 | |||
122 | |||
123 | |||
124 | |||
125 | |||
126 | |||
127 | |||
128 | |||
129 | |||
130 | |||
131 | |||
132 | |||
133 | |||
134 | |||
135 | |||
136 | |||
137 | |||
138 | |||
139 | |||
140 | |||
141 | |||
142 | |||
143 | |||
144 | |||
145 | |||
146 | |||
147 | |||
148 | |||
149 | |||
150 | handleWebTemplateLoad: { | ||
151 | value: function(event) { | ||
152 | //TODO: Remove, also for prototyping | ||
153 | this.application.ninja.documentController._hackRootFlag = true; | ||
154 | |||
155 | this._window = this.iframe.contentWindow; | ||
156 | this._document = this.iframe.contentWindow.document; | ||
157 | this.documentRoot = this.iframe.contentWindow.document.body; | ||
158 | |||
159 | for (var k in this._document.styleSheets) { | ||
160 | if (this._document.styleSheets[k].ownerNode && this._document.styleSheets[k].ownerNode.setAttribute) { | ||
161 | this._document.styleSheets[k].ownerNode.setAttribute('data-ninja-template', 'true'); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | // Live node list of the current loaded document | ||
166 | this._liveNodeList = this.documentRoot.getElementsByTagName('*'); | ||
167 | |||
168 | |||
169 | setTimeout(function () { | ||
170 | |||
171 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
172 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
173 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
174 | if(this._document.styleSheets.length) { | ||
175 | //Checking all styleSheets in document | ||
176 | for (var i in this._document.styleSheets) { | ||
177 | //If rules are null, assuming cross-origin issue | ||
178 | if(this._document.styleSheets[i].rules === null) { | ||
179 | //TODO: Revisit URLs and URI creation logic, very hack right now | ||
180 | var fileUri, cssUrl, cssData, query, prefixUrl, fileCouldDirUrl, docRootUrl; | ||
181 | // | ||
182 | docRootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]).replace(/\/\//gi, '/')); | ||
183 | //TODO: Parse out relative URLs and map them to absolute | ||
184 | if (this._document.styleSheets[i].href.indexOf(this.application.ninja.coreIoApi.rootUrl) !== -1) { | ||
185 | // | ||
186 | cssUrl = this._document.styleSheets[i].href.split(this.application.ninja.coreIoApi.rootUrl)[1]; | ||
187 | fileUri = this.application.ninja.coreIoApi.cloudData.root+cssUrl; | ||
188 | //TODO: Add error handling for reading file | ||
189 | cssData = this.application.ninja.coreIoApi.readFile({uri: fileUri}); | ||
190 | // | ||
191 | var tag = this.iframe.contentWindow.document.createElement('style'); | ||
192 | tag.setAttribute('type', 'text/css'); | ||
193 | tag.setAttribute('data-ninja-uri', fileUri); | ||
194 | tag.setAttribute('data-ninja-file-url', cssUrl); | ||
195 | tag.setAttribute('data-ninja-file-read-only', JSON.parse(this.application.ninja.coreIoApi.isFileWritable({uri: fileUri}).content).readOnly); | ||
196 | tag.setAttribute('data-ninja-file-name', cssUrl.split('/')[cssUrl.split('/').length-1]); | ||
197 | //Copying attributes to maintain same properties as the <link> | ||
198 | for (var n in this._document.styleSheets[i].ownerNode.attributes) { | ||
199 | if (this._document.styleSheets[i].ownerNode.attributes[n].value && this._document.styleSheets[i].ownerNode.attributes[n].name !== 'disabled' && this._document.styleSheets[i].ownerNode.attributes[n].name !== 'disabled') { | ||
200 | if (this._document.styleSheets[i].ownerNode.attributes[n].value.indexOf(docRootUrl) !== -1) { | ||
201 | tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value.split(docRootUrl)[1]); | ||
202 | } else { | ||
203 | tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value); | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | // | ||
208 | fileCouldDirUrl = this._document.styleSheets[i].href.split(this._document.styleSheets[i].href.split('/')[this._document.styleSheets[i].href.split('/').length-1])[0]; | ||
209 | |||
210 | //TODO: Make public version of this.application.ninja.ioMediator.getNinjaPropUrlRedirect with dynamic ROOT | ||
211 | tag.innerHTML = cssData.content.replace(/url\(()(.+?)\1\)/g, detectUrl); | ||
212 | |||
213 | function detectUrl (prop) { | ||
214 | return prop.replace(/[^()\\""\\'']+/g, prefixUrl);; | ||
215 | } | ||
216 | |||
217 | function prefixUrl (url) { | ||
218 | if (url !== 'url') { | ||
219 | if (!url.match(/(\b(?:(?:https?|ftp|file|[A-Za-z]+):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$]))/gi)) { | ||
220 | url = fileCouldDirUrl+url; | ||
221 | } | ||
222 | } | ||
223 | return url; | ||
224 | } | ||
225 | |||
226 | //Looping through DOM to insert style tag at location of link element | ||
227 | query = this._templateDocument.html.querySelectorAll(['link']); | ||
228 | for (var j in query) { | ||
229 | if (query[j].href === this._document.styleSheets[i].href) { | ||
230 | //Disabling style sheet to reload via inserting in style tag | ||
231 | query[j].setAttribute('disabled', 'true'); | ||
232 | //Inserting tag | ||
233 | this._templateDocument.head.insertBefore(tag, query[j]); | ||
234 | } | ||
235 | } | ||
236 | } else { | ||
237 | console.log('ERROR: Cross-Domain-Stylesheet detected, unable to load in Ninja'); | ||
238 | //None local stylesheet, probably on a CDN (locked) | ||
239 | var tag = this.iframe.contentWindow.document.createElement('style'); | ||
240 | tag.setAttribute('type', 'text/css'); | ||
241 | tag.setAttribute('data-ninja-external-url', this._document.styleSheets[i].href); | ||
242 | tag.setAttribute('data-ninja-file-read-only', "true"); | ||
243 | tag.setAttribute('data-ninja-file-name', this._document.styleSheets[i].href.split('/')[this._document.styleSheets[i].href.split('/').length-1]); | ||
244 | //Copying attributes to maintain same properties as the <link> | ||
245 | for (var n in this._document.styleSheets[i].ownerNode.attributes) { | ||
246 | if (this._document.styleSheets[i].ownerNode.attributes[n].value && this._document.styleSheets[i].ownerNode.attributes[n].name !== 'disabled' && this._document.styleSheets[i].ownerNode.attributes[n].name !== 'disabled') { | ||
247 | if (this._document.styleSheets[i].ownerNode.attributes[n].value.indexOf(docRootUrl) !== -1) { | ||
248 | tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value.split(docRootUrl)[1]); | ||
249 | } else { | ||
250 | tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value); | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | /* | ||
255 | |||
256 | //TODO: Figure out cross-domain XHR issue, might need cloud to handle | ||
257 | var xhr = new XMLHttpRequest(); | ||
258 | xhr.open("GET", this._document.styleSheets[i].href, true); | ||
259 | xhr.send(); | ||
260 | // | ||
261 | if (xhr.readyState === 4) { | ||
262 | console.log(xhr); | ||
263 | } | ||
264 | //tag.innerHTML = xhr.responseText //xhr.response; | ||
265 | */ | ||
266 | //Temp rule so it's registered in the array | ||
267 | tag.innerHTML = 'noRULEjustHACK{background: #000}'; | ||
268 | //Disabling external style sheets | ||
269 | query = this._templateDocument.html.querySelectorAll(['link']); | ||
270 | for (var k in query) { | ||
271 | if (query[k].href === this._document.styleSheets[i].href) { | ||
272 | |||
273 | //TODO: Removed the temp insertion of the stylesheet | ||
274 | //because it wasn't the proper way to do it | ||
275 |