All I'm trying to do is toggle the class of an elements by ID when they are clicked on.
<script>
function selectLoad(id)
{
if(document.getElementById(id).className == "load") {
document.getElementById(id).className = "loadSelected";
} else {
document.getElementById(id).className = "load";
}
}
</script>
<div class="load" id=" ... set by PHP per element ... " onclick="selectLoad(this)">
This returns an error...
Uncaught TypeError: Cannot read property 'className' of null
So I guess it doesn't like the conditional.
I'm new to JS and need help, thanks in advance.
You are passing the dom element itself (using this), not the id.
You should change the code to
function selectLoad(element)
{
if (element.className == "load") {
element.className = "loadSelected";
} else {
element.className = "load";
}
}
I think you are passing an id that does not exist in the dom. Has the dom loaded before your javascript is executed? Move the script to the bottom of the page just before the closing html tag
EDIT: Following discussion in comments below the error is this line:
<div class="load" id=" ... set by PHP per element ... " onclick="selectLoad(this)">
it should read
<div class="load" id=" ... set by PHP per element ... " onclick="selectLoad(this.id)">
Your code is not safe because you don't check if you have the DOM element with the given id
That is why you get the error: Cannot read property 'className' of null
if(document.getElementById(id)) {
// ... do something and do not go further.
return;
}
And the problem is passing this when you call selectLoad. At this point, this is the DOM element, not the string that yo expect: ... set by PHP per element .... So you have to change the code accordingly.
Related
I have an object of data retrieved via a GET request, which I'm then looping through and display in the DOM.
I then want to grab the ID of the <i> element, (which is a number from each element in the object), so I can then grab this ID and work with it and pass into another function, in another js file. (Eventually, I'll be using this ID for a DELETE request).
Problem is, I run getElementsByClassName on the i tag, I get the following error:
TypeError: Cannot set property 'onclick' of undefined
When my data is injected into the DOM, I can see all the HTML tags/content there in the DOM through console. However, it's almost as if the JavaScript maybe loading too quickly.
I've tried setTimeOut() function to bypass this.
Window.onload = {} and drop my function in here.
And even addEventListener.
However, the error still appears, regardless of what I try....
Any ideas?
Here is snippets of my code below:
function displayLastTask(res) {
const lastTask = (res[Object.keys(res).length-1]);
return new Promise(resolve => {
setTimeout(() => {
resolve(
individualTasks +=
`<div class="todoStyle">
<div class="text">
<p>Date: ${lastTask.date}</p>
<p>Task: ${lastTask.todo}</p>
</div>
<div class-"icon">
<i class="far fa-calendar-times deleteButton" id=${lastTask.id}></i>
</div>
</div>`
);
tasksContainer.innerHTML = individualTasks;
return tasksContainer;
}, 2000);
});
}
And here is the simple JS, I'm trying to grab the ID by:
var divs = document.getElementsByClassName('deleteButton');
for (var i = 0; i <= divs.length; i += 1) {
divs[i].onclick = function(e) {
e.preventDefault();
alert(this.id);
};
}
After the close the error in console. And copy and paste the code above into console, it works...
I cannot figure out, why any tag I try/className to grab, is returned undefined with the onclick combo, after the GET request is made and my data is posted into the DOM.
This error occurred because of getElementsByClassName('deleteButton') execution before appending deleteButton to the dom, u can use .then method after calling the displayLastTask like this:
displayLastTask(res).then(() => {
var divs = document.getElementsByClassName('deleteButton');
for (var i = 0; i <= divs.length; i += 1) {
divs[i].onclick = function(e) {
e.preventDefault();
alert(this.id);
};
}
});
Your onclick is being attached too soon. Specifically, when you call divs[i].onclick = function(e), your divs need to be in the DOM. However, it looks like they're not present when that loop runs, so the handlers are not attached.
You need to attach the onclick handlers after your GET request completes.
If there is an answer to this question out there I can not find it.
I have the following function in JavaScript and need to be able to reuse it over and over.
function ParentService_load(_Object) {
$(_Object.parent.parent).jqxDropDownButton({
...
});
$(_Object).jqxGrid({
...
});
$(_Object).bind('rowselect', function(event) {
...
var row = $(_Object).jqxGrid('getrowdata', args.rowindex);
...
$(_Object.parent.parent).jqxDropDownButton('setContent', dropDownContent);
if (row["servicename"].toString().toLowerCase() === "new") {
$(_Object.parent.parent).jqxDropDownButton('close');
...
}
});
}
<div id="jqxParentServiceDropdownButton">
<div id='jqxParentServiceDropdownWidget' style="font-size: 13px; font-family: Verdana; float: left;">
<div id="jqxParentServiceDropdownGrid" onload="ParentService_load(this);"></div>
</div>
</div>
I haven't found a definitive way to call a javascript or jquery function from an element and have that function use that elements' name, etc... So how would I accomplish this?
If by "name" you mean id, then within your function, you can access that as _Object.id. Because you're passing this in your onload=... (but see below), that's a reference to the element on which the event occurred. Within the function, you're receiving that argument as _Object, so you can use the properties on _Object to access information about the element, including its id.
But note that div elements don't have a load event. Also, div elements don't have a parent property; you may be thinking of parentNode.
I'm not completely sure what you are asking, so here are a bunch of examples about returning values embedded in the HTML from a function;
$(document).ready(function(){
$(".lw").click(function() {
alert("Class:" + $(this).attr("class") +
"\nID:" + $(this).attr("id") +
"\nData:" + $(this).data("test") +
"\nName:" + $(this).attr("name") +
"\nTagname:" + $(this).prop("tagName"));
alert($(this).parent().prop("tagName"));
});
});
http://liveweave.com/CZSYqW
Clicking on either of the <p> elements returns a different value in an alert box.
I'm trying to figure out the following.
I have following jQuery code:
var as = "";
var bPlay = 0;
audiojs.events.ready(function() {
as = audiojs.createAll();
$(".audiojs .play-pause").click(function() {
var e = $(this).parents(".audiojs").index(".audiojs");
$.each(as, function(t, n) {
if (t != e && as[t].playing) {
as[t].pause()
}
})
bPlay = !bPlay;
if (bPlay == 1) {
$(".bar").each(function(i) {
fluctuate($(this));
});
} else {
$(".bar").stop();
}
})
});
In a nutshell it preforms list of things when someone clicks particular .audiojs instance on a page. 1) checks if there is any other instance playing, if there is pauses it. And if it is playing applies fluctuate function to elements on a page that have class="bar". This is the issue! I don't want to apply it to all .bar's on a page, but only to a specific group that is associated with particular .audiojs instance (the one that is being clicked and is playing).
I thought of the following solution. Each .audiojs instance is inside a div tag that has id like "post-1", "post-2" etc.. where numerical value is post id from database. I can add this numerical id to bar, so it would be like bar-1, bar-2 etc... However after this I'm having issues.
For javascript to work I need to retrieve numerical value from "post-[id]" associated with audiojs instance that is being clicked and than store it somehow, so I can use it like this afterwards
bPlay = !bPlay;
if (bPlay == 1) {
$(".bar-[value retrieved from post-...]").each(function(i) {
fluctuate($(this));
});
} else {
$(".bar-[value retrieved from post...]").stop();
}
Could someone explain to me how it can be achieved?
Honestly, the easiest way would be to stick it in a custom data-* attribute on the <div id="post-X"> element, like so:
<div id="post-1" data-bar="bar-1">...</div>
Then, you said your .audiojs element is inside that <div>, so just go from this inside the event handler to that <div> element (using .closest()) and get the value of it:
var barId = $(this).closest('[id^="post-"]').attr('data-bar');
Then when you need to use it:
$("." + barId).each(function(i) {
fluctuate($(this));
});
Instead of embedding the value in a class or ID, use a data-* attribute:
<div class="audiojs" data-fluctuate-target="bar-1">
<button type="button" class="play-pause">
<!-- ... -->
</button>
</div>
<div class="bar-1">
<!-- ... -->
</div>
In your click event handler, use the following to fluctuate or stop the correct elements:
var fluctuateClass = $(this).closest('.audiojs').attr('data-fluctuate-target');
$('.' + fluctuateClass).each(function () {
if (bPlay == 1) {
fluctuate($(this));
} else {
$(this).stop();
}
});
I have some JQuery code that converts all HTML elements of a specific class to & from textarea elements.
My Problem: I use JQuery(.addClass()) to change an elements class from "updatable" to "updatable P". But when I go to search for all the elements that have the class "updatable" (using the function $(".updatable").each()) it does'nt find any elements when it should find 3.
What am I doing wrong to make this happen? It seems that after I change an elements classI am unable to identify/find that element by its class(using JQuery) again.
<html>
<head>
<script type="text/javascript" src="jquery-1.6.4.js"></script>
<script type="text/javascript">
<!--
var STATE = 1;
function Toggle()
{
if (STATE==1) { convertToUpdatable(); STATE = 0; }
else { convertToStatic(); STATE = 1; }
}
function getTitleName( ele )
{
try { return ele.className.split(" ")[1]; }
catch (ex) { return "undefined"; }
}
function convertToUpdatable()
{
// Post: Convert all HTML elements (with the class 'updatable') to textarea HTML elements
// and store their HTML element type in the class attribute
// EG: Before: <p class="updatable Paragraph1"/> Hello this is some text 1 </p>
// After : <p class='updatableElementTitle'>Paragraph1</p><textarea class="updatable Paragraph1 p"/> Hello this is some text 1 </textarea>
$(".updatable").each(function()
{
var title = getTitleName( this );
$(this).replaceWith("<p class='updatableElementTitle'>"+title+"</p><textarea>"+$(this).text() +"</textarea>");
$(this).addClass( this.nodeName );
alert( this.className );
});
}
function convertToStatic()
{
// Post: Find all HTML elements (with the class 'updatable'), check to see if they are part of another class aswell
// (which will be their original HTML element type) & convert the element back to that original HTML element type
// PROBLEM OCCURS HERE: after I have changed an elements className in the convertToUpdatable() I can no
// longer find any HTML elements that have the className updatable using $(".updatable").each()
$(".updatable").each(function()
{
alert("Loop");
// Determine elements original HTML(node) type
try
{
var type = this.className.split(" ");
type = (type[ type.length-1 ]).toLowerCase();
alert(type);
}
catch (ex) { alert("Updatable element had no type defined in class attribute"); return; }
// Convert element back to original HTML type
$(this).replaceWith( type +$(this).text() + type );
// Remove elements type from its className (remove " P" from "updatable Paragraph1 P")
$(this).removeClass( type );
alert( this.className );
});
// Delete all elements with the class 'updatableElementTitle'
$(".updatableElementTitle").remove();
}
-->
</script>
</head>
<body>
<p class="updatable Paragraph1"/> Hello this is some text 1 </p>
<b class="updatable Paragraph2"/> Hello this is some text 2 </b>
<i class="updatable Paragraph3"/> Hello this is some text 3 </i>
<input id="MyButton" type="button" value="Click me!" onclick="Toggle();" />
</body>
</html>
.replaceWith() destroys the existing element. Thus, you can no longer use this after you've done the replaceWith() in the loop because that DOM element is no longer the element that's in your document (it's the old one that has been removed and will be garbage collected as soon as your function exits).
Since you're specifying the HTML for the new tag, I would suggest you just put the new class name in the HTML you pass to replaceWith(). Further, the alert you have to check the className is checking the old DOM element, not the new DOM element. Remember, this points to the old DOM name, not the one you replaced it with.
You could do so by changing this:
$(".updatable").each(function()
{
var title = getTitleName( this );
$(this).replaceWith("<p class='updatableElementTitle'>"+title+"</p><textarea>"+$(this).text() +"</textarea>");
$(this).addClass( this.nodeName );
alert( this.className );
});
}
to this:
$(".updatable").each(function()
{
var title = getTitleName( this );
$(this).replaceWith("<p class='updatableElementTitle " + this.nodeName + "'>" + title + "</p><textarea>"+$(this).text() +"</textarea>");
});
}
Although, I don't understand why you're adding the nodeName as a class?
You are using replaceWith which (according to the spec) completely removes all content and replaces it with the new content. After you've replaced the content there are no more nodes with the updatable class, so you won't ever find them again.
Try replacing $(this).addClass( this.nodeName ); with $(this).addClass('updatable');.
I am quite new with Javascript and I got a problem with document.getElementById() that always returns NULL, and that's driving me nuts.
I have a element in my code and I want to get its coordinates so I can move it.
Here is the code:
<html>
<head>
<script type="text/javascript" >
function MoveIt(obj) {
alert(obj); // returns "Object HTMLDivElement"
var xx = document.getElementById("arect");
if(document.getElementById("arect").value == null) {
alert('NULL >> ' + xx.value);
}
else {
alert('NOT NULL >>' + xx.value);
}
posX = xx.style.scrollTop;
posY = xx.style.left;
}
</script>
</head>
<body bgcolor="white" >
<DIV class="background" id="MyDiv2">
<div id="arect" name="arect" class="transbox" onmousedown="MoveIt(this);" >
</div>
</div>
</body>
</html>
The above function MoveIt() always returns NULL
The page contents need to be loaded before trying to read them. Try
window.onload = function() {
// run your script in here
}
Or if you're using jQuery, prefer
$(document).ready(function() {
...
}
You never checked getElementById(...) for NULL.
You checked getElementById(...).value for NULL, and divs don't have a "value".
Also note that you forgot to close that <div /> tag, which is illegal in your XHTML... and used an SVG doctype for some reason. SVG is not HTML.
It's not really clear what you're trying to do here.
The "arect" element is a <div>, and <div> elements don't have a "value".
Get rid of that bogus SVG doctype too.
if(document.getElementById("arect").value == null){
alert('NULL >> '+ xx.value);
}
This code always returns null or error. If you want to see if the object exists, do the following....
if(xx == null)
alert('Object does not exist');
else
alert('Object exists. Inner HTML: ' + xx.innerHTML);
Also, div does not have value. If you want to get the html inside div, use xx.innerHTML
if the button is set to visisble= false then you cannot get the id of that button on client side. To hide the button use
button1.Style.Add("display","none")-- for visible false
and
button1.Style.Add("display","block")-- for visible true
and even if button is enabled false we cannot get the Id of the button on client side
You can get the id of the button by document.getElementById('<%= button1.ClientID %>');
Or
if you set the ClientIDMode="Static" for the control in aspx page you can get it directly by document.getElementById('button1');
Or
document.getElementById('MainContent_button1');--- MainContent here is the Id of the contentplaceholder if you have the id of the contenet placeholder different use that id_button1.
in my case it was because of having this line at the beginning of the jsp/html(whatever) file:
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
removing it solved my problem.