Get DOM Element with jQuery - javascript

I have a web page that is structured like this:
<canvas id="myCanvas"></canvas>
#for(var i=0; i<10; i++) {
<div class="my-element">
<canvas></canvas>
</div>
}
This code generates one main canvas. Below it, 10 other dynamically generated divs are being generated. In reality, this loop is just used to show that I have some code being dynamically generated. The main thing to understand is the my-element piece.
In my javascript, I have the following:
$(function() {
var mainCanvas = document.getElementById('myCanvas');
initializeCanvas(mainCanvas); // This works.
var dynamicElements = $('.my-element');
for (var i=0; i<dynamicElements.length; i++) {
initializeCanvas($(dynamicElements[i])[0]); // This does not work
}
});
function initializeCanvas(canvas) {
// do stuff
}
The first call to initializeCanvas works because I'm passing in an actual HTML Dom element. But the second initializeCanvas, which is called multiple times, fails because it's passing in something else. How do I get the same type of element as what's returned by document.getElementById in this case?
Thanks!

First of all, this doesn't make sense:
$(dynamicElements[i])[0]
You are getting jQuery element, unwrapping it, then wrapping again in jQuery...
what you simply need to do is get canvas from the element
dynamicElements.eq(i).find('canvas')[0] should do the job

You can't use the same element for this purpose. I suggest you to clone it. Like;
var dynamicElements = $('.my-element').clone();
Also when you add more element with my-element class this will be messy. You should make sure to select only one element with $('.my-element') selection.

Related

Appending child nodes on a div

Im trying to add items into a div element based on elements from an array.
The element I'm trying to add already exists on the page. Basically I'm trying to just create a new version of it and add it to the div.
The code might help explain things further.
JavaScript:
function apply(list) {
var item = $("#it_template").children("md-list-item").eq(0);
for(var i = 0; i < list.uuids.length; i++){
var uid = list.uuids[i];
item.children("p").eq(0).html(uid);
$("#items").append(item);
}
}
HTML:
<div id="items">
</div>
<div style="display:none" id="it_template">
<md-list-item md-ink-ripple class="list_item">
<p></p>
</md-list-item>
</div>
It seems to be faulty somewhere, since whenever I'm running the code I'm only seeing one item being added to the div.
Can you please help me out with where the error is?
Try this? The important change is cloning the node instead of trying to append it over and over. (A node can only have one parent, so it will just get moved instead of copied.)
Another change I made was to use .text instead of .html. If you're dealing with text, this is generally much better. (Importantly, it reduces your risk of XSS vulnerabilities.)
function apply(list) {
var item = $("#it_template").children("md-list-item").eq(0);
for(var i = 0; i < list.uuids.length; i++) {
var uid = list.uuids[i];
var newItem = item.clone();
newItem.children("p").eq(0).text(uid);
$("#items").append(newItem);
}
}
Unless you are Using Angular Material, <md-list-item> is an invalid tag.
Sorry, i am not sure what you are attempting to do but if you want to fill something with a collection of somethings and you want to use Angular. Check out NG-REPEAT directive.

Creating a div within an existing div in javascript issues

I have a problem, I wanted to create a div in html as a container and in javascript create new divs within the container based on a number input from a user prompt.
My html and javascript look like this.
HTML:
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="stylesheet.css">
<title>Sketchpad</title>
</head>
<body>
<button type="button">Reset</button>
<div class= "container">
</div>
<script src="javascript.js"></script>
<script src="jQuery.js"></script>
</body>
JS
var row = prompt("Enter number of rows:");
var column = prompt("Enter number of columns:");
function createGrid(){
var cont = document.getElementsByClassName('container');
for(i=1; i<column; i++){
var sketchSquare = document.createElement('div');
cont.appendChild(sketchSquare);
}
}
createGrid(column);
I end up with this error: Uncaught TypeError: cont.appendChild is not a function.
I imagine this is something to do with the getElementsByClassName?
I do have a solution which involves creating the container div in javascript and appending the smaller squares inside the container div. I was just curious as to why my first soltuion didn't work?
cont[0].appendChild(myDiv) is a function.
When you document.getElements By Class Name as the name implies you are getting many elements (an array of sorts) of elements and this array don't have the same functions as each of its elements.
Like this:
var thinkers = [
{think: function(){console.log('thinking');}
];
thinkers don't have the method .think
but thinkers[0].think() will work.
try this: open your javascript console by right clicking and doing inspect element:
then type:
var blah = document.getElementsByClassName('show-votes');
blah[0].appendChild(document.createElement('div'));
It works!
also if you want to use jQuery which I do see you added...
you can do:
var cont = $('container');
cont.append('<div class="sketchSquare"></div>');
Try that out by doing this:
First get an environment that has jQuery.
Hmm maybe the jQuery docs have jQuery loaded!
They do: http://api.jquery.com/append/.
Open the console there and at the bottom where the console cursor is type:
$('.signature').append('<div style="background: pink; width: 300px; height: 300px"></div>');
You'll notice that you add pink boxes of about 300px^2 to 2 boxes each of which have the "signature" class.
By the way, prompt gives you a string so you'll have to do row = Number(row); or row = parseInt(row, 10); and another thing don't use that global i do for(var i = 0; ...
var cont = document.getElementsByClassName('container');
Because that^ doesn't return a node, it'll return an HTMLCollection.
https://www.w3.org/TR/2011/WD-html5-author-20110705/common-dom-interfaces.html#htmlcollection-0
You need to pick an individual node from that collection before appending.
There could be a couple of issues that could cause this. Without fully giving the answer here's what it could be at a high level.
Your script is ran before the DOM is fully loaded. Make sure that your script is ran after the DOM is present in the page. This can be accomplished using either the DOMReady event ($(document).ready equivalent without jQuery) or simply making sure your script tag is the last element before the closing body tag. (I usually prefer the former)
When you utilize document.getElementsByClassName('container') (https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName) this method returns an array therefore you would either need to apply the operation to all elements of the result or just select the zero-th as document.getElementsByClassName('container')[0]. As an alternative, if you would like to be more explicit you could also place an id on the container element instead to more explicitly state which element you would like to retrieve. Then, you would simply use document.getElementById([id]) (https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById) and this would get back a single element not a collection.
The result of prompt is a string. Therefore you would have to first parse it as an integer with parseInt(result, 10) where 10 is simply the radix or more simply you want a number that is from 0-10.
You should include jquery library before your script, it`s important
<script src="jQuery.js"></script>
<script src="javascript.js"></script>

JavaScript removeChild not working

I am using this JavaScript code to remove a couple elements from the page, but it's not working. When I inspect the code with Opera Dragonfly it says something like:
Uncaught exception: Error: WRONG_ARGUMENTS_ERR
and points to the file and function name.
The weird thing is that I use the exact same code in another function on the same page and it works without problem. The code is very small and simple:
var docBody = document.getElementById("body");
if(document.getElementById("marginDiv")){
docBody.removeChild("marginDiv");
}
Both body and marginDiv exist on the page. My goal is to make the thumbnails disappear when one clicks the background.
You're trying to remove a string. A string is hardly an HTML element. You're also relying on marginDiv being a direct child of body, which may not be the case.
Instead, try this:
var remove = document.getElementById('marginDiv');
if( remove) remove.parentNode.removeChild(remove);
Try
docBody.removeChild(document.getElementById("marginDiv"));
removeChild needs a reference to a DOM element, not a string. Try this:
var docBody = document.getElementById("body");
var marginDiv = document.getElementById("marginDiv");
if(marginDiv)){
docBody.removeChild(marginDiv);
}
if(document.getElementById("marginDiv")){
docBody.removeChild("marginDiv");
}
you have to check if specified element exist marginDiv exist, then removechild(...)

Get all html between two elements

Problem:
Extract all html between two headers including the headers html. The header text is known, but not the formatting, tag name, etc. They are not within the same parent and might (well, almost for sure) have sub children within it's own children).
To clarify: headers could be inside a <h1> or <div> or any other tag. They may also be surrounded by <b>, <i>, <font> or more <div> tags. The key is: the only text within the element is the header text.
The tools I have available are: C# 3.0 utilizing a WebBrowser control, or Jquery/Js.
I've taken the Jquery route, traversing the DOM, but I've ran into the issue of children and adding them appropriately. Here is the code so far:
function getAllBetween(firstEl,lastEl) {
var collection = new Array(); // Collection of Elements
var fefound =false;
$('body').find('*').each(function(){
var curEl = $(this);
if($(curEl).text() == firstEl)
fefound=true;
if($(curEl).text() == lastEl)
return false;
// need something to add children children
// otherwise we get <table></table><tbody></tbody><tr></tr> etc
if (fefound)
collection.push(curEl);
});
var div = document.createElement("DIV");
for (var i=0,len=collection.length;i<len;i++){
$(div).append(collection[i]);
}
return($(div).html());
}
Should I be continueing down this road? With some sort of recursive function checking/handling children, or would a whole new approach be better suited?
For the sake of testing, here is some sample markup:
<body>
<div>
<div>Start</div>
<table><tbody><tr><td>Oops</td></tr></tbody></table>
</div>
<div>
<div>End</div>
</div>
</body>
Any suggestions or thoughts are greatly appreciated!
My thought is a regex, something along the lines of
.*<(?<tag>.+)>Start</\1>(?<found_data>.+)<\1>End</\1>.*
should get you everything between the Start and end div tags.
Here's an idea:
$(function() {
// Get the parent div start is in:
var $elie = $("div:contains(Start)").eq(0), htmlArr = [];
// Push HTML of that div to the HTML array
htmlArr.push($('<div>').append( $elie.clone() ).html());
// Keep moving along and adding to array until we hit END
while($elie.find("div:contains(End)").length != 1) {
$elie = $elie.next();
htmlArr.push($('<div>').append( $elie.clone() ).html());
};
// htmlArr now has the HTML
// let's see what it is:
alert(htmlArr.join(""));
});​
Try it out with this jsFiddle example
This takes the entire parent div that start is in. I'm not sure that's what you want though. The outerHTML is done by $('<div>').append( element.clone() ).html(), since outerHTML support is not cross browser yet. All the html is stored in an array, you could also just store the elements in the array.

How can I apply a function to several images in jQuery?

I need a little help with (probably) something really simple.
I want to use a script which converts images from color to grayscale.
I got it working partially — the first image turns gray, but the second won’t.
I know this is because an id cannot be used multiple times:
var imgObj = document.getElementById('grayimage');
I tried this:
var imgObj = $(’.grayimage’)[0];
But it didn’t work. Changing it to getElementByClass also does not work. (Before people ask, I did change the id to class in the <img> tag.)
I really could use some help here. Thanks in advance!
$('.grayimage').each(function(idx,imgObj){
<do your code here>
});
$('.grayimage') gives you a list of all elements with grayimage as a class. If you add '[0]' you're accessing the first element, so any changes you make will apply to only the first image that it finds with this class.
You should loop through all elements:
var images = $('.grayimage');
for(i = 0; i < images.length; i++) {
var image = images[i];
// Do stuff
}

Categories