diff --git a/Dockerfile b/Dockerfile index a10b120..288b2f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,12 @@ FROM node:8 -WORKDIR . /app/jacinto/casemanager +WORKDIR . /app RUN npm i npm RUN npm i -g @adonisjs/cli COPY ./src/adonisjs . -#RUN cp .env.example .env RUN npm install - -CMD [ "adonis", "serve", "--dev" ] +CMD [ "adonis", "serve"] diff --git a/dccs/README.md b/dccs/README.md new file mode 100644 index 0000000..5c93af1 --- /dev/null +++ b/dccs/README.md @@ -0,0 +1,5 @@ +# Digital Content Components + +## Properties +Getter and setter approach based on: +> [Attributes and Properties in Custom Elements, Alligator.io, September 13, 2017](https://alligator.io/web-components/attributes-properties/) diff --git a/dccs/components/dcc-base.js b/dccs/components/dcc-base.js new file mode 100644 index 0000000..6f51b8f --- /dev/null +++ b/dccs/components/dcc-base.js @@ -0,0 +1,6 @@ +/** + * DCC which is the basis of all components + */ + +class DCCBase extends HTMLElement { +} \ No newline at end of file diff --git a/dccs/components/dcc-block.js b/dccs/components/dcc-block.js new file mode 100644 index 0000000..52780fe --- /dev/null +++ b/dccs/components/dcc-block.js @@ -0,0 +1,173 @@ +/* Block DCC + * + * xstyle - controls the behavior of the style + * * "in" or not defined -> uses the internal trigger-button style + * * "none" -> apply a minimal styling (just changes cursor to pointer) + * * "out" -> apply an style externally defined with the name "trigger-button-template" +**************************************************************************/ + +class DCCBlock extends DCCBase { + constructor() { + super(); + + this._pendingRequests = 0; + + this.defineXstyle = this.defineXstyle.bind(this); + this.defineLocation = this.defineLocation.bind(this); + this._renderInterface = this._renderInterface.bind(this); + } + + connectedCallback() { + if (!this.hasAttribute("xstyle") && window.messageBus.page.hasSubscriber("dcc/request/xstyle")) { + window.messageBus.page.subscribe("dcc/xstyle/" + this.id, this.defineXstyle); + window.messageBus.page.publish("dcc/request/xstyle", this.id); + this._pendingRequests++; + } + if (!this.hasAttribute("location") && + window.messageBus.page.hasSubscriber("dcc/request/location")) { + window.messageBus.page.subscribe("dcc/location/" + this.id, this.defineLocation); + window.messageBus.page.publish("dcc/request/location", this.id); + this._pendingRequests++; + } + this._checkRender(); + } + + defineXstyle(topic, message) { + window.messageBus.page.unsubscribe("dcc/xstyle/" + this.id, this.defineXstyle); + this.xstyle = message; + this._pendingRequests--; + this._checkRender(); + } + + defineLocation(topic, message) { + window.messageBus.page.unsubscribe("dcc/location/" + this.id, this.defineLocation); + this.location = message; + this._pendingRequests--; + this._checkRender(); + } + + _checkRender() { + if (this._pendingRequests == 0) { + if (document.readyState === "complete") + this._renderInterface(); + else + window.addEventListener("load", this._renderInterface); + } + } + + /* Attribute Handling */ + + static get observedAttributes() { + return ["id", "label", "image", "location", "xstyle"]; + } + + get id() { + return this.getAttribute("id"); + } + + set id(newValue) { + this.setAttribute("id", newValue); + } + + get label() { + return this.getAttribute("label"); + } + + set label(newValue) { + this.setAttribute("label", newValue); + } + + get image() { + return this.getAttribute("image"); + } + + set image(newValue) { + this.setAttribute("image", newValue); + } + + get location() { + return this.getAttribute("location"); + } + + set location(newValue) { + this.setAttribute("location", newValue); + } + + get xstyle() { + return this.getAttribute("xstyle"); + } + + set xstyle(newValue) { + this.setAttribute("xstyle", newValue); + } + + /* Rendering */ + + elementTag() { + return DCCBlock.elementTag; + } + + _renderInterface() { + let presentation = null; + if (!this.hasAttribute("xstyle")) + this.xstyle = "in"; + + let render; + switch (this.xstyle) { + case "in" : if (this.hasAttribute("image")) + render = "image-style" + else + render = "regular-style" + break; + case "none": render = ""; + break; + case "out-image": + case "out": render = this.elementTag() + "-template"; + break; + default: render = this.xstyle; + } + + // console.log("* id: " + this.id); + // console.log("* location: " + this.location); + // console.log("* xstyle: " + this.xstyle); + if (this.xstyle.startsWith("out") && + this.hasAttribute("location") && this.location != "#in") { + presentation = document.querySelector("#" + this.location); + this._injectDCC(presentation, render); + let wrapper = document.querySelector("#" + this.location + "-wrapper"); + if (wrapper != null) { + if (wrapper.style.display) // html + delete wrapper.style.display; + if (wrapper.getAttribute("visibility")) // svg + delete wrapper.removeAttribute("visibility"); + } + } else { + let template = document.createElement("template"); + template.innerHTML = this._generateTemplate(render); + + let host = this; + if (this.xstyle == "in" || this.xstyle == "none") + host = this.attachShadow({mode: "open"}); + host.appendChild(template.content.cloneNode(true)); + presentation = host.querySelector("#presentation-dcc"); + } + return presentation; + } + + /* + _computeTrigger() { + if (this.hasAttribute("label") || this.hasAttribute("action")) { + let eventLabel = (this.hasAttribute("action")) ? this.action : "navigate/trigger"; + let message = (this.hasAttribute("link")) ? this.link : this.label; + window.messageBus.ext.publish(eventLabel, message); + } + } + */ +} + +(function() { + DCCBlock.elementTag = "dcc-block"; + + customElements.define(DCCBlock.elementTag, DCCBlock); + +})(); \ No newline at end of file diff --git a/dccs/components/dcc-character.js b/dccs/components/dcc-character.js new file mode 100644 index 0000000..96caf3d --- /dev/null +++ b/dccs/components/dcc-character.js @@ -0,0 +1,178 @@ +/* Character DCC + **************/ +class DCCCharacter extends DCCBase { + connectedCallback() { + let templateHTML = + ` +
+
+ [images] +
+
+
+
Name:
+
[character]
+
+
+
Role:
+
[role]
+
+
+
Description:
+
[description]
+
+
+
`; + + templateHTML = templateHTML.replace("[images]", this._imageElements()) + .replace("[character]", this.character) + .replace("[role]", this.role) + .replace("[description]", this.description); + + // building the template + const template = document.createElement("template"); + template.innerHTML = templateHTML; + let shadow = this.attachShadow({mode: "open"}); + shadow.appendChild(template.content.cloneNode(true)); + + this._presentation = shadow.querySelector("#presentation-dcc"); + this._recordImages = shadow.querySelector("#record-images"); + } + + /* Properties + **********/ + + static get observedAttributes() { + return ["image", "character", "role", "description"]; + } + + get image() { + return this.getAttribute("image"); + } + + set image(newValue) { + this.setAttribute("image", newValue); + } + + get character() { + return this.getAttribute("character"); + } + + set character(newValue) { + this.setAttribute("character", newValue); + } + + get role() { + return this.getAttribute("role"); + } + + set role(newValue) { + this.setAttribute("role", newValue); + } + + get description() { + return this.getAttribute("description"); + } + + set description(newValue) { + this.setAttribute("description", newValue); + } + + _imageElements() { + let extension = this.image.lastIndexOf("."); + let icon = this.image.substring(0, extension) + "-icon" + this.image.substring(extension); + + return "
" + + "
"; + } + + /* Editable Component */ + editDCC() { + if (!DCCCharacter.editableCode) { + editableDCCCharacter(); + DCCCharacter.editableCode = true; + } + this._editDCC(); + } + + editImage() { + this._editImage(); + } +} + +(function() { + DCCCharacter.editableCode = false; + customElements.define("dcc-character", DCCCharacter); +})(); \ No newline at end of file diff --git a/dccs/components/dcc-dialog.js b/dccs/components/dcc-dialog.js new file mode 100644 index 0000000..5ea4778 --- /dev/null +++ b/dccs/components/dcc-dialog.js @@ -0,0 +1,197 @@ +/** + * Talk DCC + * + * xstyle = out -> in the outer space it first looks for the specific name and then for the generic "character" name + */ +class DCCTalk extends DCCBase { + constructor() { + super(); + + this._pendingRequests = 0; + + this.defineSequence = this.defineSequence.bind(this); + this.defineXstyle = this.defineXstyle.bind(this); + this._renderInterface = this._renderInterface.bind(this); + } + + connectedCallback() { + if (window.messageBus.page.hasSubscriber("dcc/request/talk-sequence")) { + window.messageBus.page.subscribe("dcc/talk-sequence/" + this.id, this.defineSequence); + window.messageBus.page.publish("dcc/request/talk-sequence", this.id); + this._pendingRequests++; + } + if (!this.hasAttribute("xstyle") && window.messageBus.page.hasSubscriber("dcc/request/xstyle")) { + window.messageBus.page.subscribe("dcc/xstyle/" + this.id, this.defineXstyle); + window.messageBus.page.publish("dcc/request/xstyle", this.id); + this._pendingRequests++; + } + this._checkRender(); + } + + defineSequence(topic, message) { + window.messageBus.page.unsubscribe("dcc/talk-sequence/" + this.id, this.defineSequence); + this.sequence = message; + this._pendingRequests--; + this._checkRender(); + } + + defineXstyle(topic, message) { + window.messageBus.page.unsubscribe("dcc/xstyle/" + this.id, this.defineXstyle); + this.xstyle = message; + this._pendingRequests--; + this._checkRender(); + } + + _checkRender() { + if (this._pendingRequests == 0) { + if (document.readyState === "complete") + this._renderInterface(); + else + window.addEventListener("load", this._renderInterface); + } + } + + /* + * Property handling + */ + + static get observedAttributes() { + return ["sequence", "character", "speech", "xstyle"]; + } + + get sequence() { + return this.getAttribute("sequence"); + } + + set sequence(newValue) { + this.setAttribute("sequence", newValue); + } + + get character() { + return this.getAttribute("character"); + } + + set character(newValue) { + this.setAttribute("character", newValue); + } + + get speech() { + return this.getAttribute("speech"); + } + + set speech(newValue) { + this.setAttribute("speech", newValue); + } + + get xstyle() { + return this.getAttribute("xstyle"); + } + + set xstyle(newValue) { + this.setAttribute("xstyle", newValue); + } + + /* Rendering */ + + _renderInterface() { + if (this.hasAttribute("xstyle") && this.xstyle == "out") { + let character = this._injectTalkElement("#talk-character"); + if (character != null) + character.innerHTML = this.character; + + // works for SVG but not for HTML + let image = this._injectTalkElement("#talk-image"); + if (image != null) + image.setAttributeNS("http://www.w3.org/1999/xlink", "href", + "images/" + this.character.replace(/ /igm, "_").toLowerCase() + ".png"); + + if (this.hasAttribute("speech")) { + let speech = this._injectTalkElement("#talk-speech"); + if (speech != null) + speech.innerHTML = this.speech; + } + } else { + let charImg = "images/" + this.character.toLowerCase() + .replace(/ /igm, "_") + ".png"; + let template = document.createElement("template"); + + const speech = (this.hasAttribute("speech")) ? this.speech : ""; + template.innerHTML = DCCTalk.templateElements.replace("[image]",charImg) + .replace("[character]", this.character) + .replace("[speech]", speech); + this._shadow = this.attachShadow({mode: "open"}); + this._shadow.appendChild(template.content.cloneNode(true)); + this._presentation = this._shadow.querySelector("#presentation-dcc"); + } + } + + _injectTalkElement(prefix) { + const charLabel = this.character.replace(/ /igm, "_").toLowerCase(); + + // search sequence: by name, by number, generic + let target = document.querySelector(prefix + "-" + charLabel); + if (target == null && this.hasAttribute("sequence")) + target = document.querySelector(prefix + "-" + this.sequence); + if (target == null) + target = document.querySelector(prefix); + + return target; + } +} + +class DCCDialog extends DCCBase { + constructor() { + super(); + this._sequence = 0; + this.requestSequence = this.requestSequence.bind(this); + } + + connectedCallback() { + window.messageBus.page.subscribe("dcc/request/talk-sequence", this.requestSequence); + } + + disconnectedCallback() { + window.messageBus.page.unsubscribe("dcc/request/talk-sequence", this.requestSequence); + } + + requestSequence(topic, message) { + this._sequence++; + window.messageBus.page.publish("dcc/talk-sequence/" + message, this._sequence); + } +} + +(function() { + DCCTalk.templateStyle = + ` +
+ `; + + DCCTalk.templateElements = + `
+
[speech]
`; + + DCCDialog.editableCode = false; + customElements.define("dcc-dialog", DCCDialog); + DCCTalk.editableCode = false; + customElements.define("dcc-talk", DCCTalk); +})(); \ No newline at end of file diff --git a/dccs/components/dcc-expression.js b/dccs/components/dcc-expression.js new file mode 100644 index 0000000..527cc5e --- /dev/null +++ b/dccs/components/dcc-expression.js @@ -0,0 +1,43 @@ +/* Expression DCC + ****************/ +class DCCExpression extends DCCBase { + constructor() { + super(); + } + + async connectedCallback() { + const result = await window.messageBus.ext.request("var/" + this.expression + "/get", "", + "var/" + this.expression); + + let template = document.createElement("template"); + template.innerHTML = + DCCExpression.templateElements.replace("[result]", result.message); + + this._shadow = this.attachShadow({mode: "open"}); + this._shadow.appendChild(template.content.cloneNode(true)); + } + + /* + * Property handling + */ + + static get observedAttributes() { + return ["expression"]; + } + + get expression() { + return this.getAttribute("expression"); + } + + set expression(newValue) { + this.setAttribute("expression", newValue); + } +} + +(function() { + DCCExpression.templateElements = + `[result]`; + + DCCExpression.elementTag = "dcc-expression"; + customElements.define(DCCExpression.elementTag, DCCExpression); +})(); \ No newline at end of file diff --git a/dccs/components/dcc-image-marker.js b/dccs/components/dcc-image-marker.js new file mode 100644 index 0000000..d7ad115 --- /dev/null +++ b/dccs/components/dcc-image-marker.js @@ -0,0 +1,371 @@ +/* Image Marker DCC + ******************/ +class DCCImageMarker extends DCCBase { + constructor() { + super(); + + this._pendingRequests = 0; + + this._currentState = 0; + this._stateVisible = false; + + /* + this._showState = this._showState.bind(this); + this._hideState = this._hideState.bind(this); + this._changeState = this._changeState.bind(this); + this.defineStates = this.defineStates.bind(this); + */ + + this.markerSpot = this.markerSpot.bind(this); + } + + async connectedCallback() { + /* + this._presentation.addEventListener("mouseover", this._showState); + this._presentation.addEventListener("mouseout", this._hideState); + this._presentation.addEventListener("click", this._changeState); + */ + + // limited: considers only one group per page + /* + this.completeId = this.id; + if (!this.hasAttribute("states") && window.messageBus.page.hasSubscriber("dcc/marker-states/request")) { + this.context = await window.messageBus.page.request("dcc/marker-context/request", this.id, "dcc/marker-context/" + this.id); + this.completeId = this.context.message + "." + this.id; + + window.messageBus.page.subscribe("dcc/marker-states/" + this.id, this.defineStates); + window.messageBus.page.publish("dcc/marker-states/request", this.id); + this._pendingRequests++; + } + + this._checkRender(); + + window.messageBus.ext.publish("var/" + this.completeId + "/subinput/ready", + {sourceType: DCCStateSelector.elementTag, + content: this.innerHTML}); + */ + + this._renderInterface(); + } + + /* + disconnectedCallback() { + this._presentation.removeEventListener('mouseover', this._showState); + this._presentation.removeEventListener('mouseout', this._hideState); + this._presentation.removeEventListener('click', this._changeState); + } + + defineStates(topic, message) { + window.messageBus.page.unsubscribe("dcc/marker-states/" + this.id, this.defineStates); + this.states = message; + this._pendingRequests--; + this._checkRender(); + } + + _checkRender() { + if (this._pendingRequests == 0) + this._renderInterface(); + } + */ + + /* + * Property handling + */ + + static get observedAttributes() { + return ["id", "label", "states", "colors"]; + } + + get id() { + return this.getAttribute("id"); + } + + set id(newValue) { + this.setAttribute("id", newValue); + } + + get label() { + return this.getAttribute("label"); + } + + set label(newValue) { + this.setAttribute("label", newValue); + } + + get coords() { + return this.getAttribute("coords"); + } + + set coords(newValue) { + this.setAttribute("coords", newValue); + } + + get states() { + return this.getAttribute("states"); + } + + set states(newStates) { + this.setAttribute("states", newStates); + } + + get colors() { + return this.getAttribute("colors"); + } + + set colors(newColors) { + this.setAttribute("colors", newColors); + } + + /* Rendering */ + + _renderInterface() { + window.messageBus.page.publish("dcc/marker-spot/set", + {label: this.label, + coords: this.coords, + handler: this.markerSpot}); + /* + if (this._presentation != null) { + if (this._presentationState != null) { + if (this._stateVisible && this.states != null) { + const statesArr = this.states.split(","); + this._presentationState.innerHTML = "[" + statesArr[this._currentState] + "]"; + } else + this._presentationState.innerHTML = ""; + } + this._presentation.className = + DCCStateSelector.elementTag + "-template " + + DCCStateSelector.elementTag + "-" + this._currentState + "-template"; + } + */ + } + + /* Event handling */ + + markerSpot() { + console.log("***** Spot *****"); + } + + /* + _showState() { + this._stateVisible = true; + this._renderInterface(); + } + + _hideState() { + this._stateVisible = false; + this._renderInterface(); + } + + _changeState() { + if (this.states != null) { + const statesArr = this.states.split(","); + this._currentState = (this._currentState + 1) % statesArr.length; + window.messageBus.ext.publish("var/" + this.completeId + "/state_changed", + {sourceType: DCCInput.elementTag, + state: statesArr[this._currentState]}); + } + this._renderInterface(); + } + */ +} + +/* Group Marker DCC + ******************/ +class DCCGroupMarker extends DCCBase { + constructor() { + super(); + this.requestContext = this.requestContext.bind(this); + this.requestStates = this.requestStates.bind(this); + this.setMarkerSpot = this.setMarkerSpot.bind(this); + } + + connectedCallback() { + const templateHTML = DCCGroupMarker.templateElements.replace("[image]", this.image); + + // building the template + let template = document.createElement("template"); + template.innerHTML = templateHTML; + let shadow = this.attachShadow({mode: "open"}); + shadow.appendChild(template.content.cloneNode(true)); + + this._imageG = shadow.querySelector("#imageG"); + + /* + this._image = shadow.querySelector("#image-src"); + this._imageMap = shadow.querySelector("#image-map"); + this._imageCanvas = shadow.querySelector("#image-canvas"); + this._canvas = this._imageCanvas.getContext("2d") + */ + + /* + console.log("image width: " + this._image.clientWidth); + console.log("image height: " + this._image.clientHeight); + console.log("canvas width: " + this._imageCanvas.width); + console.log("canvas height: " + this._imageCanvas.height); + + this._propX = this._image.clientWidth / this._imageCanvas.width; + this._propY = this._image.clientHeight / this._imageCanvas.height; + */ + + window.messageBus.page.subscribe("dcc/marker-context/request", this.requestContext); + window.messageBus.page.subscribe("dcc/marker-states/request", this.requestStates); + window.messageBus.page.subscribe("dcc/marker-spot/set", this.setMarkerSpot); + + window.messageBus.ext.publish("var/" + this.context + "/group_input/ready", + DCCGroupSelector.elementTag); + } + + disconnectedCallback() { + window.messageBus.page.unsubscribe("dcc/marker-context/request", this.requestContext); + window.messageBus.page.unsubscribe("dcc/marker-states/request", this.requestStates); + window.messageBus.page.unsubscribe("dcc/marker-spot/set", this.setMarkerSpot); + } + + + requestStates(topic, message) { + window.messageBus.page.publish("dcc/marker-states/" + message, this.states); + } + + requestContext(topic, message) { + window.messageBus.page.publish("dcc/marker-context/" + message, this.context); + } + + /* + * Property handling + */ + + static get observedAttributes() { + return ["image", "context", "states", "colors"]; + } + + get image() { + return this.getAttribute("image"); + } + + set image(newValue) { + this.setAttribute("image", newValue); + } + + get context() { + return this.getAttribute("context"); + } + + set context(newValue) { + this.setAttribute("context", newValue); + } + + get states() { + return this.getAttribute("states"); + } + + set states(newStates) { + this.setAttribute("states", newStates); + } + + get colors() { + return this.getAttribute("colors"); + } + + set colors(newColors) { + this.setAttribute("colors", newColors); + } + + /* Event handling */ + setMarkerSpot(topic, message) { + let rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + let coordsArr = message.coords.split(","); + let x1 = parseInt(coordsArr[0]), + y1 = parseInt(coordsArr[1]), + x2 = parseInt(coordsArr[2]), + y2 = parseInt(coordsArr[3]); + rect.setAttributeNS(null, 'x', x1); + rect.setAttributeNS(null, 'y', y1); + rect.setAttributeNS(null, 'width', x2-x1); + rect.setAttributeNS(null, 'height', y2-y1); + rect.addEventListener("mouseover", message.handler); + this._imageG.appendChild(rect); + + /* + let area = document.createElement("area"); + area.alt = message.label; + area.title = message.label; + area.coords = message.coords; + area.shape = "rect"; + area.addEventListener("mouseover", message.handler); + this._imageMap.appendChild(area); + + console.log(area.coords); + + let coordsArr = message.coords.split(","); + let x1 = parseInt(coordsArr[0]), + y1 = parseInt(coordsArr[1]), + x2 = parseInt(coordsArr[2]), + y2 = parseInt(coordsArr[3]); + this._canvas.rect(x1, y1, x2-x1, y2-y1); + this._canvas.stroke(); + */ + } +} + +(function() { + +DCCImageMarker.elementTag = "dcc-image-marker"; +customElements.define(DCCImageMarker.elementTag, DCCImageMarker); + +DCCGroupMarker.templateElements = + ` + + + + + `; + +/* +DCCGroupMarker.templateElements = + ` +
+
+ + +
+
+ `; +*/ + +DCCGroupMarker.elementTag = "dcc-group-marker"; +customElements.define(DCCGroupMarker.elementTag, DCCGroupMarker); + +// + +})(); \ No newline at end of file diff --git a/dccs/components/dcc-input.js b/dccs/components/dcc-input.js new file mode 100644 index 0000000..4c5c0b4 --- /dev/null +++ b/dccs/components/dcc-input.js @@ -0,0 +1,104 @@ +/** + * Input DCC + */ + + +class DCCInput extends DCCBlock { + constructor() { + super(); + // this.submitInput = this.submitInput.bind(this); + this.inputTyped = this.inputTyped.bind(this); + this.inputChanged = this.inputChanged.bind(this); + } + + connectedCallback() { + super.connectedCallback(); + + window.messageBus.ext.publish("var/" + this.variable + "/input/ready", DCCInput.elementTag); + } + + /* + * Property handling + */ + + static get observedAttributes() { + return DCCBlock.observedAttributes.concat(["variable", "rows", "vocabulary"]); + } + + get variable() { + return this.getAttribute("variable"); + } + + set variable(newValue) { + this.setAttribute("variable", newValue); + } + + get rows() { + return this.getAttribute("rows"); + } + + set rows(newValue) { + this.setAttribute("rows", newValue); + } + + get vocabulary() { + return this.getAttribute("vocabulary"); + } + + set vocabulary(newValue) { + this.setAttribute("vocabulary", newValue); + } + + /* Event handling */ + + inputTyped() { + window.messageBus.ext.publish("var/" + this.variable + "/typed", + {sourceType: DCCInput.elementTag, + value: this._inputVariable.value}); + } + + inputChanged() { + window.messageBus.ext.publish("var/" + this.variable + "/changed", + {sourceType: DCCInput.elementTag, + value: this._inputVariable.value}); + } + + /* Rendering */ + + elementTag() { + return DCCInput.elementTag; + } + + _injectDCC(presentation, render) { + presentation.innerHTML = this._generateTemplate(render); + const selector = "#" + this.variable.replace(/\./g, "\\."); + this._inputVariable = presentation.querySelector(selector); + this._inputVariable.addEventListener("input", this.inputTyped); + this._inputVariable.addEventListener("change", this.inputChanged); + } + + _generateTemplate(render) { + let elements = null; + if (this.hasAttribute("rows") && this.rows > 1) + elements = DCCInput.templateElements.area.replace("[rows]", this.rows) + .replace("[variable]", this.variable) + .replace("[render]", render); + else + elements = DCCInput.templateElements.text.replace("[variable]", this.variable) + .replace("[render]", render); + + return elements; + } +} + +(function() { + // temporary (size = 50) + DCCInput.templateElements = { + text: "", + area: "