How to Setup Less Using Only Js

show more/Less text with just HTML and JavaScript

My answer is similar but different, there are a few ways to achieve toggling effect. I guess it depends on your circumstance. This may not be the best way for you in the end.

The missing piece you've been looking for is to create an if statement. This allows for you to toggle your text.

More on if statements here.

JSFiddle: http://jsfiddle.net/8u2jF/

Javascript:

var status = "less";

function toggleText()
{
var text="Here is some text that I want added to the HTML file";

if (status == "less") {
document.getElementById("textArea").innerHTML=text;
document.getElementById("toggleButton").innerText = "See Less";
status = "more";
} else if (status == "more") {
document.getElementById("textArea").innerHTML = "";
document.getElementById("toggleButton").innerText = "See More";
status = "less"
}
}

Without jQuery, make a show more show less a href

Ok, You've got a lot of learning to do. I don't mean that in a bad way, but here's a vanillaJS example of how I'd tackle this:

window.addEventListener('load',function l()
{//use addEventListener, to avoid mem-leaks
"use strict";//for JSLint
var more = document.getElementById('more'),
less = document.getElementById('less'),
div = more.parentNode,//3 DOM reference, to be used by event handlers
added = [],//keep references to added elements, use as stack
rmHandle = function(e)
{//callback definition, don't bind unless less link should be usable
var rm = added.pop();
rm.parentNode.removeChild(rm);
if (added.length === 0)
{
less.removeEventListener('click', rmHandle, false);
}
e.preventDefault();
e.stopPropagation();
};
more.addEventListener('click',function(e)
{//add node:
var newP, count = added.length;
e.preventDefault();
e.stopPropagation();
if (count === 0)
{//bind less event handler here
less.addEventListener('click', rmHandle, false);
}
++count;
newP = document.createElement('p');//create node
newP.setAttribute('id','param'+count);//set id
newP.appendChild(document.createTextNode('New Paragraph #'+count));//add txt content
added.push(newP);//keep reference to node
div.insertBefore(newP, less);//append at end...
},false);
window.removeEventListener('load',l,false);//unbind load handler, this is the leak in IE
}, false);

Now, this by itself is a bit meaningless, so I've gone ahead and set up this fiddle

There are quite a few things left to be done (ie an unload event handler, hide the less link etc...)

Some clarification to help you understand the code:

  • addEventListener: Instead of setting attibutes, or directly binding event handlers using onload or onclick, I'm adding event listeners. These have the benefit of keeping everything JS-side. You're using setAttribute('onclick'...) somewhere in your code. This sets an attribute in the DOM, that refers back to JS. This is considered bad practice, and quite out-dated.
  • l-callback. My main callback (window.addEventListener('load', function l()... is called l. In this function, I query the DOM three times (sort of) and I assign the references to these DOM nodes to a variable: more, less and div. Next, I declare an array, to hold all nodes I'll be creating. A sort of stack, so I never need to query the dom to get a reference to those nodes I've created.
  • I also declare a function (rmHandle), which will handle the clicks on the less link. Because I declare this function within the scope of l, the function has access to all variables I previously declared (less, more, added). Again: I need never query the DOM...
  • more.addEventListener: This link has to work from the off, so I'm attaching my event listener to this DOM node on load.
  • no return false: Your question suggests that you know of/have used jQuery. return false in jQ and return false in JavaScript are not the same thing. if you attach an event handler to a form in VanillaJS return false might leave you gobsmacked, because at times: the form will still be submitted. Read about the W3C event model: the capturing and bubbling phases. quirksmode.org is a good resource for details. You'll understand why I'm calling these methods explicitly soon enough.
  • document.createTextNode: Now I will admit to using innerHTML every now and then, too. But since you're learning, I might aswell point out that innerHTML is not standard, the official standard is to use createTextNode.
  • At the end I remove the load event listener Because IE tends to leak memory if you don't. Then, the callback goes out of scope and there's nothing you can do about it. So everything can be flagged for GC, and there is no way anything can leak memory, still...

Edit:

I will admit that, listing up a few list-items, of which one just briefly touches on JS's way of resolving variable names in nested scopes isn't quite clear enough. It wasn't for me when I first started learning about closures, and it certainly isn't enough to explain why the code I posted is going to outperform yours by quite a bit.

So if you're up to it, I'm going to explain this a bit more, using a excerpt from your code, and walk you through a clean-up review:

var less = document.getElementById("less");
less.onclick = function less()
{
var para1 = document.getElementById("para1");
var para2 = document.getElementById("para2");
alert("fr");
alert( para1.innerHTML);
para1.parentNode.removeChild(para1);
para2.parentNode.removeChild(para2);
var less = document.getElementById("less");
var toMore = less.setAttribute("id", "more");
var more = document.getElementById("more");
more.setAttribute("onclick", "more(); return false;");
more.innerHTML ="click here for more";
return false;
};

This code should look familiar to you (it's copy-pasted from your question after all). Now why would I change this? First off: the DOM API (not part of JS BTW) is slow, clunky, illogical and a main source of frustration and using it too much kills woodland critters. In this snippet, we see this, though:

var less = document.getElementById("less");
less.onclick = function less()
{
//...
var less = document.getElementById("less");
}

So the name less is being used 3 times in an assignment context. Two of those assignments involve a DOM query. Not just a query, but exactly the same query: document.getElementById("less");! It's often said that one of the rules for writing good code is Do Not Repeat Yourself.

Another thing you might have heard is that, even when using loosely typed languages, it's not a bad idea to not assign different types to one variable. You're doing just that, though when you write function less(){}. Apart from a few (at times significant, but that's for some other time) semantic differences, this is basically the same as doing:

var less = function(){};

Each of these assignments is masking the previous one. If wou would've written:

var less = document.getElementById("less");
less.onclick = function less_func()
{
console.log(less);//logs a dom reference!
};
//or even:
less.onclick = function()
{//anonymous or lambda functions are valid... and quite common, too
console.log(less);
};

You wouldn't need that second DOM query witing the onclick function at all. This is because if JS's way of trying to resolve all variables to a previously declared variable. Consider this:

var evilGlobal = 'Do not use Globals';
function()
{
var goodLocal = 'Declared in function',
funcVar = function()
{
console.log(goodLocal);
console.log(evilGlobal);
},
func2 = function goodLocal(evilGlobal)
{
console.log(goodLocal);
console.log(evilGlobal);
console.log(funcVar());
};
funcVar();//logs Declared in function and Do not use Globals
func2();//logs itself (function), and undefined and then same as above
func2(goodLocal);//logs itself, Declared in Function and the same as funcVar
}

How does this come about? within funcVar it's fairly simple:

console.log(goodLocal);//<-- JS looks inside funcVar's function scope for var goodLocal
//not found? JS looks in the outer scope, that of the anonymous function that starts
//with var goodLocal = 'Declared in Function'
//This is the var used

The same applies to console.log(evilGlobal). Only this time, JS scans funcVar's scope, the anonymous function's scope and the global namespace. Why shouldn't you use globals? well, they're clearly slower, they can change state because functions can access them freely, and they clog the memory (the garbage collector only frees what is no longer referenced anywhere. The global namespace is always accessible).

The second case is a tad trickier, but not by much:

function goodLocal()//the goodLocal name is defined as the function!

this name is masks the variable in the outer scope. JS starts scanning the local scope, and finds goodLocal to be pointing to the function. It never checks the outer scope, so it never sees the goodLocal var in the parent function.

The same applies to evilGlobal:

function goodLocal(evilGlobal)

An argument is a variable, declared in the scope of the function. JS will never scan the global ns, because both names can be resolves localy, except for:

console.log(funcVar());

This will result in a scope scan of the parent function, which declares the funcVar variable, and assigns the previously discussed function to it. This function will still behave no different, as the function is called in its own scope/context.

Call contexts are quite tricky, too, so I'm going to gloss over this for a moment.

Back to your code: the other statements are actually repetitions of stuff you've written before, too: var para1 and var para2 are redundant, if you just keep them accessible in the outer scope.

Ah well, just keep reading, and keep learning, you'll get it soon enough...

Show more/Show less Toggle Button for Multiple Elements with Pure JavaScript [No jQuery]

You need querySelectorAll instead of querySelector to retrieve and iterate over multiple elements. I'd suggest using a .hidden class instead, and then you can iterate over the .hidden-items and just toggle the class on each:

const button = document.querySelector('.toggle-button');const hiddenItems = document.querySelectorAll('.hidden-item');let isHidden = true;button.addEventListener('click', () => {  button.textContent = isHidden  ? 'Hide items'  : 'Show more items';    isHidden = !isHidden;  hiddenItems.forEach(item => item.classList.toggle('hidden'));});
.hidden {  display: none;}
<div class="item">Item 1</div><div class="item">Item 2</div><div class="item hidden-item hidden">Item 3</div><div class="item hidden-item hidden">Item 4</div><div class="item hidden-item hidden">Item 5</div><button class="toggle-button">Show more items</button>

show less or show more in javaScript html

You can do a little trick like this where you assign the full text content to a dataset attribute at page load but display the short version on the page.
When the button is clicked, assign the short text content to another dataset attribute and display the full text. This process then repeats to hide the full text when the button is clicked again.

document.querySelectorAll('button.More').forEach(bttn=>{
bttn.dataset.state=0;
bttn.addEventListener('click',function(e){
let span=this.previousElementSibling;
span.dataset.tmp=span.textContent;
span.textContent=span.dataset.content;
span.dataset.content=span.dataset.tmp;

this.innerHTML=this.dataset.state==1 ? 'Show More...' : 'Show Less...';
this.dataset.state=1-this.dataset.state;
})
});

document.querySelectorAll('span.p1').forEach(span=>{
span.dataset.content=span.textContent;
span.textContent=span.textContent.substr(0,100) + '...';
})
.p1{margin:1rem;display:block;}
<span class="p1" >
Breaking India: Western Interventions in Dravidian and Dalit Faultlines is a book written by Rajiv Malhotra and Aravindan Neelakandan which argues that India's integrity is being undermined
</span>
<button class="More">..Show More</button>

<span class="p1" >
I hate yogurt. It's just stuff with bits in. You hit me with a cricket bat. All I've got to do is pass as an ordinary human being. Simple. What could possibly go wrong? I'm the Doctor, I'm worse than everyone's aunt. *catches himself* And that is not how I'm introducing myself.

All I've got to do is pass as an ordinary human being. Simple. What could possibly go wrong? The way I see it, every life is a pile of good things and bad things.…hey.…the good things don't always soften the bad things; but vice-versa the bad things don't necessarily spoil the good things and make them unimportant.
</span>
<button class="More">..Show More</button>

<span class="p1" >
Saving the world with meals on wheels. Saving the world with meals on wheels. It's art! A statement on modern society, 'Oh Ain't Modern Society Awful?'! I'm nobody's taxi service; I'm not gonna be there to catch you every time you feel like jumping out of a spaceship.

You hit me with a cricket bat. You've swallowed a planet! You know how I sometimes have really brilliant ideas? Heh-haa! Super squeaky bum time! Aw, you're all Mr. Grumpy Face today.
</span>
<button class="More">..Show More</button>

<span class="p1" >
Aw, you're all Mr. Grumpy Face today. I am the last of my species, and I know how that weighs on the heart so don't lie to me! All I've got to do is pass as an ordinary human being. Simple. What could possibly go wrong?

You hit me with a cricket bat. No, I'll fix it. I'm good at fixing rot. Call me the Rotmeister. No, I'm the Doctor. Don't call me the Rotmeister. Stop talking, brain thinking. Hush. I am the last of my species, and I know how that weighs on the heart so don't lie to me!
</span>
<button class="More">..Show More</button>


Related Topics



Leave a reply



Submit