/* Copyright (c) 2012, Motorola Mobility LLC. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Motorola Mobility LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //////////////////////////////////////////////////////////////////////// // var Montage = require("montage/core/core").Montage, Component = require("montage/ui/component").Component, TemplateCreator = require("node_modules/tools/template/template-creator").TemplateCreator, ClassUuid = require("js/components/core/class-uuid").ClassUuid; //////////////////////////////////////////////////////////////////////// // exports.TemplateDocumentMediator = Montage.create(Component, { //////////////////////////////////////////////////////////////////// // hasTemplate: { value: false }, //////////////////////////////////////////////////////////////////// // getAppTemplatesUrlRegEx: { value: function () { var regex = new RegExp(chrome.extension.getURL(this.application.ninja.currentDocument.model.views.design.document.baseURI.split(chrome.extension.getURL('/'))[1]).replace(/\//gi, '\\\/'), 'gi'); return regex; } }, //////////////////////////////////////////////////////////////////// // getDataDirectory: { value: function (path) { //TODO: Implement user overwrite return this._getUserDirectory(path+'data/'); } }, //////////////////////////////////////////////////////////////////// // getNinjaDirectory: { value: function (path) { //TODO: Implement user overwrite return this._getUserDirectory(this.getDataDirectory(path)+'ninja/'); } }, //////////////////////////////////////////////////////////////////// // getCanvasDirectory: { value: function (path) { //TODO: Implement user overwrite return this._getUserDirectory(this.getNinjaDirectory(path)+'canvas/'); } }, //////////////////////////////////////////////////////////////////// // _getUserDirectory: { value: function (path) { //Checking for data directory var check = this.application.ninja.coreIoApi.fileExists({uri: path}), directory; //Creating directory if doesn't exists switch (check.status) { case 204: //Exists directory = path; break; case 404: //Doesn't exists directory = this.application.ninja.coreIoApi.createDirectory({uri: path}); //Checking for success if (directory.status === 201) { directory = path; } else { //Error directory = null; } break; default: //Error directory = null; break; } //Returning the path to the directory on disk (null for any error) return directory; } }, //////////////////////////////////////////////////////////////////// // parseHtmlToNinjaTemplate: { value: function (html) { //Creating temp object to mimic HTML var doc = window.document.implementation.createHTMLDocument(), template, docHtmlTag, hackHtml = document.createElement('html'), hackTag; //Setting content to temp doc.getElementsByTagName('html')[0].innerHTML = html; //TODO: Improve this, very bad way of copying attributes (in a pinch to get it working) hackHtml.innerHTML = html.replace(/html/gi, 'ninjahtmlhack'); hackTag = hackHtml.getElementsByTagName('ninjahtmlhack')[0]; docHtmlTag = doc.getElementsByTagName('html')[0]; //Looping through the attributes to copy them if (hackTag) { for (var m in hackTag.attributes) { if (hackTag.attributes[m].value) { docHtmlTag.setAttribute(hackTag.attributes[m].name.replace(/ninjahtmlhack/gi, 'html'), hackTag.attributes[m].value.replace(/ninjahtmlhack/gi, 'html')); } } } //Garbage collection hackHtml = hackTag = null; //Creating return object return {head: doc.head.innerHTML, body: doc.body.innerHTML, document: doc}; } }, //////////////////////////////////////////////////////////////////// //TODO: Expand to allow more templates, clean up variables parseNinjaTemplateToHtml: { value: function (saveExternalData, template, ninjaWrapper, libCopyCallback) { //TODO: Improve reference for rootUrl var regexRootUrl, rootUrl = this.application.ninja.coreIoApi.rootUrl + escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1])), mjsCreator = template.mjsTemplateCreator.create(), mJsSerialization, toremovetags = [], presentNodes, montageTemplate; //Creating instance of template creator montageTemplate = mjsCreator.initWithDocument(template.document); //Setting up expression for parsing URLs regexRootUrl = new RegExp(rootUrl.replace(/\//gi, '\\\/'), 'gi'); //Injecting head and body into old document if (montageTemplate._ownerSerialization.length > 0) { template.file.content.document.head.innerHTML = montageTemplate._document.head.innerHTML.replace(regexRootUrl, ''); template.file.content.document.body.innerHTML = montageTemplate._document.body.innerHTML.replace(regexRootUrl, ''); // mJsSerialization = montageTemplate._ownerSerialization; } else { template.file.content.document.head.innerHTML = template.head.innerHTML.replace(regexRootUrl, ''); template.file.content.document.body.innerHTML = template.body.innerHTML.replace(regexRootUrl, ''); } //Removes all attributes from node function wipeAttributes (node) { for (var f in node.attributes) { node.removeAttribute(node.attributes[f].name); } } //Copying attributes to maintain same properties as the wipeAttributes(template.file.content.document.body); for (var n in template.body.attributes) { if (template.body.attributes[n].value) { template.file.content.document.body.setAttribute(template.body.attributes[n].name, template.body.attributes[n].value); } } // if(template.template) { // // TODO - Need to handle banner and animation templates. //Copying attributes to maintain same properties as var ninjaContentTagMem = template.document.getElementsByTagName('ninja-content')[0], ninjaContentTagDoc = template.file.content.document.getElementsByTagName('ninja-content')[0]; if (ninjaContentTagMem && ninjaContentTagMem.getAttribute('data-ninja-style') !== null) { ninjaContentTagDoc.setAttribute('style', ninjaContentTagMem.getAttribute('data-ninja-style')); ninjaContentTagDoc.removeAttribute('data-ninja-style'); } else if (ninjaContentTagMem && ninjaContentTagMem.getAttribute('data-ninja-style') === null) { ninjaContentTagDoc.removeAttribute('style'); ninjaContentTagDoc.removeAttribute('data-ninja-style'); } // TODO - clean up into single method ninjaContentTagMem = template.document.getElementsByTagName('ninja-viewport')[0], ninjaContentTagDoc = template.file.content.document.getElementsByTagName('ninja-viewport')[0]; if (ninjaContentTagMem && ninjaContentTagMem.getAttribute('data-ninja-style') !== null) { ninjaContentTagDoc.setAttribute('style', ninjaContentTagMem.getAttribute('data-ninja-style')); ninjaContentTagDoc.removeAttribute('data-ninja-style'); } else if (ninjaContentTagMem && ninjaContentTagMem.getAttribute('data-ninja-style') === null) { ninjaContentTagDoc.removeAttribute('style'); ninjaContentTagDoc.removeAttribute('data-ninja-style'); } } else { if (template.body && template.body.getAttribute('data-ninja-style') !== null) { template.file.content.document.body.setAttribute('style', template.body.getAttribute('data-ninja-style')); template.file.content.document.body.removeAttribute('data-ninja-style'); } else if (template.body && template.body.getAttribute('data-ninja-style') === null) { template.file.content.document.body.removeAttribute('style'); template.file.content.document.body.removeAttribute('data-ninja-style'); } } wipeAttributes(template.file.content.document.head); //Copying attributes to maintain same properties as the for (var m in template.document.head.attributes) { if (template.document.head.attributes[m].value) { template.file.content.document.head.setAttribute(template.document.head.attributes[m].name, template.document.head.attributes[m].value); } } //Copying attributes to maintain same properties as the var htmlTagMem = template.document.getElementsByTagName('html')[0], htmlTagDoc = template.file.content.document.getElementsByTagName('html')[0]; wipeAttributes(htmlTagDoc); // for (var m in htmlTagMem.attributes) { if (htmlTagMem.attributes[m].value) { if (htmlTagMem.attributes[m].value.replace(/montage-app-bootstrapping/gi, '').length>0) { htmlTagDoc.setAttribute(htmlTagMem.attributes[m].name, htmlTagMem.attributes[m].value.replace(/ montage-app-bootstrapping/gi, '')); } } } // if (htmlTagMem && htmlTagMem.getAttribute('data-ninja-style') !== null) { htmlTagDoc.setAttribute('style', htmlTagMem.getAttribute('data-ninja-style')); htmlTagDoc.removeAttribute('data-ninja-style'); } else if (htmlTagMem && htmlTagMem.getAttribute('data-ninja-style') === null) { htmlTagDoc.removeAttribute('style'); htmlTagDoc.removeAttribute('data-ninja-style'); } //Getting list of current nodes (Ninja DOM) presentNodes = template.file.content.document.getElementsByTagName('*'); //Looping through nodes to determine origin and removing if not inserted by Ninja for (var n in presentNodes) { // if (presentNodes[n].getAttribute && presentNodes[n].getAttribute('data-ninja-node') === null) { toremovetags.push(presentNodes[n]); } else if (presentNodes[n].getAttribute && presentNodes[n].getAttribute('data-ninja-node') !== null) { //Removing attribute presentNodes[n].removeAttribute('data-ninja-node'); } } //Getting all CSS (style or link) tags var styletags = template.file.content.document.getElementsByTagName('style'), linktags = template.file.content.document.getElementsByTagName('link'), njtemplatetags = template.file.content.document.querySelectorAll('[data-ninja-template]'); //Adding to tags to be removed form template for (var f in njtemplatetags) { if (njtemplatetags[f].getAttribute) toremovetags.push(njtemplatetags[f]); } //Getting styles tags to be removed from document if (styletags.length) { for (var j = 0; j < styletags.length; j++) { if (styletags[j].getAttribute) { if (styletags[j].getAttribute('data-ninja-uri') !== null && !styletags[j].getAttribute('data-ninja-template')) { toremovetags.push(styletags[j]); } else if (styletags[j].getAttribute('data-ninja-external-url')) { toremovetags.push(styletags[j]); } } } } //Removing styles tags from document for (var h = 0; toremovetags[h]; h++) { try { //Checking head first template.file.content.document.head.removeChild(toremovetags[h]); } catch (e) { } try { //Checking body if not in head template.file.content.document.body.removeChild(toremovetags[h]); } catch (e) { //Error, not found! } } //Removing disabled tags from tags that were not originally disabled by user (Ninja enables all) for (var l in linktags) { if (linktags[l].getAttribute && linktags[l].getAttribute('disabled')) {//TODO: Use querySelectorAll for (var p = 0; toremovetags[p]; p++) { if (toremovetags[p].getAttribute('href') === linktags[l].getAttribute('href')) { if (!toremovetags[p].getAttribute('data-ninja-disabled')) { linktags[l].removeAttribute('disabled'); } } } } } //TODO: Make proper CSS method //Checking for type of save: styles =