0

I'm trying to make an expanding box by clicking on <a> but I can't understand how to use the this
this is how far I've gotten so far

function change()
{
 if(this.parentElement.style.height!="auto")
 {
  this.parentElement.style.height="auto";
  this.innerText="show less";
  }
  else
  {
  this.parentElement.style.height="100px";
  this.innerText="show lmore";
  }
}
.container {
  height: 100px;
  position: relative;

  display: grid;
  width: 100%;
  grid-template-columns: auto;
  grid-template-rows: 1fr 1rem;

  overflow: hidden;
  background-color: red;


}


.content {
  width: 100%;
  overflow: hidden;

}
<div class="container">

  <p class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

  <a class="read_more" href="javascript:void(0);" onclick="change()" style="background-color:yellow; width:50%">show</a>
</div>

While you're at it can you remind me why clicking anywhere in the green box is causing the link to be pressed?
(I can't seem to remember)
isherwood
  • 58,414
  • 16
  • 114
  • 157
cak3_lover
  • 1,440
  • 5
  • 26

3 Answers3

2

You use onclick=change(this), then add a parameter to the function instead of using this in the function.

function change(el) {
  if (el.parentElement.style.height != "auto") {
    el.parentElement.style.height = "auto";
    el.innerText = "show less";
  } else {
    el.parentElement.style.height = "100px";
    el.innerText = "show lmore";
  }
}
.container {
  height: 100px;
  position: relative;
  display: grid;
  width: 100%;
  grid-template-columns: auto;
  grid-template-rows: 1fr 1rem;
  overflow: hidden;
  background-color: red;
}

.content {
  width: 100%;
  overflow: hidden;
}
<div class="container">

  <p class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
    eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

  <a class="read_more" href="javascript:void(0);" onclick="change(this)" style="background-color:yellow; width:50%">show</a>
</div>
Barmar
  • 741,623
  • 53
  • 500
  • 612
2

The immediate answer is to pass this as an argument into your callback function, but...

You shouldn't be using an <a> element for this in the first place.

  • Anchors are for navigation and not just so that users have something to click on. Using them as JavaScript "hooks" can cause accessibility issues.
  • Any visible HTML element supports a click event, so for inline content, just use a span instead.
  • This will have the added benefits of you never having to use javascript:void() again! And, this in a DOM element event handler will work without having to pass it into the callback.

Next, do not use inline HTML event attributes like onclick.

  • This is a 25+ year old technique that simply will not die the death it deserves because it's so widely used and copied without an understanding of its drawbacks and the benefits of the modern approach of using .addEventListener() in separated JavaScript.

Strive to remove as many inline styles as possible and use CSS classes.

  • Inline styles have the highest CSS Specificity and therefore are the hardest styles to override if needed.

  • Using CSS classes avoids duplication of code, it declutters the HTML, and makes adding/removing the class very simple through JavaScript.

  • As you'll see below, relying on CSS classes reduces your JavaScript to just two lines in the function!

// If you set up your events in JavaScript with .addEventListener, "this" just works!
document.querySelector(".read_more").addEventListener("click", change);

function change() {
 // Just toggle the use of the smallSize CSS class and your done!
 this.parentElement.classList.toggle("smallSize");
 
 // And set the show message accordingly
 this.textContent = this.textContent === "Show More" ? "Show Less" : "Show More";
}
.container {
  position: relative;
  display: grid;
  width: 100%;
  grid-template-columns: auto;
  grid-template-rows: 1fr 1rem;
  background-color: #866;
}

.content { overflow: hidden; }

.read_more {
  background-color:yellow; width:50%; cursor:pointer;
}

/* All you need to do is apply this to the parent in the HTML
   and then toggle its use when the show is clicked. */
.smallSize { height:100px; overflow:hidden; }
<div class="container smallSize">
  <p class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

  <!-- See how much cleaner the HTML is now? -->
  <span class="read_more">Show More</span>
</div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

You can use a parameter in the function like Barmar's answer, but if you really want to use the this context, you'll need to attach your click event handler through JavaScript.

When using the inline onclick="..." attribute, the this context in the function will refer to the overall window object instead of the link in question.

var readMoreLinks = document.querySelectorAll(".read_more");
readMoreLinks.forEach(link => link.addEventListener("click", change));

function change()
{
 if(this.parentElement.style.height!="auto")
 {
  this.parentElement.style.height="auto";
  this.innerText="show less";
  }
  else
  {
  this.parentElement.style.height="100px";
  this.innerText="show lmore";
  }
}
.container {
  height: 100px;
  position: relative;

  display: grid;
  width: 100%;
  grid-template-columns: auto;
  grid-template-rows: 1fr 1rem;

  overflow: hidden;
  background-color: red;


}


.content {
  width: 100%;
  overflow: hidden;

}
<div class="container">

  <p class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

  <a class="read_more" href="javascript:void(0);" style="background-color:yellow; width:50%">show</a>
</div>
jeffjenx
  • 17,041
  • 6
  • 57
  • 99