Why doesn't this javascript work assign .cells[] properly? - javascript

Why doesn't this work?
var row = document.getElementById(currentRow);
var otherRow = document.getElementById(targetRow);
row.cells[0] = otherRow.cells[0];
This works with
row.cells[0].innerHTML = otherRow.cells[0].innerHTML;
However, there are attributes attached to the cell which I also want to move over without having to manually recreate them.
Solution (Note: more is being done in my actual implementation, but this is the framework):
for (var i = 0; i < 4; i++) {
var copyTo = row.cells[i];
var copyFrom = otherRow.cells[i].cloneNode(true);
copyTo.parentNode.replaceChild(copyFrom, copyTo);
}

You should be able to use cloneNode() to actually clone the node and its attributes.

Each entry in cells refers to a DOMElement. When you typed row.cells[0] = otherRow.cells[0], you are saying that you want row.cell[0] to reference the same DOMElement as otherRow.cells[0].
I'm guessing you want row.cells[0] to have the same text or HTML as otherRow.cells[0]; in which case, the second code snippet will do just that, since you are actually modifying the DOMElement, and not just changing which DOMElement you are referencing.

Related

jQuery replaceWith not working without DOM

I am trying to do some element manipulation on a Node.js server where I need to take a string of HTML, then replace some of the nodes with other node types. This was working fine when I was doing it with a DOM but as soon as I don't have a DOM it does not work.
In a very simple example, I want to do something like this... where I find all the div elements and replace with spans.
const html = '<html><div>hello</div><div>hello</div></html>';
const obj = $(html);
const filter = $(obj).find('div');
for (let j = filter.length; j >= 0; j--) {
$(filter[j]).replaceWith("<span>goodbye</span>");
}
console.log(obj);
I can't just do a find and replace on the string as I don't want all elements I am doing a filter based on various things before I do this.
It is not working saying that the node is not an element. Is there a way I can do this? I have also tried using JSDOM to do this but again, no luck.
I want the console here to show the HTML element with two spans rather than two divs, I have tried adding a jsfiddle for this however I am getting a different error on here too, if anyone can help it would be appreciated.
http://jsfiddle.net/vkn285a1/1/
** UPDATE **
From the answer below, I have updated but I am now getting my desired result, thank you.. I had to change to use SVG which is what I am actually parsing and it worked a treat
const html = "<svg><g><text>hello</text><text>hello</text></g></svg>";
const obj = $.parseHTML(html);
const filter = $(obj).find("text");
for (let j = filter.length; j >= 0; j--) {
$(filter[j]).replaceWith("<span>goodbye</span>");
}
Your issue is following:
const obj = $(html);
this obj is NULL.
You have to use parseHTML function to get object from string as following.
const html = '<html><div>hello</div><div>hello</div></html>';
const obj = $.parseHTML(html);
Then obj will be an array of divs in html tag of string.
After that, you can try anything for those objects that are not NULL.

Remove / Replace class with another class without having an ID - Javascript only

Basicly i have two buttons one who will create divs with the class "TargetDummy" and another who should be able to remove the created "TargetDummy".
The problem is i cant seem to edit the "TargetDummy"divs since they don't have an ID and i can't give them one since there are several of them.
I am looking for a solution in javascript only. My code for creating the "TargetDummy"divs is below
var Div = document.createElement("div");
document.body.appendChild(Div).className = "TargetDummy";
I thought something like
var Dummies = document.getElementsByClassName("TargetDummy");
Dummies.className = "something";
or
Dummies.remove();
would do it, but unfortunately not. I am still learning Javascript so go easy on me :)
If you want to simply hide the Divs, you could loop through them and give them a new class via the className property.
Example JS:
var Dummies = document.getElementsByClassName("red");
function addNewClass() {
for(var i = 0; i < Dummies.length; i++) {
Dummies[i].className = "newClass";
Dummies[i--].className = "newClass"
}
}
http://codepen.io/anon/pen/OPZNJN

jQuery - text() method?

Being fairly new to jquery and javascript I can't seem to understand how the .text() method really works. I read through the jQuery documentation but still can't figure it out.
for (var i=0; i < arrayLength; i++){
var currentElement = $(".artist")[i];
var currentArtist = currentElement.text;
console.log(currentElement);
console.log(currentArtist);
}
currentArtist returns "undefined" in the console. It works fine on the $(".artist") alone, but not when I use the [i] or anything additional for that matter. What am I missing here? How else could I grab a text value inside a selector?
By using the [] operator on jQuery object you're accessing the raw element node that was found by jQuery. This raw element doesn't have the jQuery methods anymore, nor a text property.
If you want to get single element from jQuery object and keep the jQuery wrapper, use eq method.
var artistElement = $(".artist").eq(i);
artistElement.text(); // gets the text content of the element
The code you've posted is also not very optimized. For instance, with every loop iteration you're searching the document over and over again for elements with class artist. Better to cache that search result in a variable before performing the loop. And if the loop iterates over all .artist elements, you can use jQuery's each method.
$(".artist").each(function () {
var artist = $(this); // this poits to the raw element thus wrapping into jQuery object
console.log(artist.text());
});
var currentArtist = currentElement.text;
Should be:
var currentArtist = currentElement.text();
You should use a each():
$(".artist").each(function(i,val){
var currentArtist = $(val).text();
console.log(val);
console.log(currentArtist);
});
$(".artist") produce a jQuery object that could be like this:
[div, div, div, div, prevObject: jQuery.fn.jQuery.init, context: document, selector: ".artist"...]
So the result of $(".artist")[i] is a HTMLElement and do not have a text method, that's why you're getting undefined
Also text() is a function and may be followed with ()
But if you want to keep the for loop you can do
for (var i=0; i < arrayLength; i++){
var currentElement = $(".artist")[i];
var currentArtist = $(currentElement).text();
console.log(currentElement);
console.log(currentArtist);
}
.text() shows the text of an html element or set of html elements that would be visible to the user.

How to make Javascript more specific?

I am new at JavaScript so I think my problem may be simple.
This works:
var convId = document.getElementById("wrapper");
convId.setAttribute("align","right");
But when I try to make it more specific:
var convId = document.getElementById("wrapper");
var convIdDl = convId.getElementsByTagName("dl");
convIdDl.setAttribute("align","right");
my definition list doesn't align to the right.
I have checked the HTML and CSS and everything is correct, but that shouldn't even matter
JavaScript overwrites them both.
The getElementsByTagName method returns a collection (to be more specific, a NodeList). You need to specify which element of that collection you want to use (just like you would when accessing an element in an array). Here I'm assuming you want the first:
convIdDl[0].setAttribute("align", "right");
As noted in the comments, you should definitely not be using the align attribute. CSS should be used in all cases.
The getElementsByTagName() function returns a collection of DOM elements, so you'll probably want to iterate through that and set the attribute on each element individually.
for(var i = 0; i < convIdDl.length; i++) {
convIdDl[i].setAttribute("align", "right");
}

How do I write a mouse down event in JavaScript?

This is very basic I'm sure to JavaScript but I am having a hard time so any help would be appreciated.
I want to call a function within a for loop using the mouseDown event occurring within an object's second child node. The part italicized is my attempt to do this. The swapFE function is still a work in progress by the way. And one more thing is when I put the italicized part in the swapFE function everything works properly but when I put it in the for loop it doesn't all show up. I don't know why. I am basically trying to swap French phrases for English ones when I click the phrase with my mouse.
function setUpTranslation() {
var phrases = document.getElementsByTagName("p");
var swapFE = document.getElementsByTagName("phrase");
for (i = 0; i<phrases.length; i++) {
phrases[i].number = i;
phrases[i].childNodes[1].innerHTML = french[i];
*phrases[i].childNodes[1].onMouseDown = swapFE;*
}
}
/* see "function_swapFE(phrase,phrasenum);" below. The expression to call function swapFE
is located underneath "function swapFE(e)" because although the directions said to put the
"run swapFE" within the for loop it did not work properly that's why I put it beneath the
"function swapFE(e)".*/
function swapFE(e) {
var phrase = eventSource(e);
var phasenum = parseInt(1) = [1].innercontent.previousSibling;
phrase.node.previousSibling.onmousedown=swapFE
function_swapFE(e)(phrase,phrasenum);
}
}
If you have questions let me know.
Thanks for your help.
With this, you are creating a local variable named swapFE;
var swapFE =
document.getElementsByTagName("phrase");
Then with this you are setting this var as a mouseDown
phrases[i].childNodes[1].onMouseDown =
swapFE;*
That's not right... onMouseDown should be set to a function name, not a local variable of that name. So you should probably rename the local var to something else. That will at least get you closer to a solution.
I can only make a couple of guesses at what might be failing with your source code. Firstly, the following code assumes that all <p> tags have at least 2 child elements:
for (i = 0; i<phrases.length; i++) {
phrases[i].number = i;
phrases[i].childNodes[1].innerHTML = french[i];
*phrases[i].childNodes[1].onMouseDown = swapFE;*
}
If any <p> tags on your page have less than 2 child elements, an error will be thrown and script execution will halt. The best solution for this would be to add a class attribute to each <p> tag that will contain the elements you're looking for. Alternatively, you could just check for the existence of the second childnode with an if statement. Or you could do both.
Secondly, like all events, onmousedown should be declared in lowercase. Setting onMouseDown will not throw an error, but instead create a custom property on the element instead of attaching an event handler.
Finally, the following code:
var swapFE = document.getElementsByTagName("phrase");
will locally override the global function swapFE for that function, replacing it with a variable instead.
This is how I might write your setupTranslation function:
function setUpTranslation() {
var phrases = document.getElementsByTagName("p");
// rename the swapFE var as outlined below
var swapFENodes = document.getElementsByTagName("phrase");
var cNode; // set up an empty variable that we use inside the loop
for (i = 0; i<phrases.length; i++) {
/* Check for the existence of the translationPhrase class
in the <p> tag and the set the cNode var to childNodes[1]
and testing for its existence at the same time */
if (cNode.className != "translationPhrase"
|| !(cNode = phrases[i].childNodes[1]))
continue; // skip to the next iteration
phrases[i].number = i;
cNode.innerHTML = french[i];
cNode.onmousedown = swapFE; // Changed onMouseDown to onmousedown
}
}

Categories

Resources