From f10bec0c594c6404eec51dc1a005f7f17570ba52 Mon Sep 17 00:00:00 2001 From: Jose Antonio Marquez Date: Fri, 11 May 2012 10:13:27 -0700 Subject: Cleaning up template --- js/document/templates/montage-web/index.html | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/js/document/templates/montage-web/index.html b/js/document/templates/montage-web/index.html index e02d8d8e..a1b8b242 100755 --- a/js/document/templates/montage-web/index.html +++ b/js/document/templates/montage-web/index.html @@ -15,8 +15,6 @@ - - Ninja Prototype - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/js/document/templates/banner/main.js b/js/document/templates/banner/main.js new file mode 100644 index 00000000..d5ac88d5 --- /dev/null +++ b/js/document/templates/banner/main.js @@ -0,0 +1,49 @@ +/* + This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ +var Montage = require("montage/core/core").Montage, + Component = require("montage/ui/component").Component; + +exports.Main = Montage.create(Component, { + + hasTemplate: { + value: false + }, + + /** + * Adding window hooks to callback into this object from Ninja. + */ + templateDidLoad: { + value: function(){ + var self = this; + window.addComponent = function(element, data, callback) { + var component; + + component = require.async(data.path) + .then(function(component) { + var componentRequire = component[data.name]; + var componentInstance = componentRequire.create(); + + componentInstance.element = element; + + componentInstance.needsDraw = true; + componentInstance.ownerComponent = self; + + callback(componentInstance, element); + }) + .end(); + + }; + + // Dispatch event when this template has loaded. + /* + var newEvent = document.createEvent( "CustomEvent" ); + newEvent.initCustomEvent( "userTemplateDidLoad", false, true ); + document.body.dispatchEvent( newEvent ); + */ + + } + } +}); \ No newline at end of file diff --git a/js/document/templates/banner/package.json b/js/document/templates/banner/package.json new file mode 100755 index 00000000..c8bc02fb --- /dev/null +++ b/js/document/templates/banner/package.json @@ -0,0 +1,8 @@ +{ + "directories": { + "lib": "" + }, + "mappings": { + "montage": "../../../../node_modules/montage/" + } +} \ No newline at end of file diff --git a/js/document/templates/html/index.html b/js/document/templates/html/index.html new file mode 100755 index 00000000..a1b8b242 --- /dev/null +++ b/js/document/templates/html/index.html @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/js/document/templates/html/main.js b/js/document/templates/html/main.js new file mode 100644 index 00000000..d5ac88d5 --- /dev/null +++ b/js/document/templates/html/main.js @@ -0,0 +1,49 @@ +/* + This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ +var Montage = require("montage/core/core").Montage, + Component = require("montage/ui/component").Component; + +exports.Main = Montage.create(Component, { + + hasTemplate: { + value: false + }, + + /** + * Adding window hooks to callback into this object from Ninja. + */ + templateDidLoad: { + value: function(){ + var self = this; + window.addComponent = function(element, data, callback) { + var component; + + component = require.async(data.path) + .then(function(component) { + var componentRequire = component[data.name]; + var componentInstance = componentRequire.create(); + + componentInstance.element = element; + + componentInstance.needsDraw = true; + componentInstance.ownerComponent = self; + + callback(componentInstance, element); + }) + .end(); + + }; + + // Dispatch event when this template has loaded. + /* + var newEvent = document.createEvent( "CustomEvent" ); + newEvent.initCustomEvent( "userTemplateDidLoad", false, true ); + document.body.dispatchEvent( newEvent ); + */ + + } + } +}); \ No newline at end of file diff --git a/js/document/templates/html/package.json b/js/document/templates/html/package.json new file mode 100755 index 00000000..c8bc02fb --- /dev/null +++ b/js/document/templates/html/package.json @@ -0,0 +1,8 @@ +{ + "directories": { + "lib": "" + }, + "mappings": { + "montage": "../../../../node_modules/montage/" + } +} \ No newline at end of file diff --git a/js/document/templates/montage-html/default_html.css b/js/document/templates/montage-html/default_html.css deleted file mode 100755 index 04b21c6f..00000000 --- a/js/document/templates/montage-html/default_html.css +++ /dev/null @@ -1,74 +0,0 @@ -/* -This file contains proprietary software owned by Motorola Mobility, Inc.
-No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
-(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. -
*/ - -* { - -webkit-transition-duration: 0s !important; - -webkit-animation-duration: 0s !important; - -webkit-animation-name: none !important; -} - -html{ - overflow:hidden; -} - -body -{ - background: #808080; -} - -#Viewport -{ - margin: 0px; - padding: 0px; - top: 200px; - left: 700px; - /*position: absolute;*/ - /*height: 600px;*/ - /*width: 800px;*/ - opacity: 0.99; - z-index:2; -} - -#stageBG -{ - background: #ffffff; - top: 200px; - left: 700px; - z-index:1; -} - -.stageDimension -{ - position: absolute; - height: 600px; - width: 800px; -} - -.stageView -{ - border: 1px solid black; - -webkit-transform-style: preserve-3d; - -webkit-transform: perspective(1400) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); -} - -.stageContentShadow { - -webkit-box-shadow: 3px 5px 4px rgba(0,0,0,.5); - -moz-box-shadow: 3px 5px 4px rgba(0,0,0,.5); - box-shadow: 3px 5px 4px rgba(0,0,0,.5); -} - -#userHead -{ - display: none; -} - -.active-element-outline { - outline: #adff2f solid 2px; -} - -.nj-preset-transition { - -webkit-transition: all 450ms linear !important; -} \ No newline at end of file diff --git a/js/document/templates/montage-html/index.html b/js/document/templates/montage-html/index.html deleted file mode 100755 index 79c6cd51..00000000 --- a/js/document/templates/montage-html/index.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - Ninja Prototype - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/js/document/templates/montage-html/main.reel/main.js b/js/document/templates/montage-html/main.reel/main.js deleted file mode 100644 index 019c675e..00000000 --- a/js/document/templates/montage-html/main.reel/main.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file contains proprietary software owned by Motorola Mobility, Inc.
- No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
- (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. -
*/ -var Montage = require("montage/core/core").Montage, - Component = require("montage/ui/component").Component; - -exports.Main = Montage.create(Component, { - - hasTemplate: { - value: false - }, - - /** - * Adding window hooks to callback into this object from Ninja. - */ - templateDidLoad: { - value: function(){ - var self = this; - window.addComponent = function(element, data, callback) { - var component; - - component = require.async(data.path) - .then(function(component) { - var componentRequire = component[data.name]; - var componentInstance = componentRequire.create(); - - componentInstance.element = element; - - componentInstance.needsDraw = true; - componentInstance.ownerComponent = self; - - callback(componentInstance, element); - }) - .end(); - - }; - - // Dispatch event when this template has loaded. - var newEvent = document.createEvent( "CustomEvent" ); - newEvent.initCustomEvent( "userTemplateDidLoad", false, true ); - - document.body.dispatchEvent( newEvent ); - - } - } -}); \ No newline at end of file diff --git a/js/document/templates/montage-html/package.json b/js/document/templates/montage-html/package.json deleted file mode 100755 index c8bc02fb..00000000 --- a/js/document/templates/montage-html/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "directories": { - "lib": "" - }, - "mappings": { - "montage": "../../../../node_modules/montage/" - } -} \ No newline at end of file diff --git a/js/document/templates/montage-web/index.html b/js/document/templates/montage-web/index.html deleted file mode 100755 index a1b8b242..00000000 --- a/js/document/templates/montage-web/index.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/js/document/templates/montage-web/main.js b/js/document/templates/montage-web/main.js deleted file mode 100644 index d5ac88d5..00000000 --- a/js/document/templates/montage-web/main.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file contains proprietary software owned by Motorola Mobility, Inc.
- No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
- (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. -
*/ -var Montage = require("montage/core/core").Montage, - Component = require("montage/ui/component").Component; - -exports.Main = Montage.create(Component, { - - hasTemplate: { - value: false - }, - - /** - * Adding window hooks to callback into this object from Ninja. - */ - templateDidLoad: { - value: function(){ - var self = this; - window.addComponent = function(element, data, callback) { - var component; - - component = require.async(data.path) - .then(function(component) { - var componentRequire = component[data.name]; - var componentInstance = componentRequire.create(); - - componentInstance.element = element; - - componentInstance.needsDraw = true; - componentInstance.ownerComponent = self; - - callback(componentInstance, element); - }) - .end(); - - }; - - // Dispatch event when this template has loaded. - /* - var newEvent = document.createEvent( "CustomEvent" ); - newEvent.initCustomEvent( "userTemplateDidLoad", false, true ); - document.body.dispatchEvent( newEvent ); - */ - - } - } -}); \ No newline at end of file diff --git a/js/document/templates/montage-web/package.json b/js/document/templates/montage-web/package.json deleted file mode 100755 index c8bc02fb..00000000 --- a/js/document/templates/montage-web/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "directories": { - "lib": "" - }, - "mappings": { - "montage": "../../../../node_modules/montage/" - } -} \ No newline at end of file diff --git a/js/document/views/design.js b/js/document/views/design.js index 321f93e8..e838dd49 100755 --- a/js/document/views/design.js +++ b/js/document/views/design.js @@ -21,11 +21,21 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, { _callback: { value: null }, + //////////////////////////////////////////////////////////////////// + // + _template: { + value: null + }, //////////////////////////////////////////////////////////////////// // _document: { value: null }, + //////////////////////////////////////////////////////////////////// + // + _bodyFragment: { + value: null + }, //////////////////////////////////////////////////////////////////// // _headFragment: { @@ -70,14 +80,20 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, { //////////////////////////////////////////////////////////////////// // render: { - value: function (callback, template) {//TODO: Add support for templates + value: function (callback, template) { + //TODO: Remove, this is a temp patch for webRequest API gate this.application.ninja.documentController._hackRootFlag = false; //Storing callback for dispatch ready this._callback = callback; + this._template = template; //Adding listener to know when template is loaded to then load user content this.iframe.addEventListener("load", this.onTemplateLoad.bind(this), false); //TODO: Add source parameter and root (optional) - this.iframe.src = "js/document/templates/montage-web/index.html"; + if (template && template.type === 'banner' && template.size) { + this.iframe.src = "js/document/templates/banner/index.html"; + } else { + this.iframe.src = "js/document/templates/html/index.html"; + } } }, //////////////////////////////////////////////////////////////////// @@ -104,27 +120,63 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, { this.model.baseHref = basetag[basetag.length-1].getAttribute('href'); } } - //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 - this._observer.head = new WebKitMutationObserver(this.insertHeadContent.bind(this)); - this._observer.head.observe(this._headFragment, {childList: true}); - //Inserting HTML and parsing URLs via mediator method - 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)); - //Adding event listener to know when the body is ready and make callback (using HTML5 new DOM Mutation Events) - this._observer.body = new WebKitMutationObserver(this.bodyContentLoaded.bind(this)); - this._observer.body.observe(this.document.body, {childList: true}); - //Inserting HTML and parsing URLs via mediator method - 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)); - //Copying attributes to maintain same properties as the - for (var n in this.content.document.body.attributes) { - if (this.content.document.body.attributes[n].value) { - this.document.body.setAttribute(this.content.document.body.attributes[n].name, this.content.document.body.attributes[n].value); + //Checking to content to be template + if (this._template) { + if (this._template.type === 'banner') { + //Loading contents into a fragment + this._bodyFragment = this.document.createElement('body'); + //Listening for content to be ready + this._observer.body = new WebKitMutationObserver(this.insertBannerContent.bind(this)); + this._observer.body.observe(this._bodyFragment, {childList: true}); + //Inserting HTML and parsing URLs via mediator method + this._bodyFragment.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)); + } + } else { + //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 + this._observer.head = new WebKitMutationObserver(this.insertHeadContent.bind(this)); + this._observer.head.observe(this._headFragment, {childList: true}); + //Inserting HTML and parsing URLs via mediator method + 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)); + //Adding event listener to know when the body is ready and make callback (using HTML5 new DOM Mutation Events) + this._observer.body = new WebKitMutationObserver(this.bodyContentLoaded.bind(this)); + this._observer.body.observe(this.document.body, {childList: true}); + //Inserting HTML and parsing URLs via mediator method + 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)); + //Copying attributes to maintain same properties as the + for (var n in this.content.document.body.attributes) { + if (this.content.document.body.attributes[n].value) { + this.document.body.setAttribute(this.content.document.body.attributes[n].name, this.content.document.body.attributes[n].value); + } } + //TODO: Add attribute copying for and } - //TODO: Add attribute copying for and } }, + //////////////////////////////////////////////////////////////////// + // + insertBannerContent: { + value: function (e) { + //Getting first element in DOM (assumes it's root) + var banner = this._bodyFragment.getElementsByTagName('*')[1], + ninjaBanner = this.document.body.getElementsByTagName('ninja-banner')[0]; + //Copying attributes to maintain same properties as the banner root + for (var n in banner.attributes) { + if (banner.attributes[n].value) { + ninjaBanner.setAttribute(banner.attributes[n].name, banner.attributes[n].value); + } + } + //Adjusting margin per size of document + this.document.head.getElementsByTagName('style')[0].innerHTML += '\n ninja-banner {margin-top: -'+Math.floor(this._template.size.height/2)+'px; margin-left: -'+Math.floor(this._template.size.width/2)+'px}'; + //Setting content in template + ninjaBanner.innerHTML = banner.innerHTML; + //Garbage collection + this._bodyFragment = null; + //Calling standard method to finish opening document + this.bodyContentLoaded(null); + } + }, //////////////////////////////////////////////////////////////////// // insertHeadContent: { diff --git a/js/io/templates/descriptor.json b/js/io/templates/descriptor.json index 21c4b58c..0b2b70e5 100644 --- a/js/io/templates/descriptor.json +++ b/js/io/templates/descriptor.json @@ -1,13 +1,21 @@ { "categories":{ - "children":["/"] + "children":["/basic", "/template"] }, - "/":{ + + "/basic":{ "name":"Blank File", - "uri":"/", + "uri":"/basic", "type":"directory", "children":["js/io/templates/files/html.txt", "js/io/templates/files/js.txt", "js/io/templates/files/css.txt", "js/io/templates/files/json.txt", "js/io/templates/files/php.txt", "js/io/templates/files/pl.txt", "js/io/templates/files/py.txt", "js/io/templates/files/rb.txt", "js/io/templates/files/xml.txt"] }, + "/template":{ + "name":"Template", + "uri":"/template", + "type":"directory", + "children":["js/io/templates/files/banner.txt"] + }, + "js/io/templates/files/html.txt":{ "name":"HTML", "uri":"js/io/templates/files/html.txt", @@ -75,6 +83,49 @@ "name": "Basic", "uri": "defaultTemplate", "type":"file" + }, + + "js/io/templates/files/banner.txt":{ + "name":"Banner", + "uri":"js/io/templates/files/banner.txt", + "type":"file", + "fileExtension":".html", + "children":["120x600", "160x600", "200x200", "250x250", "300x250", "336x280", "550x400"] + }, + + "120x600":{ + "name": "Skyscraper", + "uri": "120x600", + "type":"file" + }, + "160x600":{ + "name": "Wide Skyscraper", + "uri": "160x600", + "type":"file" + }, + "200x200":{ + "name": "Small Square", + "uri": "200x200", + "type":"file" + }, + "250x250":{ + "name": "Square", + "uri": "250x250", + "type":"file" + }, + "300x250":{ + "name": "Medium Rectangle", + "uri": "300x250", + "type":"file" + }, + "336x280":{ + "name": "Large Rectangle", + "uri": "336x280", + "type":"file" + }, + "550x400":{ + "name": "Animation Default", + "uri": "550x400", + "type":"file" } - } \ No newline at end of file diff --git a/js/io/templates/files/banner.txt b/js/io/templates/files/banner.txt new file mode 100755 index 00000000..fdafe4f6 --- /dev/null +++ b/js/io/templates/files/banner.txt @@ -0,0 +1,13 @@ + + +
+ + + + + + + +
\ No newline at end of file diff --git a/js/io/ui/new-file-dialog/new-file-options-navigator.reel/new-file-options-navigator.js b/js/io/ui/new-file-dialog/new-file-options-navigator.reel/new-file-options-navigator.js index 1a26c99c..ebe2df61 100644 --- a/js/io/ui/new-file-dialog/new-file-options-navigator.reel/new-file-options-navigator.js +++ b/js/io/ui/new-file-dialog/new-file-options-navigator.reel/new-file-options-navigator.js @@ -249,7 +249,8 @@ var NewFileOptionsNavigator = exports.NewFileOptionsNavigator = Montage.create(C handleOkButtonAction:{ value: function(evt){ - var selectedProjectTypeID = this.selectedProjectType.uri, + var templateData, + selectedProjectTypeID = this.selectedProjectType.uri, templateID = this.selectedTemplate.uri, projectName = this.newFileLocation.newFileName.value, projectDirectory = this.newFileLocation.fileInputField.newFileDirectory.value, @@ -264,7 +265,10 @@ var NewFileOptionsNavigator = exports.NewFileOptionsNavigator = Montage.create(C "projectDirectory="+projectDirectory+"\n"+ "projectWidth="+projectWidth+"\n"+ "projectHeight="+projectHeight; - + //////////////////////////////////////////////////////////////////// + //Template data must be passed during file creation (lots of confusion data here, should be cleaned up…) + templateData = {id: templateID, name: this.newFileModel.projectTypeData[selectedProjectTypeID].name, type: this.newFileModel.projectTypeData[selectedProjectTypeID].type}; + //////////////////////////////////////////////////////////////////// if(/[^/\\]$/g.test(projectDirectory)){ projectDirectory = projectDirectory + "/"; @@ -285,7 +289,8 @@ var NewFileOptionsNavigator = exports.NewFileOptionsNavigator = Montage.create(C if(!!this.newFileModel.callback){//inform document-controller if save successful this.newFileModel.callback({"fileTemplateUri":selectedProjectTypeID, "newFilePath":newFilePath, - "fileExtension":fileExtension});//document-controller api + "fileExtension":fileExtension, + "template":templateData});//document-controller api }else{ //send selection event var newFileSelectionEvent = document.createEvent("Events"); diff --git a/js/mediators/io-mediator.js b/js/mediators/io-mediator.js index dae0f359..0bff1f3b 100644 --- a/js/mediators/io-mediator.js +++ b/js/mediators/io-mediator.js @@ -53,14 +53,14 @@ exports.IoMediator = Montage.create(Component, { // fileNew: { enumerable: false, - value: function (file, template, callback) { + value: function (file, url, callback, template) { //Loading template from template URL var xhr = new XMLHttpRequest(), result; - xhr.open("GET", template, false); + xhr.open("GET", url, false); xhr.send(); if (xhr.readyState === 4) { //Making call to create file, checking for return code - switch (this.fio.newFile({ uri: file, contents: xhr.response })) { + switch (this.fio.newFile({ uri: file, contents: parseTemplate(xhr.response, template) })) { case 201: result = { status: 201, success: true, uri: file }; break; @@ -74,6 +74,20 @@ exports.IoMediator = Montage.create(Component, { result = { status: 500, success: false, uri: file }; break; } + //TODO: Improve template data injection + function parseTemplate (content, template) { + // + if (template.name.toLowerCase() === 'banner') { + //Getting dimensions of banner + var dimensions = template.id.split('x'); + dimensions = {width: String(dimensions[0])+'px', height: String(dimensions[1])+'px'}; + // + content = content.replace(/Dimensions@@@/gi, "Dimensions@@@"+template.id); + content = content.replace(/ninja-banner {}/gi, "ninja-banner {width: "+dimensions.width+"; height: "+dimensions.height+"}"); + } + // + return content; + } } else { result = { status: 500, success: false, uri: file }; } diff --git a/js/panels/properties.reel/properties.js b/js/panels/properties.reel/properties.js index 6f43ce03..20f670d9 100755 --- a/js/panels/properties.reel/properties.js +++ b/js/panels/properties.reel/properties.js @@ -75,9 +75,7 @@ exports.Properties = Montage.create(Component, { // For now always assume that the stage is selected by default when opening the old template // TODO: Remove marker for old template: NINJA-STAGE-REWORK - if(this.application.ninja.selectedElements.length === 0 && this.application.ninja.currentDocument.documentRoot.nodeName.toLowerCase() !== "body") { - this.displayStageProperties(); - } + this.displayElementProperties(this.application.ninja.currentDocument.documentRoot); } }, -- cgit v1.2.3