From c4114992337ec8b3c37c66ab17d0a45d033993f2 Mon Sep 17 00:00:00 2001 From: Jose Antonio Marquez Date: Thu, 3 May 2012 11:43:46 -0700 Subject: Reloading local stylesheets Added the reload method of local linked styles, still need to parse style contents for URLs and also add cross-domain stylesheet support. --- js/document/views/design.js | 133 +++++++++++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 44 deletions(-) (limited to 'js/document') diff --git a/js/document/views/design.js b/js/document/views/design.js index fa9d412e..e5213761 100755 --- a/js/document/views/design.js +++ b/js/document/views/design.js @@ -88,7 +88,6 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, { this.document.styleSheets[k].ownerNode.setAttribute('data-ninja-template', 'true'); } } - //Creating temp code fragement to load head this._headFragment = this.document.createElement('head'); //Adding event listener to know when head is ready, event only dispatched once when using innerHTML @@ -103,12 +102,29 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, { this.document.body.innerHTML += ''+(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)); } }, + //////////////////////////////////////////////////////////////////// + // + insertHeadContent: { + value: function (e) { + //Removing event + this._observer.head.disconnect(); + this._observer.head = null; + //Adding the loaded nodes from code fragment into actual document head + for(var i in this._headFragment.childNodes) { + //Minor hack to know node is actual HTML node + if(this._headFragment.childNodes[i].outerHTML) { + this.document.head.appendChild(this._headFragment.childNodes[i]); + } + } + } + }, //////////////////////////////////////////////////////////////////// // bodyContentLoaded: { value: function (e) { //Removing event, only needed on initial load this._observer.body.disconnect(); + this._observer.body = null; //Removing loading container this.document.body.removeChild(this.document.getElementsByTagName('ninjaloadinghack')[0]); @@ -116,34 +132,28 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, { - - - - //Temporarily checking for disabled special case + // var stags = this.document.getElementsByTagName('style'), ltags = this.document.getElementsByTagName('link'); - // - for (var m = 0; m < ltags.length; m++) { - if (ltags[m].getAttribute('data-ninja-template') === null) { - if (ltags[m].getAttribute('disabled')) { - ltags[m].removeAttribute('disabled'); - ltags[m].setAttribute('data-ninja-disabled', 'true'); - } - } - } - // - for (var n = 0; n < stags.length; n++) { - if (stags[n].getAttribute('data-ninja-template') === null) { - if (stags[n].getAttribute('disabled')) { - stags[n].removeAttribute('disabled'); - stags[n].setAttribute('data-ninja-disabled', 'true'); - } - } - } - // - if(this.document.styleSheets.length > 0) { - for (var i = 0; i < this.document.styleSheets.length; i++) { + //Temporarily checking for disabled special case (we must enabled for Ninja to access styles) + this.ninjaDisableAttribute(stags); + this.ninjaDisableAttribute(ltags); + + + + + //Looping through all link tags to reload into style tags + if(ltags.length > 0) { + for (var i = 0; i < ltags.length; i++) { // + if (ltags[i].href) { + //TODO: Verify this works for tags in body as well (working in head) + this.document.head.insertBefore(this.getStyleTagFromCssFile(ltags[i]), ltags[i]) || this.document.body.insertBefore(this.getStyleTagFromCssFile(ltags[i]), ltags[i]); + //Disabling tag once it has been reloaded + ltags[i].setAttribute('disabled', 'true'); + } else { + //Error: broken? + } } } @@ -151,33 +161,68 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, { - - - //Makign callback if specified if (this._callback) this._callback(); } }, //////////////////////////////////////////////////////////////////// // - insertHeadContent: { - value: function (e) { - //Removing event - this._observer.head.disconnect(); - //Adding the loaded nodes from code fragment into actual document head - for(var i in this._headFragment.childNodes) { - //Minor hack to know node is actual HTML node - if(this._headFragment.childNodes[i].outerHTML) { - this.document.head.appendChild(this._headFragment.childNodes[i]); - } - } - } - }, + ninjaDisableAttribute: { + value: function (tags) { + //Looping through tags + for (var i = 0; i < tags.length; i++) { + if (tags[i].getAttribute('data-ninja-template') === null) { + if (tags[i].getAttribute('disabled')) { + tags[i].removeAttribute('disabled'); + tags[i].setAttribute('data-ninja-disabled', 'true'); + } + } + } + } + }, //////////////////////////////////////////////////////////////////// // - initCss: { - value: function () { + getStyleTagFromCssFile: { + value: function (linktag) { // + var tag, cssUrl, fileUri, cssData, docRootUrl; + //TODO: Remove usage of hack reference of URL + docRootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]).replace(/\/\//gi, '/')); + //Checking for location of href to load (special case for cross-domain) + if (linktag.href.indexOf(this.application.ninja.coreIoApi.rootUrl) !== -1) { + //Getting file URI (not URL since we must load through I/O API) + cssUrl = linktag.href.split(this.application.ninja.coreIoApi.rootUrl)[1]; + fileUri = this.application.ninja.coreIoApi.cloudData.root+cssUrl; + //Loading data from CSS file + cssData = this.application.ninja.coreIoApi.readFile({uri: fileUri}); + // + } else { + //Cross-domain resource + } + //TODO: Improve into single method + fileCouldDirUrl = linktag.href.split(linktag.href.split('/')[linktag.href.split('/').length-1])[0]; + //Creating style tag to load CSS content into + tag = this.document.createElement('style'); + tag.setAttribute('type', 'text/css'); + tag.setAttribute('data-ninja-uri', fileUri); + tag.setAttribute('data-ninja-file-url', cssUrl); + tag.setAttribute('data-ninja-file-read-only', JSON.parse(this.application.ninja.coreIoApi.isFileWritable({uri: fileUri}).content).readOnly); + tag.setAttribute('data-ninja-file-name', cssUrl.split('/')[cssUrl.split('/').length-1]); + //Copying attributes to maintain same properties as the + for (var n in linktag.attributes) { + if (linktag.attributes[n].value && linktag.attributes[n].name !== 'disabled') { + if (linktag.attributes[n].value.indexOf(docRootUrl) !== -1) { + tag.setAttribute(linktag.attributes[n].name, linktag.attributes[n].value.split(docRootUrl)[1]); + } else { + tag.setAttribute(linktag.attributes[n].name, linktag.attributes[n].value); + } + } + } + // + //tag.innerHTML = cssData.content.replace(/url\(()(.+?)\1\)/g, detectUrl); + tag.innerHTML = cssData.content; + // + return tag; } }, //////////////////////////////////////////////////////////////////// -- cgit v1.2.3