How to build-in array sub-function in my setAttribute function? - javascript

I have written a function that automatically inserts an attribute (i.e. a per case adapted onclick function) in input elements. It also makes a few exceptions. It looks like this, somewhat simplified for clarity reasons:
function insertAttribute() {
var allInputs = document.getElementsByTagName('input');
var allInputsCount = allInputs.length;
var thatInput = null;
for (i = 0; i < allInputsCount; i++) {
thatInput = allInputs[i];
var highlightFunction = "highlightItem('"+thatInput.name+"-row','"+thatInput.name+"-button')";
if ((thatInput.name != "A") && (thatInput.name != "B") && (thatInput.name != "C"))
thatInput.setAttribute("onclick",highlightFunction);
}
}
The problem is, there are some 20 exceptions. I could expand the if line, but I would rather do it with an array. But how do I do that? I googled how to use array in javascript function, and the (two top) results suggest I should do it like this:
function insertAttribute() {
var allInputs = document.getElementsByTagName('input');
var allInputsCount = allInputs.length;
var thatInput = null;
for (i = 0; i < allInputsCount; i++) {
thatInput = allInputs[i];
var highlightFunction = "highlightItem('"+thatInput.name+"-row','"+thatInput.name+"-button')";
var exceptedArray = ["A","B","C"];
if (thatInput.name != exceptedArray)
thatInput.setAttribute("onclick",highlightFunction);
}
}
But that doesn't work -- the attribute is still inserted in the exceptions. How should it be done? I would need a vanilla script solution. I'll be happy with a good tutorial, too. As you might have guessed, this is the first time I'm using such an array sub-function.

The solution offered in the comment, exceptedArray.indexOf(thatInput.name)==-1 worked in most browsers, but not in IE8. Its script debugger said that it did not support indexOf. It does in other contexts, but apparently not in this context.
In the meantime, I learned how to make a script loop through an array myself. And this works in all browsers:
var allInputs = document.getElementsByTagName('input');
var allInputsCount = allInputs.length;
var thatInput = null;
for (var i=0; i<allInputsCount; i++) {
thatInput = allInputs[i];
var highlightFunction = "highlightItem('"+thatInput.name+"-row','"+thatInput.name+"-button')";
var exceptedNamesArray = ["A","B","C","A4dTInput","A4eTInput"];
var excNamesArrayCount = exceptedNamesArray.length;
var excName = null;
for (var j=0; j<excNamesArrayCount; j++) {
excName = exceptedNamesArray[j];
if (thatInput.name != excName)
thatInput.setAttribute("onclick",highlightFunction);
}
}

Related

Strange error when appending elements in JavaScript

I've been getting a problem when trying to append an element in JavaScript, the error I've been getting looks a bit like this:
Uncaught TypeError: Failed to execute appendChild on Node: parameter 1 is not of type Node.
I'm also using using a framework called Interact.js just so you know
here's the peice of code that the browser isn't happy about:
var tempText = [];
var classNum = event.relatedTarget.getElementsByClassName('text');
var newCont = document.createElement('div');
for(var i = 0; i < classNum.length; i++){
tempText.push(event.relatedTarget.getElementsByClassName('text')[i].textContent);
}
for(var i = 0; i < tempText.length; i++){
var pText = document.createElement('p').appendChild(tempText);
newCont.appendChild(pText[i]);
}
var placement = document.getElementById('toolbar')[0];
placement.appendChild(newCont);
I just noticed a small mistake. The document.getElementById returns only a single object. So don't use the [0]:
var placement = document.getElementById('toolbar'); // There is no [0]. Remove it.
placement.appendChild(newCont);
But the whole thing is really easy to do using jQuery. Since you are fine with using a jQuery solution, read on. Please include the jQuery library by adding this piece:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
And the JavaScript would be:
var tempText = [];
var classNum = event.relatedTarget.getElementsByClassName('text');
var newCont = document.createElement('div');
for (var i = 0; i < classNum.length; i++) {
tempText.push(event.relatedTarget.getElementsByClassName('text')[i].textContent);
}
for (var i = 0; i < tempText.length; i++) {
// Change here:
var pText = $("<p />", {html: tempText});
$(newCont).append(pText);
}
var placement = $('#toolbar');
placement.append(newCont);
Since I am unaware of the HTML underlying, I just guessed it and converted a few to jQuery.
As you tagged your question with jquery, you can condense your code to this:
var $newCont = $('<div>');
$('.text', event.relatedTarget).each(function() {
$newCont.append($('<p>').append($(this).text()));
})
$('#toolbar').append($newCont);
Or in a functional programming way:
$('#toolbar').append($('<div>').append(
$('.text', event.relatedTarget).map(function() {
return $('<p>').append($(this).text());
}).get()
));

Console.log gives correct output but when accessing set value it gives wrong output

Called Function:
this.findVerticalPossibleScoring = function(){
var possibilitySet = [];
for (var j = 0; j < 9;j++ ) {
for (var i = 0; i < 7; ){
var tempTile = this._tiles[i][j];
if(this.gameTilesValue[i][j]!=-1){
var tileTagValue = this.gameTilesValue[i][j];
if(this.gameTilesValue[i+1][j]==tileTagValue && this.gameTilesValue[i+2][j]==tileTagValue){
setElement = [];
do{
var tempPoint = this.makeArray(i,j);
setElement.push(tempPoint);
console.log(" verical i:"+i+" j:"+j);
i=i+1;
}while(i<9&&this.gameTilesValue[i][j]==tileTagValue);
possibilitySet.push(setElement);
continue;
}
}
i = i+1;
}
}
return possibilitySet;
};
this.makeArray = function (a,b){
console.log("element i:"+a+" j:"+b);
var arrayTemp = [];
arrayTemp.push(a);
arrayTemp.push(b);
return arrayTemp;
};
Calling function part:
if(scoringPossible == true){
//blast the tiles and add new tiles;
var verticalPossibleScoring = this.findVerticalPossibleScoring();
toBeDeletedTiles = [];
for(var i=0;i<verticalPossibleScoring.length;i++){
var tempSet = verticalPossibleScoring[i];
for(var j = 0;j<tempSet.length;j++){
var tempSetEntry = tempSet[i];
console.log("TILE i:"+tempSetEntry[0]+" j:"+tempSetEntry[1]);
}
}
}
I have added called function as well as calling function if loop as calling function is too big. I know this is infamous javascript loop issue. I am using gc-devkit game engine which is new and I new to it. I had solved the same issue for UIImage in it by creating custom class, but here I don't require custom array for it. Can any one guide me through this issue. Thanks in advance.
You use j as your loop variable when iterating over tempSet but then use i when getting elements from tempSet. Maybe just change
var tempSetEntry = tempSet[i];
to
var tempSetEntry = tempSet[j];

InDesign: Delete Document Dictionary

I am having trouble deleting a document dictionary in InDesign CS 5.5.
I can clear the contents of a user dictionary using this script:
var myUserDictionaries = app.userDictionaries;
var myCountDict = myUserDictionaries.count();
for (var i = myCountDict-1; i >= 0; i-- ) {
myUserDictionary = myUserDictionaries[i];
var myAddedWords = myUserDictionary.addedWords;
myUserDictionary.removeWord(myAddedWords);
}
But this leaves the document dictionary untouched. A few years ago, this was an unresolved problem as seen on the Adobe forums.
But I found this code (from here):
var myHyphenations = app.activeDocument.hyphenationExceptions;
for (var i = 0; i < myHyphenations.length; i++) {
if (myHyphenations[i].name === "Danish") {
var mySourceDictionary = myHyphenations[i];
mySourceHyphenations = mySourceDictionary.addedExceptions;
break
}
}
Which seems to be able to access the document dictionary. But my question is (since I'm not much of a programmer), how to modify this code to clear or delete the document dictionary (for English:USA)?
Actually this turned out to be more simple than I anticipated.
Here's the script that will delete/clear a document dictionary:
var myHyphenations = app.activeDocument.hyphenationExceptions;
var myCountDict = myHyphenations.count();
for (var i = myCountDict-1; i >= 0; i-- ) {
myHyphenation = myHyphenations[i];
var myAddedWords = myHyphenation.addedExceptions;
myHyphenation.removeException(myAddedWords);
}

Unpredictable behaviour when setting a boolean variable in JavaScript [Deep copying in strict mode]

function computerSetManapool(cost) {
var splittedCost = cost.split(',');
for (var i = 0; i < splittedCost.length; i++) {
if (splittedCost[i] === "CL") {
for (var j = 0; j < computerLands.length; j++) {
if (!computerLands[j].tapped) {
computerLands[j].tapped = true;
console.log(computerLands[j].name + " gets tapped");
break;
}
}
}
}
}
I'm having a bit of trouble with this little piece of code, it's a Windows Store App, though I'm not using anything like the WinJS library or jQuery or what not.
Especially this line worries me:
computerLands[j].tapped = true;
I was debugging this in Visual Studio, while j had the value of 1. Therefore computerLands[1].tapped was supposed to be set to true.
Instead it set computerLands[1].tapped = true AND computerLands[3].tapped = true.
It does not happen every time, but many times and therefore I can't see what the problem is.
computerLands is an initially empty array, which then gets dynamically pushed objects into it.
If someone even has a remote idea what problem this could be, I would be really grateful.
Edit: This is the code where computerLands gets populated:
function computerTurn() {
untapAll("computer");
drawCards(1, "computer");
for (var i = 0; i < computerHand.length; i++) {
if (computerHand[i].type === "land") {
var container = document.getElementById("computerLandsContainer");
var newItem = document.createElement("div");
newItem.id = computerLandsID;
computerLandsID++;
newItem.style.backgroundImage = "url("+computerHand[i].image+")";
newItem.style.backgroundSize = "100%";
var btn1 = document.createElement("button");
btn1.id = "tapButtonComputer";
btn1.innerText = "˜";
newItem.appendChild(createEnlargeButton(newItem,"computer"));
newItem.appendChild(btn1);
container.appendChild(newItem);
computerLands.push(computerHand[i]);
console.log("Computer plays: " + computerHand[i].name);
computerLands[computerLands.length - 1].id = newItem.id;
var index = computerHand.indexOf(computerHand[i]);
computerHand.splice(index,1);
break;
}
}
}
The actual line is just this:
computerLands.push(computerHand[i]);
After pushing it into computerLands it gets removed from computerHand via splice().
var index = computerHand.indexOf(computerHand[i]);
computerHand.splice(index,1);
Finally I found a solution, I got it from this page: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/f79b2e68-15a9-4d5e-8aad-e15f78d94840/how-do-i-clone-an-object?forum=winappswithhtml5
It describes how to deep copy in Javascript in Windows Store Apps (this other solution I found http://james.padolsey.com/javascript/deep-copying-of-objects-and-arrays/ is not allowed in Windows Store Apps strict mode), basically you create a new object and copy every property into it. Now here's my new working code:
function populateComputerLands() {
for (var i = 0; i < 4; i++) {
//computerLands.push(availableComputerCards[0]); <--- old code
var objectToCopy = availableComputerCards[0]; // new code
var newObject = Object.create(Object.getPrototypeOf(objectToCopy));
var newObjectProperties = Object.getOwnPropertyNames(objectToCopy);
var propertyName;
for (var p in newObjectProperties) {
propertyName = newObjectProperties[p];
Object.defineProperty(newObject, propertyName, Object.getOwnPropertyDescriptor(objectToCopy, propertyName));
};
computerLands.push(newObject);
}
}

populate select element based on json

How could I populate a second select element? I've figured out how to do the first one. But how could I do the same for the second depending on which "Make" is selected? I've tried to talk myself through it while taking small steps but I'm thinking this may be too advanced for me.
var cars = '{"USED":[{"name":"Acura","value":"20001","models":[{"name":"CL","value":"20773"},{"name":"ILX","value":"47843"},{"name":"ILX Hybrid","value":"48964"},{"name":"Integra","value":"21266"},{"name":"Legend","value":"21380"},{"name":"MDX","value":"21422"},{"name":"NSX","value":"21685"},{"name":"RDX","value":"21831"},{"name":"RL","value":"21782"},{"name":"RSX","value":"21784"},{"name":"SLX","value":"21879"},{"name":"TL","value":"22237"},{"name":"TSX","value":"22248"},{"name":"Vigor","value":"22362"},{"name":"ZDX","value":"32888"}]},{"name":"Alfa Romeo","value":"20047","models":[{"name":"164","value":"20325"},{"name":"8c Competizione","value":"34963"},{"name":"Spider","value":"22172"}]}';
var carobj = eval ("(" + cars + ")");
var select = document.getElementsByTagName('select')[0];
//print array elements out
for (var i = 0; i < carobj.USED.length; i++) {
var d = carobj.USED[i];
select.options.add(new Option(d.name, i))
};
If I read your question right, you want to populate a second select with the models for the make in the first select. See below for a purely JS approach (with jsfiddle). If possible, I would recommend looking into jQuery, since I would prefer a jQuery solution.
http://jsfiddle.net/m5U8r/1/
var carobj;
window.onload = function () {
var cars = '{"USED":[{"name":"Acura","value":"20001","models":[{"name":"CL","value":"20773"},{"name":"ILX","value":"47843"},{"name":"ILX Hybrid","value":"48964"},{"name":"Integra","value":"21266"},{"name":"Legend","value":"21380"},{"name":"MDX","value":"21422"},{"name":"NSX","value":"21685"},{"name":"RDX","value":"21831"},{"name":"RL","value":"21782"},{"name":"RSX","value":"21784"},{"name":"SLX","value":"21879"},{"name":"TL","value":"22237"},{"name":"TSX","value":"22248"},{"name":"Vigor","value":"22362"},{"name":"ZDX","value":"32888"}]},{"name":"Alfa Romeo","value":"20047","models":[{"name":"164","value":"20325"},{"name":"8c Competizione","value":"34963"}, {"name":"Spider","value":"22172"}]}]}';
carobj = eval ("(" + cars + ")");
var makes = document.getElementById('make');
for (var i = 0; i < carobj.USED.length; i++) {
var d = carobj.USED[i];
makes.options.add(new Option(d.name, i));
}
makes.onchange = getModels;
getModels();
}
// add models based on make
function getModels () {
var makes = document.getElementById('make');
var make = makes.options[makes.selectedIndex].text;
for (var i = 0; i < carobj.USED.length; i++) {
if (carobj.USED[i].name == make) {
var models = document.getElementById('model');
models.options.length = 0;
for (var j= 0; j < carobj.USED[i].models.length; j++) {
var model = carobj.USED[i].models[j];
models.options.add(new Option(model.name, j));
}
break;
}
}
}
I would also recommend looking into safer JSON parsing. There is a security risk in using eval if it runs on any user input. You could look into JSON.org and their json2.js. Or if you want to use jQuery: parseJSON. Below is the jQuery version:
jQuery.parseJSON(jsonString);
JSON parsing tips from: Safely turning a JSON string into an object.

Categories