diff options
Diffstat (limited to 'js/document/document-html.js')
-rwxr-xr-x | js/document/document-html.js | 304 |
1 files changed, 301 insertions, 3 deletions
diff --git a/js/document/document-html.js b/js/document/document-html.js index b48e004a..8cb88516 100755 --- a/js/document/document-html.js +++ b/js/document/document-html.js | |||
@@ -6,8 +6,9 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot | |||
6 | 6 | ||
7 | //////////////////////////////////////////////////////////////////////// | 7 | //////////////////////////////////////////////////////////////////////// |
8 | // | 8 | // |
9 | var Montage = require("montage/core/core").Montage, | 9 | var Montage = require("montage/core/core").Montage, |
10 | Component = require("montage/ui/component").Component; | 10 | Component = require("montage/ui/component").Component; |
11 | HtmlDocumentModel = require("js/document/models/html").HtmlDocumentModel; | ||
11 | //////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////// |
12 | // | 13 | // |
13 | exports.HtmlDocument = Montage.create(Component, { | 14 | exports.HtmlDocument = Montage.create(Component, { |
@@ -16,9 +17,306 @@ exports.HtmlDocument = Montage.create(Component, { | |||
16 | hasTemplate: { | 17 | hasTemplate: { |
17 | enumerable: false, | 18 | enumerable: false, |
18 | value: false | 19 | value: false |
19 | } | 20 | }, |
21 | |||
22 | model: { | ||
23 | value: null | ||
24 | }, | ||
25 | |||
26 | loadDelegate: { | ||
27 | value: null | ||
28 | }, | ||
29 | |||
30 | delegateContext: { | ||
31 | value: null | ||
32 | }, | ||
33 | |||
34 | // Getters for the model. | ||
35 | // TODO: Change how these properties are accessed through Ninja | ||
36 | name: { | ||
37 | get: function() { | ||
38 | return this.model._name; | ||
39 | }, | ||
40 | set: function(value) { | ||
41 | this.model._name = value; | ||
42 | } | ||
43 | }, | ||
44 | |||
45 | // View Properties | ||
46 | // TODO: Move those into a view object - for now dump it here | ||
47 | iframe: { | ||
48 | value: null | ||
49 | }, | ||
50 | |||
51 | uuid: { | ||
52 | get: function() { | ||
53 | return this._uuid; | ||
54 | } | ||
55 | }, | ||
20 | //////////////////////////////////////////////////////////////////// | 56 | //////////////////////////////////////////////////////////////////// |
21 | //////////////////////////////////////////////////////////////////// | 57 | //////////////////////////////////////////////////////////////////// |
58 | init: { | ||
59 | value:function(file, context, callback) { | ||
60 | this.model = Montage.create(HtmlDocumentModel, { | ||
61 | file: { | ||
62 | value: file | ||
63 | } | ||
64 | }); | ||
65 | |||
66 | this.name = file.name; | ||
67 | |||
68 | // this.init(file.name, file.uri, file.extension, iframe, uuid, callback); | ||
69 | |||
70 | |||
71 | this.iframe = this.createView(); | ||
72 | |||
73 | //this.selectionExclude = ["HTML", "BODY", "Viewport", "UserContent", "stageBG"]; | ||
74 | //this.currentView = "design"; | ||
75 | // | ||
76 | |||
77 | this.delegateContext = context; | ||
78 | this.loadDelegate = callback; | ||
79 | } | ||
80 | }, | ||
81 | |||
82 | // Create View | ||
83 | // Move this into a base view object | ||
84 | createView: { | ||
85 | value: function() { | ||
86 | var ifr = document.createElement("iframe"); | ||
87 | ifr.id = "document_" + this._uuid; | ||
88 | |||
89 | |||
90 | ifr.style.border = "none"; | ||
91 | ifr.style.background = "#FFF"; | ||
92 | ifr.style.height = "100%"; | ||
93 | ifr.style.width = "100%"; | ||
94 | |||
95 | // TODO: Reable opacity to display only when done loading | ||
96 | // ifr.style.opacity = 0; | ||
97 | |||
98 | ifr.src = "js/document/templates/montage-web/index.html"; | ||
99 | ifr.addEventListener("load", this.handleWebTemplateLoad.bind(this), true); | ||
100 | |||
101 | return document.getElementById("iframeContainer").appendChild(ifr); | ||
102 | } | ||
103 | }, | ||
104 | |||
105 | handleWebTemplateLoad: { | ||
106 | value: function(event) { | ||
107 | //TODO: Remove, also for prototyping | ||
108 | this.application.ninja.documentController._hackRootFlag = true; | ||
109 | |||
110 | |||
111 | //TODO: Clean up, using for prototyping save | ||
112 | // this._templateDocument = {}; | ||
113 | // this._templateDocument.html = this.iframe.contentWindow.document; | ||
114 | // this._templateDocument.body = | ||
115 | |||
116 | this._window = this.iframe.contentWindow; | ||
117 | this._document = this.iframe.contentWindow.document; | ||
118 | this.documentRoot = this.iframe.contentWindow.document.body; | ||
119 | |||
120 | for (var k in this._document.styleSheets) { | ||
121 | if (this._document.styleSheets[k].ownerNode && this._document.styleSheets[k].ownerNode.setAttribute) { | ||
122 | this._document.styleSheets[k].ownerNode.setAttribute('data-ninja-template', 'true'); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | // TODO: We don't need this anymore -> need to setup the main container still | ||
127 | //Adding a handler for the main user document reel to finish loading | ||
128 | // this.documentRoot.addEventListener("userTemplateDidLoad", this.userTemplateDidLoad.bind(this), false); | ||
129 | |||
130 | // Live node list of the current loaded document | ||
131 | this._liveNodeList = this.documentRoot.getElementsByTagName('*'); | ||
132 | |||
133 | // TODO Move this to the appropriate location | ||
134 | /* | ||
135 | var len = this._liveNodeList.length; | ||
136 | |||
137 | for(var i = 0; i < len; i++) { | ||
138 | NJUtils.makeModelFromElement(this._liveNodeList[i]); | ||
139 | } | ||
140 | */ | ||
141 | |||
142 | setTimeout(function () { | ||
143 | |||
144 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
145 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
146 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
147 | if(this._document.styleSheets.length) { | ||
148 | //Checking all styleSheets in document | ||
149 | for (var i in this._document.styleSheets) { | ||
150 | //If rules are null, assuming cross-origin issue | ||
151 | if(this._document.styleSheets[i].rules === null) { | ||
152 | //TODO: Revisit URLs and URI creation logic, very hack right now | ||
153 | var fileUri, cssUrl, cssData, query, prefixUrl, fileCouldDirUrl, docRootUrl; | ||
154 | // | ||
155 | docRootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]).replace(/\/\//gi, '/')); | ||
156 | //TODO: Parse out relative URLs and map them to absolute | ||
157 | if (this._document.styleSheets[i].href.indexOf(this.application.ninja.coreIoApi.rootUrl) !== -1) { | ||
158 | // | ||
159 | cssUrl = this._document.styleSheets[i].href.split(this.application.ninja.coreIoApi.rootUrl)[1]; | ||
160 | fileUri = this.application.ninja.coreIoApi.cloudData.root+cssUrl; | ||
161 | //TODO: Add error handling for reading file | ||
162 | cssData = this.application.ninja.coreIoApi.readFile({uri: fileUri}); | ||
163 | // | ||
164 | var tag = this.iframe.contentWindow.document.createElement('style'); | ||
165 | tag.setAttribute('type', 'text/css'); | ||
166 | tag.setAttribute('data-ninja-uri', fileUri); | ||
167 | tag.setAttribute('data-ninja-file-url', cssUrl); | ||
168 | tag.setAttribute('data-ninja-file-read-only', JSON.parse(this.application.ninja.coreIoApi.isFileWritable({uri: fileUri}).content).readOnly); | ||
169 | tag.setAttribute('data-ninja-file-name', cssUrl.split('/')[cssUrl.split('/').length-1]); | ||
170 | //Copying attributes to maintain same properties as the <link> | ||
171 | for (var n in this._document.styleSheets[i].ownerNode.attributes) { | ||
172 | 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') { | ||
173 | if (this._document.styleSheets[i].ownerNode.attributes[n].value.indexOf(docRootUrl) !== -1) { | ||
174 | tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value.split(docRootUrl)[1]); | ||
175 | } else { | ||
176 | tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value); | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | // | ||
181 | fileCouldDirUrl = this._document.styleSheets[i].href.split(this._document.styleSheets[i].href.split('/')[this._document.styleSheets[i].href.split('/').length-1])[0]; | ||
182 | |||
183 | //TODO: Make public version of this.application.ninja.ioMediator.getNinjaPropUrlRedirect with dynamic ROOT | ||
184 | tag.innerHTML = cssData.content.replace(/url\(()(.+?)\1\)/g, detectUrl); | ||
185 | |||
186 | function detectUrl (prop) { | ||
187 | return prop.replace(/[^()\\""\\'']+/g, prefixUrl);; | ||
188 | } | ||
189 | |||
190 | function prefixUrl (url) { | ||
191 | if (url !== 'url') { | ||
192 | 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)) { | ||
193 | url = fileCouldDirUrl+url; | ||
194 | } | ||
195 | } | ||
196 | return url; | ||
197 | } | ||
198 | |||
199 | //Looping through DOM to insert style tag at location of link element | ||
200 | query = this._templateDocument.html.querySelectorAll(['link']); | ||
201 | for (var j in query) { | ||
202 | if (query[j].href === this._document.styleSheets[i].href) { | ||
203 | //Disabling style sheet to reload via inserting in style tag | ||
204 | query[j].setAttribute('disabled', 'true'); | ||
205 | //Inserting tag | ||
206 | this._templateDocument.head.insertBefore(tag, query[j]); | ||
207 | } | ||
208 | } | ||
209 | } else { | ||
210 | console.log('ERROR: Cross-Domain-Stylesheet detected, unable to load in Ninja'); | ||
211 | //None local stylesheet, probably on a CDN (locked) | ||
212 | var tag = this.iframe.contentWindow.document.createElement('style'); | ||
213 | tag.setAttribute('type', 'text/css'); | ||
214 | tag.setAttribute('data-ninja-external-url', this._document.styleSheets[i].href); | ||
215 | tag.setAttribute('data-ninja-file-read-only', "true"); | ||
216 | tag.setAttribute('data-ninja-file-name', this._document.styleSheets[i].href.split('/')[this._document.styleSheets[i].href.split('/').length-1]); | ||
217 | //Copying attributes to maintain same properties as the <link> | ||
218 | for (var n in this._document.styleSheets[i].ownerNode.attributes) { | ||
219 | 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') { | ||
220 | if (this._document.styleSheets[i].ownerNode.attributes[n].value.indexOf(docRootUrl) !== -1) { | ||
221 | tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value.split(docRootUrl)[1]); | ||