aboutsummaryrefslogtreecommitdiff
path: root/js/document/views/design.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/document/views/design.js')
-rwxr-xr-xjs/document/views/design.js399
1 files changed, 395 insertions, 4 deletions
diff --git a/js/document/views/design.js b/js/document/views/design.js
index 84871257..b3887fdf 100755
--- a/js/document/views/design.js
+++ b/js/document/views/design.js
@@ -7,16 +7,407 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot
7//////////////////////////////////////////////////////////////////////// 7////////////////////////////////////////////////////////////////////////
8// 8//
9var Montage = require("montage/core/core").Montage, 9var Montage = require("montage/core/core").Montage,
10 Component = require("montage/ui/component").Component, 10 BaseDocumentView = require("js/document/views/base").BaseDocumentView;
11 CodeDocumentView = require("js/document/views/code").CodeDocumentView;
12//////////////////////////////////////////////////////////////////////// 11////////////////////////////////////////////////////////////////////////
13// 12//
14exports.DesignDocumentView = Montage.create(CodeDocumentView, { 13exports.DesignDocumentView = Montage.create(BaseDocumentView, {
15 //////////////////////////////////////////////////////////////////// 14 ////////////////////////////////////////////////////////////////////
16 // 15 //
17 hasTemplate: { 16 hasTemplate: {
18 enumerable: false,
19 value: false 17 value: false
18 },
19 ////////////////////////////////////////////////////////////////////
20 //
21 _callback: {
22 value: null
23 },
24 ////////////////////////////////////////////////////////////////////
25 //
26 _template: {
27 value: null
28 },
29 ////////////////////////////////////////////////////////////////////
30 //
31 _document: {
32 value: null
33 },
34 ////////////////////////////////////////////////////////////////////
35 //
36 _bodyFragment: {
37 value: null
38 },
39 ////////////////////////////////////////////////////////////////////
40 //
41 _headFragment: {
42 value: null
43 },
44 ////////////////////////////////////////////////////////////////////
45 //
46 _observer: {
47 value: {head: null, body: null}
48 },
49 ////////////////////////////////////////////////////////////////////
50 //
51 content: {
52 value: null
53 },
54 ////////////////////////////////////////////////////////////////////
55 //TODO: Remove usage
56 model: {
57 value: null
58 },
59 ////////////////////////////////////////////////////////////////////
60 //
61 document: {
62 get: function() {return this._document;},
63 set: function(value) {this._document = value;}
64 },
65 ////////////////////////////////////////////////////////////////////
66 //
67 propertiesPanel: {
68 value: null
69 },
70 ////////////////////////////////////////////////////////////////////
71 //
72 initialize: {
73 value: function (parent) {
74 //Creating iFrame for view
75 this.iframe = document.createElement("iframe");
76 //Setting default styles
77 this.iframe.style.border = "none";
78 this.iframe.style.background = "#FFF";
79 this.iframe.style.height = "100%";
80 this.iframe.style.width = "100%";
81 //Returning reference to iFrame created
82 return parent.appendChild(this.iframe);
83 }
84 },
85 ////////////////////////////////////////////////////////////////////
86 //
87 render: {
88 value: function (callback, template) {
89 //TODO: Remove, this is a temp patch for webRequest API gate
90 this.application.ninja.documentController._hackRootFlag = false;
91 //Storing callback for dispatch ready
92 this._callback = callback;
93 this._template = template;
94 //Adding listener to know when template is loaded to then load user content
95 this.iframe.addEventListener("load", this.onTemplateLoad.bind(this), false);
96 //TODO: Add source parameter and root (optional)
97 if (template && template.type === 'banner' && template.size) {
98 this.iframe.src = "js/document/templates/banner/index.html";
99 } else {
100 this.iframe.src = "js/document/templates/html/index.html";
101 }
102 }
103 },
104 ////////////////////////////////////////////////////////////////////
105 //
106 onTemplateLoad: {
107 value: function (e) {
108 this.application.ninja.documentController._hackRootFlag = true;
109 //TODO: Add support to constructing URL with a base HREF
110 var basetag = this.content.document.getElementsByTagName('base');
111 //Removing event
112 this.iframe.removeEventListener("load", this.onTemplateLoad.bind(this), false);
113 //TODO: Improve usage of this reference
114 this.document = this.iframe.contentWindow.document;
115 //Looping through template styles and marking them with ninja data attribute for I/O clean up
116 for (var k in this.document.styleSheets) {
117 if (this.document.styleSheets[k].ownerNode && this.document.styleSheets[k].ownerNode.setAttribute) {
118 this.document.styleSheets[k].ownerNode.setAttribute('data-ninja-template', 'true');
119 }
120 }
121 //Checking for a base URL
122 if (basetag.length) {
123 if (basetag[basetag.length-1].getAttribute && basetag[basetag.length-1].getAttribute('href')) {
124 //Setting base HREF in model
125 this.model.baseHref = basetag[basetag.length-1].getAttribute('href');
126 }
127 }
128 //Checking to content to be template
129 if (this._template) {
130 if (this._template.type === 'banner') {
131 //Loading contents into a fragment
132 this._bodyFragment = this.document.createElement('body');
133 //Listening for content to be ready
134 this._observer.body = new WebKitMutationObserver(this.insertBannerContent.bind(this));
135 this._observer.body.observe(this._bodyFragment, {childList: true});
136 //Inserting <body> HTML and parsing URLs via mediator method
137 this._bodyFragment.innerHTML = '<ninjaloadinghack></ninjaloadinghack>'+(this.content.body.replace(/\b(href|src)\s*=\s*"([^"]*)"/g, this.application.ninja.ioMediator.getNinjaPropUrlRedirect.bind(this.application.ninja.ioMediator))).replace(/url\(([^"]*)(.+?)\1\)/g, this.application.ninja.ioMediator.getNinjaPropUrlRedirect.bind(this.application.ninja.ioMediator));
138 }
139 } else {
140 //Creating temp code fragement to load head
141 this._headFragment = this.document.createElement('head');
142 //Adding event listener to know when head is ready, event only dispatched once when using innerHTML
143 this._observer.head = new WebKitMutationObserver(this.insertHeadContent.bind(this));
144 this._observer.head.observe(this._headFragment, {childList: true});
145 //Inserting <head> HTML and parsing URLs via mediator method
146 this._headFragment.innerHTML = (this.content.head.replace(/\b(href|src)\s*=\s*"([^"]*)"/g, this.application.ninja.ioMediator.getNinjaPropUrlRedirect.bind(this.application.ninja.ioMediator))).replace(/url\(([^"]*)(.+?)\1\)/g, this.application.ninja.ioMediator.getNinjaPropUrlRedirect.bind(this.application.ninja.ioMediator));
147 //Adding event listener to know when the body is ready and make callback (using HTML5 new DOM Mutation Events)
148 this._observer.body = new WebKitMutationObserver(this.bodyContentLoaded.bind(this));
149 this._observer.body.observe(this.document.body, {childList: true});
150 //Inserting <body> HTML and parsing URLs via mediator method
151 this.document.body.innerHTML += '<ninjaloadinghack></ninjaloadinghack>'+(this.content.body.replace(/\b(href|src)\s*=\s*"([^"]*)"/g, this.application.ninja.ioMediator.getNinjaPropUrlRedirect.bind(this.application.ninja.ioMediator))).replace(/url\(([^"]*)(.+?)\1\)/g, this.application.ninja.ioMediator.getNinjaPropUrlRedirect.bind(this.application.ninja.ioMediator));
152 //Copying attributes to maintain same properties as the <body>
153 for (var n in this.content.document.body.attributes) {
154 if (this.content.document.body.attributes[n].value) {
155 this.document.body.setAttribute(this.content.document.body.attributes[n].name, this.content.document.body.attributes[n].value);
156 }
157 }
158 //TODO: Add attribute copying for <HEAD> and <HTML>
159 }
160 }
161 },
162 ////////////////////////////////////////////////////////////////////
163 //
164 insertBannerContent: {
165 value: function (e) {
166 //Getting first element in DOM (assumes it's root)
167 //TODO: Ensure wrapper logic is proper
168 var wrapper = this._bodyFragment.getElementsByTagName('*')[1],
169 banner = this._bodyFragment.getElementsByTagName('*')[2],
170 ninjaBanner = this.document.body.getElementsByTagName('ninja-content')[0],
171 ninjaWrapper = this.document.body.getElementsByTagName('ninja-viewport')[0];
172 //Copying attributes to maintain same properties as the banner wrapper
173 for (var n in wrapper.attributes) {
174 if (wrapper.attributes[n].value) {
175 ninjaWrapper.setAttribute(wrapper.attributes[n].name, wrapper.attributes[n].value);
176 }
177 }
178 //Copying attributes to maintain same properties as the banner content
179 for (var n in banner.attributes) {
180 if (banner.attributes[n].value) {
181 ninjaBanner.setAttribute(banner.attributes[n].name, banner.attributes[n].value);
182 }
183 }
184 //Adjusting margin per size of document
185 this.document.head.getElementsByTagName('style')[0].innerHTML += '\n ninja-viewport {overflow: visible !important;} ninja-content, ninja-viewport {width: ' + this._template.size.width + 'px; height: ' + this._template.size.height + 'px;}';
186 //Setting content in template
187 ninjaBanner.innerHTML = banner.innerHTML;
188 //Garbage collection
189 this._bodyFragment = null;
190 //Calling standard method to finish opening document
191 this.bodyContentLoaded(null);
192 //TODO: Move this to be set via the controller
193 this.application.ninja.stage.documentOffsetLeft = parseInt((this.document.body.scrollWidth - this._template.size.width)/2);
194 this.application.ninja.stage.documentOffsetTop = parseInt((this.document.body.scrollHeight - this._template.size.height)/2);
195 }
196 },
197 ////////////////////////////////////////////////////////////////////
198 //
199 insertHeadContent: {
200 value: function (e) {
201 //Removing event
202 this._observer.head.disconnect();
203 this._observer.head = null;
204 //Adding the loaded nodes from code fragment into actual document head
205 for(var i in this._headFragment.childNodes) {
206 //Minor hack to know node is actual HTML node
207 if(this._headFragment.childNodes[i].outerHTML) {
208 this.document.head.appendChild(this._headFragment.childNodes[i]);
209 }
210 }
211 //Garbage collection
212 this._headFragment = null;
213 }
214 },
215 ////////////////////////////////////////////////////////////////////
216 //
217 bodyContentLoaded: {
218 value: function (e) {
219 //Removing event, only needed on initial load