Create a "read more" and "read less" link without using jQuery

For a college assignment, I need to dynamically insert new paragraphs when the "more" link is clicked and remove them when the "less" link is clicked. We are not allowed to use CSS or jQuery for this task. My current code for this functionality is below. The insertion works correctly, but the removal does not work as expected. Any thoughts on why this might be happening? I've tried putting an alert in the less() function and using return false on the anchor tag, but it doesn't prevent the page from redirecting.

window.onload = function()
{
    var href = document.getElementById("more");
    href.setAttribute("onclick","more(); return false;");
    var more = document.getElementById("more");
    more.onclick = function more()
    {   
        var para1 = document.createElement("p");
        para1.setAttribute("id", "para1");  
        var para1Cont = document.createTextNode("my text block 1");
        para1.appendChild(para1Cont);
        var more = document.getElementById("more");
        more.parentNode.insertBefore(para1, more);
        
        var para2 = document.createElement("p");
        para2.setAttribute("id", "para2");
        var para2Cont = document.createTextNode("My text block 2");
        para2.appendChild(para2Cont);
        more.parentNode.insertBefore(para2, more);
        
        var toLess = more.setAttribute("id", "less");
        var less = document.getElementById("less");
        less.setAttribute("onclick", "less(); return false;");
        less.innerHTML ="click here for less";
        
        return false;
    };
    
    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;
     }; 
};

And here's the corresponding HTML:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
<title>Help meeeee</title>
<link rel="stylesheet" type="text/css" href="styles/style.css">
    <link href="scripts/mystyles.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <div id="header">
      <h1>test page</h1>
    </div>
    <div id="content">
       <a href="nojs.htm"  id="more"> click for more </a>
    </div>
    <script type="text/javascript" src="scripts/myscript.js"></script>
  </body>

Answer №1

If you're eager to learn, here's a vanilla JavaScript example that might spark your interest:

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);

For a more meaningful demonstration, check out this fiddle

There are still some improvements to make like handling an unload event and hiding the less link.

To help you understand the code better, here are some key points:

  • addEventListener: Adopting event listeners over setting attributes directly ensures cleaner JavaScript. Directly setting attributes with setAttribute('onclick'...) is outdated practice.
  • l-callback: The main callback (
    window.addEventListener('load', function l()...
    ) queries the DOM three times and assigns the references to variables for later use.
  • document.createTextNode: Instead of using innerHTML, it's recommended to use createTextNode.

Edit:
Here's why optimizing variable names within nested scopes can enhance performance based on an excerpt from your code:

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

};

In this snippet, the name less is reused multiple times within different contexts leading to redundant DOM queries. Avoiding repetition and ensuring consistent variable types can optimize code execution.

By understanding how JavaScript resolves variable names in nested scopes, you can enhance code efficiency and reduce performance bottlenecks.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Selenium to continuously scroll to the bottom of the webpage

Selenium: I am new to WebDriverJS. I have experimented with this method in Java. Long repeat = 0l, scrollHeight = 0l, returnHeight = 0l; while(true){ if (repeat == 0) { returnHeight = (Long) jse.executeScript("var scroll =document.documentEle ...

Display a different DIV based on the presence of a URL variable, either hiding one or

If the URL contains the word 'email,' I want to hide the <div id="sociallocker"> and display the <div id="emaillocker">. I attempted the following code but it did not work: <script type="text/javascript"> $(function () { ...

What is the best way to share information among Vue3 single file component instances?

I am seeking a way to have certain data in my single file component shared among all instances on the page, similar to how static variables work in PHP/C. To achieve this, I understand that in single file components, we declare data as a function like so: ...

Having trouble accessing states in Redux using React Hooks, encountering an issue where property '_id' cannot be read from null

I'm currently working on a MERN web app and delving into React Hooks. My main goal right now is to access the states in my Redux store. However, when I refresh the page, I encounter this error message: TypeError: Cannot read property '_id&apos ...

Tips for personalizing a jQuery Mobile popup

Is there a way to customize the appearance of a dialog box using CSS? I've been struggling with my attempts so far... <div data-role="dialog" id="confirm-clear" class="dialog-custom" > <div data-role="content" > <p>Some ...

The column must have a defined value and cannot be left empty

I encountered an issue while trying to populate a database with seed data. The error message I received is: name: 'SequelizeDatabaseError', parent: Error: Column 'id' cannot be null code: 'ER_BAD_NULL_ERROR', errno: 1048, sql ...

Tween.js - Can you animate a variable using tweens?

Recently, I've been experimenting with three.js and tween.js and I'm curious if it's possible to animate a variable using tweening? Here are some of my attempts: 1) tween = new TWEEN.Tween(renderergl.toneMappingExposure).to( "0.001&qu ...

Unlocking the Power of NextJS Keyframes

After successfully creating a background with 3 images using keyframes in my initial project built with html and css, I decided to recreate the project using NextJS. However, I encountered an issue where the third image does not display in NextJS. Instead ...

A guide on extracting data from a customized HTML table on the client side and sending it to the Flask backend

I am looking to implement a feature where users can add as many rows as they want and input information into them. Once the user has finished adding the desired data, I need to process it using Flask on the server-side. Can someone please provide guidanc ...

Is there unnecessary repetition of data in Angular and Requirejs?

When running Angular under Requirejs, I encountered a situation where the data in the controller class was being repeated twice. This issue only seemed to occur when ng-app="myApp" was present in the div. Why is this happening? Here is an example from wel ...

CSS syntax highlighting in Visual Studio 2015 does not function properly when used within vbhtml razor pages

When editing my vbhtml pages, I've noticed that everything syntax-highlights properly except for the CSS enclosed in the <style>...</style> block. Inline CSS like <td style="color:yellow"... still highlights correctly, but not the CSS i ...

Transforming screen recording video chunks from blob into multipart for transmission via Api as a multipart

Seeking guidance in Angular 8 - looking for advice on converting screen recorded video chunks or blogs into a multipart format to send files via API (API only accepts multipart). Thank you in advance! ...

I am looking for a highly specialized jQuery selector that fits my exact requirements

Hello everyone, I'm encountering an issue with a jQuery selector. Here is the HTML code snippet: <div id="Id_Province_chzn"> <a href="javascript:void(0)" class="chzn-single chzn-default" tabindex="-1"> <span> + this.default_tex ...

Using the css function in JQuery may not always yield the desired results

These are the snippets of code I am working with: var topPix = $('#cc').css('top'); var leftPix = $('#cc').css('left'); $('#testFrame').css('top', topPix).css('left', leftPix); After ...

When switching windows or tabs, the user interface of the browser extension vanishes

As someone who is new to web application development and browser extension creation, I have encountered a challenge with my browser extension. When the extension popup is open and I switch browser windows, the UI (popup.html) disappears. It reappears whe ...

Guide to applying Bootstrap styles to a specific section of an HTML document

What can I do to ensure that the Bootstrap library used by the main app does not affect the styling of my controls when integrating my web application inside the main app? I want to maintain the current styles of my controls without any interference from ...

What steps should I take to resolve a 'Missing environment variable' issue in the Sanity platform?

No matter what I've tried, I can't seem to fix the error that keeps occurring. An uncaught error is popping up, saying that the environment variable NEXT_PUBLIC_SANITY_DATASET is missing. http://localhost:3333/static/sanity-5377bc10.js:4605 ...

What is the most effective way to update a variable from a function in Angular?

I have textboxes within an ng-repeat block. To detect changes from the original content, I store the original data in a variable. <tr data-ng-repeat="p in products"> <td> <textarea data-elastic data-ng-model="p.comment" data-ng-change ...

Issue with using passport.initialize() middleware in Sails.js and Passport.js combination

Currently utilizing Sails.js and attempting to integrate Passport.js with a REST API. Encountering an issue when calling the login function in my controller: /Users/Michael/Development/DictationProject/sails/20151010/dictee/node_modules/passport/lib/http/ ...

Why is my filtering and sorting function failing to function properly?

I have a collection of events represented by an array of objects, where each event contains a start date and an end date. My goal is to filter out any events that have already passed based on the current time (now), and then sort the remaining events in d ...