getElementById not working in class method - javascript

HTML:
<div id='verse'>
<p id='text'>
<span id = 'reference'>random stuff here</span>
random stuff here
</p>
</div>
JS:
class Verse {
...
update() {
document.getElementById('text').innerHTML = 'text';
document.getElementById('reference').innerHTML = 'reference';
}
...
}
Whenever I call .update in an instance of Verse, the paragraph element's text changes without a problem but trying to change the span's text gives me an error: TypeError: Cannot set properties of null. Does not work with innerText either. It works fine if I change it outside of the class. Thanks for the help!

Setting innerHTML on #text replaces the contents of the <p> entirely, so when you subsequently try to access #reference it no longer exists.
The simplest way to avoid this would be to add another span and replace its text instead of the entire <p>.
<div id='verse'>
<p>
<span id='reference'>random stuff here</span>
<span id='text'>random stuff here</span>
</p>
</div>

Related

.html() not working in second id but is in first id

When you press button it calls randomQuote() function using onClick method in html. It works fine , changes the background color and the text of quotes[rand] also works. But there is no change in by id element. Also, it is not a array problem because if i type the same by statement outside the randomQuote(), it works fine.
Here is the code:
function randomQuote(){
var rand =Math.floor(Math.random()*(quotes.length));
$("#qu").html(quotes[rand]);
$("#by").html(by[rand]);
$("body").animate({backgroundColor: colorr[rand]}, 1000);
};
(Go to https://codepen.io/TheCoder21/pen/XVVxvo) for full code
The issue in your markup:
<div class="quote">
<blockquote id="qu">
Here are some of my favourite quotes.Hope you enjoy them!
<p id="by">
random text
</p>
</blockquote>
</div>
container with id="by" overwrites by this jquery method $("#qu").html(quotes[rand]);
If you want to prevent this behaviour just wrap your text in new paragraph with id="qu":
<blockquote>
<p id="by">
Here are some of my favourite quotes.Hope you enjoy them!
</p>
<p id="by">
random text
</p>
</blockquote>
The problem is that your by element belongs inside blockguote i.e id=qu element when you did $("#qu").html(quotes[rand]);
It's html structure got changes. you no longer have a by element.
Therefore, when you try to $("#by").html(by[rand]); nothing happens. Because no by element was found.
Solution: move your by element outside the blockquote
Working code: https://codepen.io/anon/pen/MrLodd
You have to separate the id in two paragraphs inside the blockquote. You can't give the blockquote and id and then expect the paragraph tag to also pick up an id inside of it. The blockquote overrides it.
<blockquote>
<p id="qu">
Here are some of my favourite quotes.Hope you enjoy them!
<p>
<p id="by">
random text
</p>
</blockquote>

Change only text (Jquery)

I have a small problem that i cannot solve.I have this : <p>Text<span></span></p> and i want to change only the text of the <p>.Which means, when i click on an change-Button, the text based on an input field should replace the text.
What i have tried is something like this : $("p").text("newText") but this will also remove the <span>.
So how can i only change the text and not the inner html...
With your HTML above you can do
$('p').contents().first()[0].textContent='newText';
The idea is to take advantage of the fact that contents() includes text-nodes. Then, access by index [0] to get the native javascript DOM element and set the textContent
$('p').contents().first()[0].textContent = 'newText';
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<p>Text<span>inside span</span>
</p>
Put another span inside of the p tag and only change its contents:
<p>
<span id="theText">Text</span>
<span></span>
</p>
And then:
$('#theText').text('newText');
$('#theText').text('newText')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
<span id="theText"></span>
<span>some other span</span>
</p>

JavaScript: transform a text between <p> tags into a new one also between <p> tags (output)

I'm trying to operate a transformation onLoad from a <p> text </p> in order to create a <p> new modified text </p> (the point is I don't wanna use textareas) in simple javascript.
Here is what I've been trying to do (but it seems to work only with values coming from textareas) :
<script>
<?php include("js/roman.js"); ?>
function afficher(form2) {
var testin = document.form2.TextToModify.value;
document.form2.NewModifiedText.value=hangul_to_roman(testin);
}
</script>
<div>
<p name="TextToModify" value="input" onLoad="afficher(form2)">
TEXT
</p>
<p name="NewModifiedText" value="output">
<!-- NEW MODIFIED TEXT -->
</p>
</div>
Does anyone know how to get the first text between the "p" tags in order to proceed to the transformation ?
Thank you in advance !
Some notes:
Better avoid inline event handlers.
p elements can't have name nor value attributes.
document.form2.TextToModify is a non standard way of accessing a form element. The standard way would be document.forms.form2.elements.TextToModify, but it won't work because p elements aren't listed elements.
function hangul_to_roman(str){ return str; }
function afficher() {
document.getElementById('NewModifiedText').innerHTML = hangul_to_roman(
document.getElementById('TextToModify').innerHTML
);
}
afficher(); // This must run after loading the DOM
<div>
<p id="TextToModify">
TEXT
</p>
<p id="NewModifiedText">
<!-- NEW MODIFIED TEXT -->
</p>
</div>
The hangul_to_roman is only included here in order to make the code snippet runnable.
Note afficher() must be called after your elements have been loaded, e.g in a script placed just before closing </body>, or in an event listener of DOMContentLoaded or load events.

Appending child node by javascript

I have dynamically generated html thru ajax when a page is loading, something like this,
Dynamically inserted,
<p class="Hello">
<span id='click lvl1'>1</span>
<span>2</span>
</p>
Now, I am trying to add another node into my <p> element. Again, dynamically thru ajax.
Server response is something like,
<p class="Hello lvl2">
<span id='click'>1</span>
<span>2</span>
</p>
Which I want to insert into the element which I have got first time.
final result,
<p class="Hello">
<span id='click'>1</span>
<span>2</span>
<p class="Hello lvl2">
<span id='click'>1</span>
<span>2</span>
</p>
</p>
While making an second ajax call I am getting reference to <span id='click lvl1'>1</span> element.
What have I tried so far?
Everthing, I could try I have tried but I am not able to inset the node. I am assuming that I am doing something really wrong. My attempts are,
pElement is <span id='click'>1</span>
pElement.parent().appendChild(data.expandTreeVal);
pElement.parent().append(data.expandTreeVal);
pElement.parent().after(data.expandTreeVal);
pElement.parentNode().appendChild(data.expandTreeVal);
Debugging
Do I really get anything from server?
Yes, When I do alert(data.expandTreeVal); it shows me my desired HTML.
any thoughts will be a great help.
You can only append DOM elements to an element, you can't append HTML code in a string.
Create an element, use the innerHTML method to put the HTML code in it, then get the first child node from it to get the p element as a DOM element.
var div = document.createElement('DIV');
div.innerHTML = data.expandTreeVal;
var p = div.childNodes[0];
Then you can add it to the document using the parentNode and appendChild methods:
pElement.parentNode.appendChild(p);
Demo: http://jsfiddle.net/AfVfE/
You may need to post a full blown use case for me to fully understand, but I think that the whole issue is that you're referencing methods that don't exist.
My use case worked fine like this:
<p class="Hello">
<span id='click'>1</span>
<span>2</span>
<p class="Hello lvl2">
<span id='click'>1</span>
<span>2</span>
</p>
</p>
With this JS:
​var pElement = document.getElementById('click');
alert(pElement.parentNode);​​​
​

Why does delegate not work in "p" tag?

When delegate with p tag, it does not work http://jsfiddle.net/peswe/wbVMV/4/
HTML:
<p id='test'>
<div>box 1
<div>box in box1</div>
</div>
</p>
​
JavaScript:
$('p#test').delegate('div','click',function(){
alert('test');
})
Changing p#test to span#test or body, it works http://jsfiddle.net/peswe/wbVMV/3/
HTML:
<span id='test'>
<div>box 1
<div>box in box1</div>
</div>
</span>
​
JavaScript:
$('span#test').delegate('div','click',function(){
alert('test');
})
Please tell me something about it.Thank you very much!
This is how browser (HTML parser) works, since <div> is a Flow element and <p> is a Phrasing element, in most case an phrasing element cannot contain any flow element, this is called misnested tags, HTML parser would fix these issues magically with some certain steps:
When reading <p>, it generates a <p> element
When reading <div>, since <div> cannot reside in a <p> element, HTML parser closes the last <p> element, then open an <div> element
When reading </div>, closes the <div> element
When reading </p>, since previous <p> element is closed, parser recogonizes it as a <p> element missing a start tag, so parser automatically inserts an <p> start tag here to create a complete <p> element
Thus, the final DOM construct is:
<p id="test"></p> <!-- auto closed -->
<div>
box1
<div>
box in box1
</div>
</div>
<p></p> <!-- auto generated -->
It's obvious that the <div> and <p> is at the same level, not forming a containing relation, so delegate fails here.
The browser is correcting your invalid HTML and moving the div outside of the p. They become siblings, hence event delegation does not work. Just inspect the elements and see for yourself:
First case:
<body>
<p id="test"></p>
<div>box 1
<div>box in box1</div>
</div>
<p></p>
</body>
Second case:
<body>
<span id="test">
<div>box 1
<div>box in box1</div>
</div>
</span>
</body>
The p tag can only contain inline elements,
While the <span> tag (as being one that handles pretty well the crossbrowser identity of an inline-block element) accepts pretty well (visually cause in the code it get messed) the div tag, although either incorrect.
It won't validate either in strict 4.01 doctype nor in HTML5.
The appropriate way would be to wrap it in a block-level element : a div.

Categories

Resources