Can we return document.createElement("element")? - javascript

I have to create an input box multiple times, so I call a function like this multiple times:
function __createInputBox(id) {
var input = document.createElement("input");
input.setAttribute('id', id);
input.setAttribute('type', 'number');
input.setAttribute('name', id);
input.setAttribute('value', '0');
input.setAttribute('min', '0');
return input;
}
In my main function, I append it as such:
var box = __createInputBox(id);
element.appendChild(box);
I keep getting this error:
__createInputBox is not defined
So are we allowed to return the value from document.createElement("element")? If its bad to do so, what is the better way to add multiple elements to the page?
This how I declare the function:
function InputSpace(){
this.inputSpace = document.getElementById("inputspace");
this.num = 1;
function __createInputBox(id) {
// function declared here
}
This is the code where I call it:
InputSpace.prototype = {
constructor: InputSpace,
drawInputSpace : function () {
var i = 0,
max;
var table = document.createElement("TABLE");
var table_body = document.createElement("TBODY");
for(max = num; i<num; i++){
var element = document.createElement("TR");
var box = __createInputBox(id);
element.appendChild(box);
table_body.appendChild(element);
}
table.appendChild(table_body);
this.inputSpace.appendChild(table);
}

After reading the comments, we can return document.createElement("element") in from a function. The reason for the function is undefined error, was because I was calling a function outside its scope. The proper way to call an object's private function is shown here
Changing the code to access private functions properly:
function InputSpace(){
// public attributes
this.inputSpace = document.getElementById("inputspace");
this.num = 1;
}
InputSpace.prototype = (function(){
// private functions
var __createInputBox(id){
var input = document.createElement("input");
input.setAttribute('id', id);
input.setAttribute('type', 'number');
input.setAttribute('name', id);
input.setAttribute('value', '0');
input.setAttribute('min', '0');
return input;
};
return {
constructor: InputSpace,
// public functions
drawInputSpace : function () {
var i = 0,
max;
var table = document.createElement("TABLE");
var table_body = document.createElement("TBODY");
for(max = num; i<num; i++){
var element = document.createElement("TR");
var box = __createInputBox(id);
element.appendChild(box);
table_body.appendChild(element);
}
table.appendChild(table_body);
this.inputSpace.appendChild(table);
}
})();

Related

My Closure Won't Work

I'm trying to prevent polluting the global space with a bunch of variables, and since I can't use let yet, I have to make closures. So I have this basic webpage with a bootstrap accordion, each card hiding different examples. In one I have a form that asks in a <select> what your position is. OnChange it will grab the eventData object, call spillObject() (the closure method), and populate another accordion card with its contents. It works, but problem is, I can't seem to make it work as a simple closure. Nothing seems to happen, and since you can't debug a closure, other than making it spit out console.logs() everywhere, I can't find out what's wrong with it.
Here's the code:
$(function() {
$("#position").change( /*(*/ function(eventData) {
var div = $('#explodedObject');
div.html('');
var result = spillObject('#explodedObject', eventData, '');
/*};*/
div.append(result);
} /*)()*/ );
var spillObject = (function(dataParent, obj, heirarchy) {
var heirArr = heirarchy == '' ? [] : heirarchy.split('_');
heirArr.push(1);
var teir = heirArr.length - 1;
var id = "#collapse" + heirArr.join('');
var headerID = 'header' + heirArr.join('');
var card = document.createElement('div');
card.classList.add('card');
var cardHeader = document.createElement('div');
cardHeader.classList.add('card-header');
cardHeader.id = headerID;
var h5 = document.createElement('h5');
h5.classList.add('mb-0');
var button = document.createElement('button');
button.classList.add('btn', 'btn-link');
button.setAttribute('data-toggle', 'collapse');
button.setAttribute('data-target', id);
var cardBody = document.createElement('div');
cardBody.classList.add('card-body');
var collapse = document.createElement('div');
collapse.id = id.substr(1, id.length - 1);
collapse.classList.add('collapse');
collapse.setAttribute('data-parent', dataParent);
var dl = document.createElement('dl');
dl.id = '#' + heirArr.join('');
var dt;
var dd;
var x;
return function() {
for (x in obj) {
dt = document.createElement('dt');
dd = document.createElement('dd');
dt.innerHTML = x;
if (typeof obj[x] == 'object' && heirArr.length < 3) {
heirArr[teir]++;
innerObj = spillObject(dl.id, obj[x], heirArr.join('_'));
dd.appendChild(innerObj);
} else {
dd.innerHTML = obj[x];
}
dl.append(dt);
dl.append(dd);
}
heirArr.pop();
heirArr[heirArr.length - 1] = parseInt(heirArr[heirArr.length - 1]);
heirArr[heirArr.length - 1]--;
collapse.appendChild(cardBody);
button.innerHTML = 'card ' + heirArr.join('.');
h5.appendChild(button);
cardHeader.appendChild(h5);
card.appendChild(cardHeader);
card.appendChild(collapse);
cardBody.appendChild(dl);
return card;
};
});
})();
More basically, I'm following this template:
var method = (function(param){
var var1 = 'default value';
return function(){
var1 = 'something else';
};
})();
Should I have used this one instead, and if so would it hide the variables?
var method2 = function(param) {
return function() {
var var1 = 'default value';
};
};
It's because the result of spillObject is a function, you must then also call that function. Here's a simplified version of what you are doing.
var spillObject = (function(dataParent, obj, heirarchy) {
console.log('first function')
return function() {
console.log('second function')
};
});
var result = spillObject()
console.log(result)
result()

How to get parameter name as array?

in my code i'm using google map api. here i used onclick method for button. if i clicked that dynamically it shows multiple textboxes. here i enter values for all text fields. But when i passing the parameter name into servlet page it takes only the first value of text box. how to get all the values?
My code
var button = document.getElementById('waypoint-input');
button.addEventListener("click", function () {
var parentNode = document.getElementById('waypoints-list');
var input = document.createElement('input');
input.type = 'text';
input.placeholder = 'Enter a waypoint location';
input.id = 'waypoint' + me.waypointIndex;
input.inputId = me.waypointIndex;
**input.name = 'waypointlist';**
input.addEventListener('input', function () {
if (input.value == "") {
var waypoint = me.waypts.filter(function (obj) {
return obj.key === input.inputId;
})[0];
if (waypoint != null && typeof waypoint !== "undefined") {
var waypointIndexToRemove = me.waypts.map(function (el) {
return el.key;
}).indexOf(input.inputId);
me.waypts.splice(waypointIndexToRemove, 1);
me.route();
}
}
});
var removeInput = document.createElement('button');
removeInput.innerHTML = 'Remove';
removeInput.onclick = function () {
parentNode.removeChild(input);
parentNode.removeChild(removeInput);
var childInputs = parentNode.getElementsByTagName('input');
if (childInputs.length > 0) {
for (var i = 0; i < childInputs.length; i++) {
childInputs[i].inputId = i;
}
}
if (input.value != "" && input.value != null) {
var waypointIndexToRemove = me.waypts.map(function (el) {
return el.key;
}).indexOf(input.inputId);
me.waypts.splice(waypointIndexToRemove, 1);
for (var i = input.inputId; i < me.waypts.length; i++) {
me.waypts[i].key = me.waypts[i].key - 1;
}
me.route();
}
me.waypointIndex--;
}
parentNode.appendChild(input);
parentNode.appendChild(removeInput);
var waypointAutocomplete = new google.maps.places.Autocomplete(input, { placeIdOnly: true });
me.setupPlaceChangedListener(waypointAutocomplete, 'WAYPOINT', input.inputId);
me.waypointIndex++;
}, false);
I found the solution to my question.
There is no changes to my script. I simply call the parameter name in servlet page. The name is waypointlist. And I change my servlet code little bit.
That is
String[] waypointlist=request.getParameterValues("waypointlist");
String waypointarray="";
for(int i=0;i<waypointlist.length;i++)
{
waypointarray += waypointlist[i] +"/";
}

How to get HTML elment with help of ID?

Here is my JavaScript code:
function foo(){
var pagingButtons = document.createElement('div');
for(var j = 0; j < pagingObjects.length; j++ )
{
var pagingBtn = CreateHTMLElement("btnPaging"+j.toString(), "btnPaging", ShowPage, 'button', pagingObjects[j].value);
pagingBtn.setAttribute('data-start', pagingObjects[j].start);
pagingBtn.setAttribute('data-end',pagingObjects[j].end);
pagingButtons.appendChild(pagingBtn);
}
}
pagingArea.appendChild(table).appendChild(pagingButtons);
}
function CreateHTMLElement(id, name, onclick, type, value) {
var HTMLElement = document.createElement('input');
HTMLElement.id = id;
HTMLElement.name = name;
HTMLElement.onclick = onclick;
HTMLElement.type = type;
HTMLElement.value = value;
return HTMLElement;
}
I need to get from pagingArea button with id=btnPaging0.
How can I implement it?
document.getElementById("btnPaging0");

How to iterate anonymous function inside each function in Knockout viewmodel

I am building a Knockout viewmodel. The model has some fields like dateFrom, DateTo, Status and so forth. In addition, there is a list of invoices.
The invoices have some pricing information, which is a price object. My main object also have a price object, which should iterate all the invoice objects and find the total price.
My problem is the following:
The code runs smooth, until I add the following in my view:
<label data-bind="text:totalPrice().price().priceExVat"></label>
Here I get an:
TypeError: $(...).price is not a function
Which refers to my:
exVat += $(ele).price().priceExVat;
I don't understand it, because in my each function, I should have the element. The element have a price() function, so why would it not work? Is it some scope issue?
My viewmodel:
function invoice(invoiceDate, customerName, pdfLink, status) {
var self = this;
self.pdfLink = pdfLink;
self.print = ko.observable(0);
self.customerName = customerName;
self.status = status;
self.pdfPagesCount = function () {
return 1;
};
self.invoiceDate = invoiceDate;
self.price = function () {
return new price(1.8, 2.1);
};
}
function price(exVat, total) {
var self = this;
self.currency = '€';
self.total = total;
self.priceExVat = exVat;
self.vatPercentage = 0.25;
self.vatAmount = self.exVat - self.total;
self.priceExVatText = function() {
return self.priceExVat + ' ' + self.currency;
};
}
var EconomicsViewModel = function (formSelector, data) {
var self = this;
self.dateFrom = data.dateFrom;
self.dateTo = data.dateTo;
self.invoices = ko.observableArray([
new invoice('05-05-2014', 'LetterAmazer IvS', "http://www.google.com","not printed"),
new invoice('05-05-2014', 'LetterAmazer IvS', "http://www.google.com", "not printed")
]);
self.totalPrice = function () {
var exVat = 0.0;
$(self.invoices).each(function (index, ele) {
console.log(ele);
exVat += $(ele).price().priceExVat;
});
return price(exVat, 0);
};
};
From what I read, totalPrice is actually a price object, you don't need to put a .price():
<label data-bind="text:totalPrice().priceExVat"></label>
EDIT:
Sorry, there were also problems on your javascript:
self.totalPrice = function () {
var exVat = 0.0;
$(self.invoices()).each(function (index, ele) { //<-- add () to self.invoices to get the array
console.log(ele);
exVat += ele.price().priceExVat; //<-- remove useless jQuery
});
return new price(exVat, 0); //<-- add 'new'
};
Check this fiddle
EDIT2:
To answer robert.westerlund's comment, you could remove $().each and replace with ko.utils.arrayForEach or even simpler use a for loop:
var arr = self.invoices();
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
exVat += arr[i].price().priceExVat;
}
Updated fiddle

Why is my local storage not working?

Each user can dynamically create a table from a form. I am trying to save the table and its current state to local storage every time a change is made or the person exits the page. Name stores the name of the user and I am using it as a key. However, it is not working for me. I think I am saving the data when I need to using the saveData function and parsing it when I need to with the showData function. Can anyone tell me where I am going wrong please?
userDiv.onclick=(function() {
alert($(this).attr("id"));
name= $(this).attr("id");
window.location.href = "Createtask.html";
showData();//TRYING TO SHOW THE USER'S TABLE WHEN PAGE OPENS
}
function makeChart() {
table = document.createElement('table');
var taskName = document.getElementById('taskname').value,
header = document.createElement('th'),
numDays = document.getElementById('days').value, //columns
howOften = document.getElementById('times').value, //rows
row,
r,
col,
c;
var counter = 0;
var target = numDays * howOften;
var cel = null;
var myImages = new Array();
myImages[0] = "http://www.olsug.org/wiki/images/9/95/Tux-small.png";
myImages[1] = "http://a2.twimg.com/profile_images/1139237954/just-logo_normal.png";
var my_div = document.createElement("div");
my_div.id = "showPics";
document.body.appendChild(my_div);
var newList = document.createElement("ul");
my_div.appendChild(newList);
if (taskName == '' || numDays == '') {
alert('Please enter task name and number of days');
}
if (howOften == '') {
howOften = 1;
}
if (taskName != '' && numDays != '') {
for (var i = 0; i < myImages.length; i++) {
var allImages = new Image();
allImages.src = myImages[i];
allImages.onclick = function (e) {
if (sel !== null) {
sel.src = e.target.src;
my_div.style.display = 'none';
sel.onclick = null;
counter++;
sel = null;
if (counter == target) {
alert("Show some fireworks "+name+" gets a reward");
}
}
};
var li = document.createElement('ul');
li.appendChild(allImages);
newList.appendChild(li);
}
my_div.style.display = 'none';
header.innerHTML = taskName;
table.appendChild(header);
function addImage(col) {
var img = new Image();
img.src = "http://cdn.sstatic.net/stackoverflow/img/tag-adobe.png";
col.appendChild(img);
img.onclick = function () {
my_div.style.display = 'block';
sel = img;
saveData();
};
}
for (r = 0; r < howOften; r++) {
row = table.insertRow(-1);
for (c = 0; c < numDays; c++) {
col = row.insertCell(-1);
addImage(col);
}
}
document.getElementById('theRealHoldTable').appendChild(table);
document.getElementById('createChart').onclick = null;
saveData();/CALLING THE LOCAL STORAGE WHEN TABLE IS CREATED
}
}
function saveData(){
localStorage.setItem(name, JSON.stringify(table.innerHTML));
}
function showData(){
JSON.parse(localStorage.getItem( name ));
}
you are trying to stringify html-markup, which is not working! you are only able to JSON.stringify an js-object which means an instance of a class, an object literal or an array:
// this works because it is an instance
var objInstance = new SomeClass();
JSON.stringfy(objInstance);
// this works as it is an object-literal
var objLiteral = { mykey: 'myvalue' };
JSON.stringfy(objLiteral);
// this works as it is an array
var arr = [1, 2, 3]
JSON.stringfy(arr);
// THIS DOES NOT WORK!!!
JSON.stringify('<div>...</div>');
just strip the JSON.stringify part of your methods, that should work because element.innerHTML already returns a string:
function saveData(){
localStorage.setItem(name, table.innerHTML);
}
function showData(){
localStorage.getItem(name);
}

Categories

Resources