Javascript tutorial, 'childNodes' solution doesn't work - javascript

Am doing a (highly recommended) Javascript tutorial (http://www.newthinktank.com/2015/09/learn-javascript-one-video/) and one of the solutions doesn't work. I'm trying to change the background colour of the first paragraph, I don't get any errors and 'developer tools' shows me that the 'style' just doesn't updated. I even copied the code from the cheat-sheet and it still doesn't work. Not sure it's a version problem or just a genuine mistake (it's been viewed over 1,000,000 times so I'm sure someone would have picked up on it by now). Here's the code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel='stylesheet' href='style.css'>
</head>
<body>
<div id="sampDiv">
<p>Lorem ipsum dolor sit amet, <em>consectetur adipiscing</em> elit. Integer feugiat in tortor at scelerisque. Aenean nulla dui, auctor sit amet dignissim et, ultrices non odio. Pellentesque luctus eu ligula id feugiat. Mauris tempus mollis est, eget elementum massa luctus eu.</p>
<p> Sed ac ipsum libero. <b>Donec et leo</b> sit amet ante posuere pretium at eu massa. Donec tincidunt <em>elementum risus</em>, nec scelerisque massa luctus vitae. Praesent blandit tincidunt orci, <b>at commodo eros</b> interdum eu.</p>
</div>
<script>
// first paragraph
var sampDiv = document.getElementById('sampDiv');
sampDiv.childNodes[0].style.backgroundColor = "#F0FFFF";
</script>
</body>
</html>
I know there are many ways to achieve this, such as:
var pElements = document.getElementsByTagName('p');
pElements[0].style.backgroundColor = "#F0FFFF";
...but I'm interested to know what is wrong. To clarify, this is the code that isn't working:
var sampDiv = document.getElementById('sampDiv');
sampDiv.childNodes[0].style.backgroundColor = "#F0FFFF";
I'm running Chrome Version 68.0.3440.106 (Official Build) (64-bit)

The problem is that the first child node is a Text node (containing the whitespace after <div id="sampDiv"> and before <p>), not an element:
var sampDiv = document.getElementById('sampDiv');
console.log(sampDiv.childNodes[0].nodeName);
<div id="sampDiv">
<p>Lorem ipsum dolor sit amet, <em>consectetur adipiscing</em> elit. Integer feugiat in tortor at scelerisque. Aenean nulla dui, auctor sit amet dignissim et, ultrices non odio. Pellentesque luctus eu ligula id feugiat. Mauris tempus mollis est, eget elementum massa luctus eu.</p>
<p>Sed ac ipsum libero. <b>Donec et leo</b> sit amet ante posuere pretium at eu massa. Donec tincidunt <em>elementum risus</em>, nec scelerisque massa luctus vitae. Praesent blandit tincidunt orci, <b>at commodo eros</b> interdum eu.</p>
</div>
The author should have used children, which only contains elements, instead of childNodes, which includes all types of nodes:
var sampDiv = document.getElementById('sampDiv');
sampDiv.children[0].style.backgroundColor = "#F0FFFF";
<div id="sampDiv">
<p>Lorem ipsum dolor sit amet, <em>consectetur adipiscing</em> elit. Integer feugiat in tortor at scelerisque. Aenean nulla dui, auctor sit amet dignissim et, ultrices non odio. Pellentesque luctus eu ligula id feugiat. Mauris tempus mollis est, eget elementum massa luctus eu.</p>
<p>Sed ac ipsum libero. <b>Donec et leo</b> sit amet ante posuere pretium at eu massa. Donec tincidunt <em>elementum risus</em>, nec scelerisque massa luctus vitae. Praesent blandit tincidunt orci, <b>at commodo eros</b> interdum eu.</p>
</div>
Although one could argue that firstElementChild would be better than children[0].
It may be that the author didn't have that whitespace and you introduced it with formatting, or the author normally runs his/her HTML through a compressor which would probably have removed it, etc., because the code works if that whitespace isn't there:
var sampDiv = document.getElementById('sampDiv');
sampDiv.childNodes[0].style.backgroundColor = "#F0FFFF";
<div id="sampDiv"><p>Lorem ipsum dolor sit amet, <em>consectetur adipiscing</em> elit. Integer feugiat in tortor at scelerisque. Aenean nulla dui, auctor sit amet dignissim et, ultrices non odio. Pellentesque luctus eu ligula id feugiat. Mauris tempus mollis est, eget elementum massa luctus eu.</p>
<p>Sed ac ipsum libero. <b>Donec et leo</b> sit amet ante posuere pretium at eu massa. Donec tincidunt <em>elementum risus</em>, nec scelerisque massa luctus vitae. Praesent blandit tincidunt orci, <b>at commodo eros</b> interdum eu.</p>
</div>

sampDiv.childNodes[1].style.backgroundColor = "#F0FFFF";
not childNodes[0], but childNodes[1].

Related

JavaScript - Readmore.js - Method is not a function

I am attempting to implement readmore.js into my code but I am continuously running into readmore.js is not a function error. I've read over the documentation multiple times and I am unable to figure out what I am doing wrong. When implemented correctly should include a "READ MORE" button to expand the text in its entirety.
I've included the HTML script tag that is presented in the github
I've made sure I included a jquery cdn before the readmore.js
I've included a class name of article
I've attempted to wrap the .readmore in a function such as :
$(function () { $('.article').readmore({speed: 75, lessLink: 'Read less'});});
Here is a snippet of code that I am working with:
const data = [{ paragraph: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis id aliquam nibh. Aenean a porttitor ipsum. Vestibulum ut sagittis dui, nec pharetra eros. Vivamus tempus fringilla dictum. Maecenas facilisis auctor magna, a accumsan nunc molestie dictum. In tempus rhoncus condimentum. Aenean interdum leo et velit pellentesque dapibus. Vivamus nunc orci, commodo sit amet dui a, lobortis finibus arcu. Maecenas metus mauris, tincidunt sit amet ex id, gravida commodo nunc. Donec consequat tristique lacinia. Pellentesque commodo eu tortor sit amet rutrum. Vivamus mollis eros ipsum, in vestibulum lorem tempor sit amet. Morbi egestas orci sem, posuere rutrum augue malesuada eget. Mauris ultricies egestas luctus. Praesent at dignissim nunc. Aliquam erat volutpat."},{
paragraph: "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam porttitor tincidunt fringilla. In ullamcorper vitae sapien eget ornare. Nulla quis lacus condimentum lacus tincidunt consectetur ut in ante. Suspendisse a eleifend est. Pellentesque eu ornare magna. Vestibulum ac mi sit amet arcu tristique volutpat in id nisl. Aenean interdum et odio gravida hendrerit. Pellentesque at diam lacus. Mauris elementum ultricies imperdiet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus metus ligula, molestie at laoreet id, convallis et felis. Nullam molestie, augue vel interdum semper, dui massa feugiat risus, non sodales est massa non arcu. Vivamus ut sodales metus."
}
]
let htmlOutput = ""
for (let i = 0; i < data.length; i++) {
htmlOutput += "<div>" + data[i].paragraph + "</div>"
}
$("#report").html(htmlOutput)
$('.article').readmore({
speed: 75,
lessLink: 'Read less'
});
<div id="report" class="article">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="/node_modules/readmore-js/readmore.min.js"></script>
My expected outcome is to be able to include the .readmore function and have a "read more" that will expand the text once clicked.
You will have to download the readmore.min.js file from the repo. The file is located here.
https://github.com/jedfoster/Readmore.js/blob/master/readmore.min.js
Then you can include it in your project by putting it in the same directory as your index.html file and add a script tag like this
<script src="readmore.min.js"></script>
hi this might have been solved but ill add my 2c.
from your code it seem that you are adding the text inside a nested div instead of the parent div with the article class.
try adding "id='report' class= 'article' " inside the for loop div and check if the plugin works

Use Trianglify for site background?

I am trying to set my site background with Trianglify. The site I am trying to use it with is here. It doesn't have any scrolling. None of the examples work for me (they all place the generated image below the rest of the content, not as the background). I also tried the suggestion in issue #58 but that didn't work at all. Any help would be much appreciated. Thanks.
You could just change the position of your element that contains the background with CSS. I hope this answer to you question.
canvas {
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
<h1>Title</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam vitae purus quis dolor lacinia gravida. Ut sit amet purus vel tellus faucibus posuere. Pellentesque ut sapien quis elit luctus tincidunt. Etiam eros nisl, semper sit amet malesuada et, aliquet id arcu. Quisque leo ipsum, ullamcorper nec urna ac, maximus finibus tortor. Curabitur non justo condimentum, consectetur diam sed, lobortis lorem. Nulla scelerisque hendrerit nunc, eu aliquam est pretium vel. Maecenas risus mi, ultrices eget mollis sed, consectetur id eros. Donec ac mauris mattis, tincidunt lacus sit amet, congue lacus. Vivamus sed nulla sit amet dolor porttitor dictum. Cras quis mi massa. Quisque lobortis consequat ante sit amet blandit. In dictum iaculis elementum. Maecenas quis congue eros. Phasellus aliquam, libero ut fermentum accumsan, quam sem egestas elit, vel posuere purus dui id mauris. Praesent vel risus ac felis dapibus finibus in nec enim.</p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/trianglify/1.1.0/trianglify.min.js"></script>
<script>
var pattern = Trianglify({
width: window.innerWidth,
height: window.innerHeight,
cell_size: 30 + Math.random() * 100,
x_colors: 'random',
y_colors: 'match_x',
stroke_width: 3
});
document.body.appendChild(pattern.canvas())
</script>
edit: First expand snippet, then run code.
edit2: Forgot left: 0.

onmouseout event failed to fire and change value

I have a hover element in which when user hover over it will get text from a hidden element and when it hovers out it will reassign in its previous value.
My html is sort of like this.
<div id="product-name">Hover Here</div>
<br>
<div id="result-content">Lorem ipsum dolor sit amet.</div>
<div class="hidden">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla pellentesque mi leo, ut cursus tellus tempor nec. Sed facilisis augue neque, a ornare urna ornare in. Etiam consequat, dui sit amet pretium bibendum, ante ipsum ullamcorper libero, vel tempus erat urna sed purus. Quisque id ultricies elit, non posuere nunc. Etiam pulvinar magna tortor, at aliquet turpis interdum et. Duis imperdiet enim ante, sit amet pretium enim aliquet venenatis. Donec ac nibh nibh. Interdum et malesuada fames ac ante ipsum primis in faucibus. Morbi aliquam est adipiscing volutpat pulvinar. Curabitur leo augue, iaculis id lacus sed, dictum vestibulum nulla. Etiam sit amet tempus felis, ac aliquet erat. Nunc ullamcorper consequat mattis. In molestie, tortor ac venenatis dapibus, eros neque vulputate nulla, in tristique ante diam non turpis. Maecenas mattis in risus eu ornare. Cras a rutrum nulla. Proin sagittis justo vehicula augue porttitor vulputate.
</div>
and javascript is this:
var object = document.getElementById("product-name");
object.onmouseover=function(){
document.getElementById("result-content").innerHTML = document.getElementsByClassName("hidden")[0].innerHTML;
};
object.onmouseout=function(){
document.getElementById("result-content")[0].innerHTML = document.getElementById("result-content").innerHTML;
};
jsfiddle.net
But my mouseout event failed me here. Can anyone help me out here how can i resolve this. I can't use jQuery in this dom only javascript, but I wouldn't mind if anybody show me a better approach to resolve javascript mouseout/mouseover paradigm.
Fiddle Demo
You need to store initial contents of the block.
var object = document.getElementById("product-name");
var currentHtml = document.getElementById("result-content").innerHTML;
object.onmouseover=function(){
document.getElementById("result-content").innerHTML = document.getElementsByClassName("hidden")[0].innerHTML;
this.onmouseout=function(){
document.getElementById("result-content").innerHTML = currentHtml;
}
};
document.getElementById("result-content")[0].innerHTML = document.getElementById("result-content").innerHTML; will take you nowhere. You have to preserve the value somewhere.
If you fancy a bit different approach then try this.
document.querySelector("#product-name").addEventListener("mouseover", function(){
var txt = document.querySelector("#result-content").innerHTML;
document.querySelector("#result-content").innerHTML = document.querySelector(".hidden").innerHTML;
this.addEventListener("mouseout", function(){
document.querySelector("#result-content").innerHTML = txt;
});
});
jsfiddle Demo
document.querySelector is supported in most browser.
http://caniuse.com/queryselector
I think, in this case must save somewhere previous state, like:
var object = document.getElementById("product-name"),
previous_state = document.getElementById("result-content").innerHTML;
Might not be the best approach, but without major changes in code should look like this:
jsfiddle
try this one for mouse out
object.onmouseout=function(){
document.getElementById("result-content").innerHTML ='Lorem ipsum dolor sit amet.';
};

jQuery returns XML node fine the first time, but the second time i call it, its empty

I have this XML in an externally loaded file via AJAX and jQuery:
<project>
<title>Title Name 2</title>
<tags>Tag1.Tag2</tags>
<image src="img/portfolio/better/better01.jpg" title="Image title" tags="Tag1.Tag2"></image>
<image src="img/portfolio/better/better02.jpg" title="Image title" tags="Tag1.Tag2"></image>
<thumb src="img/portfolio/better/better01.jpg" title="Image title" tags="Tag1.Tag2"></thumb>
<copy>
<columnOne>
<p>Lorem ipsum dolor sit amet, cons ectetur adipiscing elit. Nulla lobortis accumsan purus. Nulla at arcu est. Mauris iaculis ses tincidunt odio cursus accumsan. Morbi quis interdumes massa. Nulla eu ipsum nunc, necs gravida metus. Pelle ntesque utes ligula est nec ullamcorper nulla.</p>
<p>Cras id hendrerit velit. Suspendisse arscibus libero. Pellentesqueses habitant morbi trtique senctus et netus etsuada fames ac turpis egestas. Aliquam sagittise euismod velit, quis pharetra lacus ibulum mollis saewesty.</p>
</columnOne>
<columnTwo>
<p>Morbi quis inteumes massa. Nulla eu ipsum nunc, necs gravida metus. Pelle ntesqueessy ligula est nec ullamcorper nulla</p>
</columnTwo>
</copy>
</project>
There are several nodes within the XML document. I have pushed all the nodes into an array called 'project_array'. When i do :
console.log(project_array[0].text());
I get:
Title Name 2
Tag1.Tag2
Lorem ipsum dolor sit amet, cons ectetur adipiscing elit. Nulla lobortis accumsan purus. Nulla at arcu est. Mauris iaculis ses tincidunt odio cursus accumsan. Morbi quis interdumes massa. Nulla eu ipsum nunc, necs gravida metus. Pelle ntesque utes ligula est nec ullamcorper nulla.
Cras id hendrerit velit. Suspendisse arscibus libero. Pellentesqueses habitant morbi trtique senctus et netus etsuada fames ac turpis egestas. Aliquam sagittise euismod velit, quis pharetra lacus ibulum mollis saewesty.
Morbi quis inteumes massa. Nulla eu ipsum nunc, necs gravida metus. Pelle ntesqueessy ligula est nec ullamcorper nulla
Which is what I expect, the entire contents of the nodes within 'project'. The second time I call it I get just the 'title' and 'tags' node, and the 'columnOne' and 'columnTwo' nodes are empty.
Head banging scenario. Any help very much appreciated.
Depending on how you populated project_array, calling project_array[0].text() might actually be removing the text content, though I'm not sure why <title> and <tags> would come through the next time.
Try using $(project_array[0]).clone().text(), storing it in a variable, and using that variable for repeat references instead.
.text() is a method to be used on jQuery Object
If project_array its a array of nodes why are using project_array[0].text()
Looks like it should be
console.log($(project_array[0]).text())

Multiline Text Truncating

Does anyone know of a clean and easy way to truncate a section of text to two lines. This is what I am trying to truncate (p element):
<blockquote><p>“<?=$test_entry ?>”</p></blockquote><cite><?=$test_name ?></cite>
I have tried various solutions including clamp.js (which doesnt even work properly in the example supplied)
I have tried CSS3 solutions using text-overflow but these only truncate to one line.
All other javascript examples use string length which breaks if the text size changes, if special chars are encoded and under many other conditions.
I am happy to change the markup if necessary I just want to be able to truncate text to fit two lines within a div box and have it end with an elipses (...) or even better with (..."). I thought this would be straightforward but apparantly not.
Can anyone point me to an existing solution or give me a clue where to start with this. Any help much appreciated.
Here you can find an existing solution based on jQuery, which should be working cross browser, in this SO question.
This is a very simple solution to truncate the multiline paragraph and this will also add the ellipsis dots at the end of the last line.
p.truncate_text {
color:red;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce quis justo nibh. Phasellus ac ante enim. Mauris ullamcorper mauris nec laoreet lacinia. Sed interdum tincidunt tempor. Cras euismod, tellus id consequat varius, est lectus sagittis justo, sit amet egestas sem dolor sit amet arcu. In commodo nibh ac nisi tincidunt tincidunt. Nullam suscipit, mi nec posuere imperdiet, odio est pellentesque arcu, at varius massa ex nec urna.</p>
<p class="truncate_text">This paragraph will truncate into 3 lines Quisque ut purus nunc. Aenean vitae lectus maximus, fermentum justo quis, lobortis neque. Curabitur lacinia in massa in efficitur. Praesent et dolor et ex sodales volutpat vel lobortis ligula. Maecenas convallis luctus tempus. Vivamus non libero nisi. Donec facilisis, odio sed dictum consectetur, eros dolor pellentesque quam, ut ornare est ligula eu ligula. Etiam elementum nibh lectus, quis sodales massa malesuada vitae. Etiam finibus quam eget condimentum rutrum. Donec et velit ipsum. </p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce quis justo nibh. Phasellus ac ante enim. Mauris ullamcorper mauris nec laoreet lacinia. Sed interdum tincidunt tempor. Cras euismod, tellus id consequat varius, est lectus sagittis justo, sit amet egestas sem dolor sit amet arcu. In commodo nibh ac nisi tincidunt tincidunt. Nullam suscipit, mi nec posuere imperdiet, odio est pellentesque arcu, at varius massa ex nec urna.</p>
Use the textarea element to limit text rows!
<textarea rows="2" readonly disabled>Try enameling the ricotta broccolis with aged champaign and rum, warmed. </textarea>
You could then use a pseudo element :after to add an ellipsis or a 'Read more'.
Don't forget the attributes 'readonly' and 'disabled'. Readonly prevents textarea from being interacted with by the user. Disabled prevents any forms in the page from submitting the values.

Categories