I have a javascript code which contains more number of functions. inside each functions code looks similar. Is there any way to reduce and optimize the code using javascript oop. So my script goes like this.
function cal_a() {
var a_list = [];
function fetch_dom() {
var a = document.getElementById("pOne");
a.innerHTML = "Hello";
a_list.push("Hello");
}
fetch_dom();
}
function cal_b() {
var b_list = [];
function fetch_dom() {
var b = document.getElementById("pTwo");
b.innerHTML = "World";
b_list.push("World");
}
fetch_dom();
}
cal_a();
cal_b();
//..
//..
//..
//cal_z();
HTML code looks
<p id="pOne"></p>
<p id="pTwo"></p>
Please pardon me if the question is wrong. Thanks in advance.
I have to say the list doesn't do anything here
function cal(id, text) {
var list = [];
function fetch_dom() {
var el = document.getElementById(id);
el.innerHTML = text;
list.push(text);
}
fetch_dom();
}
cal('id', 'text');
Sure, pull out the common parts and make a function which returns a function.
function make_cal(elem_id, text) {
return function() {
var list = [];
function fetch_dom() {
var b = document.getElementById(elem_id);
b.innerHTML = text;
list.push(text);
}
fetch_dom();
}
}
let cal_a = make_cal("pOne", "Hello");
let cal_b = make_cal("pTwo", "World");
The fetchDom is better to be placed on object constructor:
function Cal(elClass, text) {
this.list = [];
this.elClass = elClass;
this.text = text;
}
Cal.prototype.fetchDom = function() {
var el = document.getElementById(this.elClass);
el.innerHTML = this.text;
this.list.push(el);
};
var calA = new Cal("pOne", "Hello");
var calB = new Cal("pTwo", "World");
calA.fetchDom();
calB.fetchDom();
Then you can access your lists by:
calA.list;
calB.list;
Related
I made some functions, but they are all doing approximately the same thing.
I would like to combine those functions into one new function that can be reused in case i need one more new function like this.. Is it possible to do so or am i just wasting your and my time?
Here is the code:
function getBinding(selectedBinding) {
var b = elems.binding;
var selectedBinding = b.options[b.selectedIndex].value;
return selectedBinding;
}
// Getting the holes value
function getHoles(selectedHoles) {
var h = elems.holes;
var selectedHoles = h.options[h.selectedIndex].value;
return selectedHoles;
}
// Getting the paper weight value
function getPaperWeight(selectedPaperWeight) {
var pW = elems.paperWeight;
var selectedPaperWeight = pW.options[pW.selectedIndex].value;
return selectedPaperWeight;
}
// Getting the staples value
function getStaples(selectedStapling) {
var s = elems.stapling;
var selectedStapling = s.options[s.selectedIndex].value;
return selectedStapling;
}
any suggestions?
Thanks a lot!
You could take the element as parameter.
function getValue(element) {
var e = elems[element];
return e.options[e.selectedIndex].value;
}
I would get the prop type as parameters -
function selectByPropAndIndex(prop){
var elemByProp = elems[prop];
var selected= elemByProp.options[elemByProp.selectedIndex].value;
return selected;
}
You can use partial application to create this kind of functions:
function getItems(elementType) {
return function(elements) {
var items = elements[elementType];
return items.options[items.selectedIndex].value;
};
}
var getBinding = getItems('binding');
var getHoles = getItems('holes');
var getPaperWeight = getItems('paperWeight');
var getStaples = getItems('stapling');
Usage:
getBinding(elems);
You can try this:
function getSelectedProperty(property) {
var elem = elems[property];
return elem.options[elem.selectedIndex].value;
}
Note also that your original code has some problem. The parameters are useless because you are defining a new variable inside each function that would override the parameter name because you gave it the same name. As an example:
function foo(x) {
var x = 5; // this x is not the same as the parameter x
}
function getBinding(selectedElement, type) {
switch(type) {
case binding:
var element = elems.binding;
break;
case hole:
var element = elems.holes;
break;
case paper:
var element = elems.paperWeight;
break;
case staples:
var element = elems.stapling;
break;
}
var selectedElement = element.options[element.selectedIndex].value;
return selectedElement;
}
Something like getByKey?
//
function getValueByKey(key) {
var elem = elems[key];
var optionValue = elem.options[elem.selectedIndex].value;
return optionValue;
}
This is how i fixed it!
function getValue(selector){
return parseInt(selector.options[selector.selectedIndex].value);
};
Thanks all!
I am trying to call the method getTitulo, getDuracion and getLink inside the cancion.js file but when i call the function it returns the following error: "listaCanciones_Lcl[i].getTitulo is not a function". I have searched in different websites but i didnt got lucky with finding an answer. Hopefully someone here can give me some help, i will gladly appreciate it!
//Logic.js file
var listaCanciones = [],
ejecuTitulo = '',
ejecuDuracion = '',
ejecuLink = '';
var btnGenerarLista = document.getElementById("addList").addEventListener("click", agregarCanc);
var btnAgregarLista = document.getElementById("gnrList").addEventListener("click", llenarTabla);
function agregarCanc (){
var nameSong = document.querySelector('#nameSong').value;
var duraSong = document.querySelector('#duraSong').value;
var linkSong = document.querySelector('#linkSong').value;
var objCancion = new Cancion(nameSong, duraSong, linkSong);
listaCanciones.push(objCancion);
var listaCancionesJson = JSON.stringify(listaCanciones);
localStorage.setItem('json_canciones', listaCancionesJson);
}
function llenarTabla (titulo){
var celdaTitulo = document.querySelector('#tituloList'),
celdaDuracion = document.querySelector('#duracionList'),
celdaLink = document.querySelector('#linkList'),
listaCanciones_Lcl = JSON.parse(localStorage.getItem('json_canciones'));
for(var i=0; i<listaCanciones_Lcl.length;i++){
// Acceder a lista canciones
I am getting an error in this line, where is says "getTitulo" is not a function but i dont really know why?
var nodoTextoTitulo = document.createTextNode(listaCanciones_Lcl[i].getTitulo()),
nodoTextoDuracion = document.createTextNode(listaCanciones_Lcl[i].getDuracion()),
nodoTextoLink = document.createTextNode(listaCanciones_Lcl[i].getLink());
// Create td
var elementoTdTitulo = document.createElement('td'),
elementoTdDuracion = document.createElement('td'),
elementoTdLink = document.createElement('td');
// Celda Id Append Child
elementoTdTitulo.appendChild(nodoTextoTitulo);
elementoTdDuracion.appendChild(nodoTextoDuracion);
elementoTdLink.appendChild(nodoTextoLink);
// Fila Append Child
celdaTitulo.appendChild(elementoTdTitulo);
celdaDuracion.appendChild(elementoTdDuracion);
celdaLink.appendChild(elementoTdLink);
}
}
//Cancion.js File
var Cancion = function(pTitulo, pDuracion, pLink){
var id = 0;
var titulo = pTitulo;
var duracion = pDuracion;
var link = pLink;
this.getId = function (){
return id;
};
this.setTitulo = function (pTitulo){
titulo = pTitulo;
};
this.getTitulo = function(){
return titulo;
};
this.setDuracion = function(pDuracion){
duracion = pDuracion;
};
this.getDuracion = function(){
return duracion;
};
this.setLink = function (pLink){
link = pLink;
};
this.getLink = function(){
return link;
};
};
First, make sure you are loading the Cancion.js file before the others in your HTML. Your problem is that when you parse the JSON back out of local storage, Cancion is not a known object, so getTitulo is undefined. You'll have to do listaCanciones_Lcl[i].titulo; instead.
And another change you'll need is to loosen the scope of your variables. The reason you need this.x = pX is because before JSON.stringify(new Cancion(1, 2, 3)) just returned "{}". With this code it returns "{"id":0,"titulo":1,"duracion":2,"link":3}", which I think is what you were after.
function Cancion(pTitulo, pDuracion, pLink){
this.id = 0;
this.titulo = pTitulo;
this.duracion = pDuracion;
this.link = pLink;
this.getId = function (){
return this.id;
};
this.setTitulo = function (pTitulo){
this.titulo = pTitulo;
};
this.getTitulo = function(){
return this.titulo;
};
this.setDuracion = function(pDuracion){
this.duracion = pDuracion;
};
this.getDuracion = function(){
return this.duracion;
};
this.setLink = function (pLink){
this.link = pLink;
};
this.getLink = function(){
return this.link;
};
};
var objWithFunction = {
name: 'Object with Function',
getName: function() { return this.name }
};
undefined
objWithFunction.getName() // --> "Object with Function"
var string = JSON.stringify(objWithFunction)
string // -=> "{"name":"Object with Function"}"
JSON is for data only..
Better you create a model, and fill it with data.. but this model has to exist in your application.. or you load the model parallel to your data..
function SomeThing() {};
SomeThing.prototype.getName = function() { return this.name };
var Thing1 = new SomeThing(JSON.parse("{name:'ThingOne'}"));
Thing1.getName(); // ThingOne
I created the array in the scope of $(document).ready(function(){});
for example:
$(document).ready(function(){
$.getJSON("data.json", function(json) {
function Question(q,correactA,array)
{
this.question=q;
this.correct_a=correactA;
this.answers=array;
}
multiQ= new Array();
for (i=0;i<5;i++)
{
var q = json.questions[i].question;
var corA= json.questions[i].correct_answer;
var a = json.questions[i].answers;
var aString = "";
Object.keys(a).forEach(function (k) {aString += a[k] ;})
multiQ[i]=new Question(q,corA,aString);
}
for (i=0;i<5;i++)
{
console.log(multiQ[i]);
}
});
});
Now I want to send the multiQ array to external var outside the scope.
How can I do it?
Declare
var multiQ= new Array();
outside $(document).ready function:
var multiQ= new Array();
$(document).ready(function(){
$.getJSON("data.json", function(json) {
function Question(q,correactA,array)
{
this.question=q;
this.correct_a=correactA;
this.answers=array;
}
for (i=0;i<5;i++)
{
var q = json.questions[i].question;
var corA= json.questions[i].correct_answer;
var a = json.questions[i].answers;
var aString = "";
Object.keys(a).forEach(function (k) {aString += a[k] ;})
multiQ[i]=new Question(q,corA,aString);
}
for (i=0;i<5;i++)
{
console.log(multiQ[i]);
}
});
});
It's very ugly, but you could assign a global getter inside the document.ready. For example:
var multiQ = new Array();
window.getMultiQ = function() { return multiQ; }
Then outside of document ready, you could call "var q = getMultiQ();"
Again, this is very ugly and would lead to unmaintainable code very fast. Most likely, there's an easier/cleaner way to accomplish what you're trying to do.
This is my code:
function Todo(id, task, who, dueDate) {
this.id = id;
this.task = task;
this.who = who;
this.dueDate = dueDate;
this.done = false;
}
var todos = new Array();
window.onload = init;
function init() {
var submitButton = document.getElementById("submit");
submitButton.onclick = getFormData;
var searchButton = document.getElementById("button");
searchButton.onclick = search;
}
//function to add todo items to the todos array
function search() {
for (var i = 0; i < todos.legnth; i++) {
var todoObj = todos[i];
console.log(todoObj[0]);
}
}
This is not all of my code, but the last function is where I am having trouble. I can't seem to access the global todos array. I've tried passing it as a parameter to the search function. I've tried even doing i < window.todos.length. I would appreciate any help.
The problem is that you have a typo.
Replace
todos.legnth
with
todos.length
I added onkeyup javascript for a dynamically added textbox in javascript... But it doesnt seem to work....
var cell4 = row.insertCell(3);
cell4.setAttribute('align','center')
var e3 = document.createElement('input');
e3.type = 'text';
e3.name = 'txtqt' + iteration;
e3.id = 'txtqt' + iteration;
e3.onkeyup = totalAmount(event,this,'tblsample');//Adding this lines doesnt work
e3.size = 10;
cell4.appendChild(e3);
But when i used
e3.onkeyup = totalAmount;
It worked... Here is my javascript function,
function totalAmount(e,obj,tblid)
{
var tbl = document.getElementById(tblid);
//alert(tbl);
var tblRows = tbl.rows.length;
//alert(tblRows);
var result =0;
var str1;
if (obj != null) {
str1 = obj.id;
} else {
str1 = this.id;
}
var lastChar = str1.substring(5,str1.length);
//alert(lastChar);
if(str1=='txtqt'+lastChar)
{
var str2 = 'txtup'+lastChar;
var str3 = 'txtAmount'+lastChar;
var txtDeduct = document.getElementById(str1).value;
var txtAmt = document.getElementById(str2).value;
var txtTotal = document.getElementById(str3);
var totRes = txtAmt*txtDeduct;
//var res = formatNumber(totRes,2)
txtTotal.value = totRes.toFixed(2)
document.getElementById('txttotAmount').value = totRes.toFixed(2);
for(i=1;i<=tblRows;i++)
{
//alert(tblRows);
txtTotID = 'txtAmount'+i;
if(document.getElementById(txtTotID).value!='')
{
result =parseFloat(result) + parseFloat(document.getElementById(txtTotID).value);
//var res= formatNumber(result,2)
document.getElementById('txtTotalAmount').value = result.toFixed(2);
document.getElementById('txttotAmount').value = result.toFixed(2);
//document.getElementById('txtTotalAmount').value = result;
}
}
}
}
You need to wrap your function call in an anonymous function:
e3.onkeyup = function(event){ totalAmount(event,this,'tblsample'); }
But an even better way to do it, to allow for cross browser compatibility would be to use an addEvent function:
function addEvent(obj,type,fn){
if (obj.addEventListener){
obj.addEventListener(type,fn,false);
} else if(obj.attachEvent){
obj["e"+type+fn]=fn;
obj[type+fn]=function(){
obj["e"+type+fn](window.event);
};
obj.attachEvent("on"+type,obj[type+fn]);
};
};
And then add the event using that function:
addEvent(e3,'keyup',function(event){ totalAmount(event,this,'tblsample'); });
Just a much better way to handle events. I would recommend you switch to this method.
onkeyup is a function. If you pass it the return value of totalAmount(event,this,'tblsample'); it won't work (unless it returns a function).
e3.onkeyup = totalAmount; is probably enough.
then inside totalAmount..
function totalAmount(event) {
alert(this); // this is the e3 object
}
So if you need the this and the 'tblsample' arguments, I suggest you add them to the e3 object so that you can access them through the this keyword inside the totalAmount function:
e3.otherScope = this;
e3.tblid = 'tblsample;
e3.onkeyup = totalAmount;
and..
function totalAmount(event) {
alert(this); // this is the e3 object
alert(this.otherScope); // the `this` object in the other scope
alert(this.tblid); // 'tblsample'
}
Or you can simply just do
var otherScope = this;
e3.onkeyup = function(event) {
totalAmount(event, otherSope, 'tblsample');
};