Show More/Less with pure Javascript - javascript

I need a simple read more/less example in pure javascript and CSS. How can I convert this jQuery example to pure Javascript?
https://jsfiddle.net/ngaffer/s75zj385/2/
I have several long paragraphs being generated on a page. In order to shorten the page to minimize scrolling, I want to hide the majority of each paragraph and display a link "read more". When the link is clicked the button will display the hidden text and change the link to "read less".
<section>
<div class="content hideContent">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<a class="show-more" href="#">Show more</a>
</section>
<section>
<div class="content hideContent">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<a class="show-more" href="#">Show more</a>
</section>
<script>
$("a.show-more").on("click", function() {
var $this = $(this);
var $content = $this.prev("div.content");
var linkText = $this.text().toUpperCase();
if(linkText === "SHOW MORE"){
linkText = "Show less";
$content.switchClass("hideContent", "showContent", 400);
} else {
linkText = "Show more";
$content.switchClass("showContent", "hideContent", 400);
};
$this.text(linkText);
});
</script>
<style>
.hideContent {
overflow: hidden;
line-height: 1em;
height: 2em;
}
.showContent {
line-height: 1em;
height: auto;
}
</style>

Here is a pure JS code that select anchors based on the class and with animation css trick:
var anchrorClassShow=document.getElementsByTagName('a');
for(var i=0;i<anchrorClassShow.length;i++){
if(anchrorClassShow[i].className!=='show-more'){
anchrorClassShow[i].remove();
}
}
for(var i=0;i<anchrorClassShow.length;i++){
anchrorClassShow[i].addEventListener('click', function(){
var parentDiv=this.parentElement;
if(parentDiv.children[0].className.match(/hideContent/g)){
parentDiv.children[0].className='content showContent';
}else{
parentDiv.children[0].className='content hideContent';
}
});
}
.hideContent {
max-height: 2em;
transition: max-height 0.15s linear;
overflow: hidden;
background: #d5d5d5;
}
.showContent {
max-height: 500px;
transition: max-height 0.35s linear;
}
<section>
<div class="content hideContent">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<a class="show-more" href="#">Show more</a>
</section>
<section>
<div class="content hideContent">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<a class="show-more" href="#">Show more</a>
</section>

A conversion like this isn't a very lengthy process.
Here is a very useful resource to know how to replace a common jquery code with plain (vanilla) javascript.
At the same time, I also took the liberty of modifying your javascript in a new fiddle.
var click_event = function() {
var linkText = this.innerHTML.toUpperCase();
if (linkText === "SHOW MORE") {
this.innerHTML = "Show less";
this.previousElementSibling.classList.remove("hideContent");
this.previousElementSibling.classList.add("showContent");
}
else {
this.innerHTML = "Show more";
this.previousElementSibling.classList.remove("showContent");
this.previousElementSibling.classList.add("hideContent");
}
};
var elements = document.getElementsByClassName("show-more");
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', click_event, false);
}
This code implements all the basic functionalities in vanilla JS. However, I have left out the 400ms time delay, which I think would be a very interesting exercise for you to work on. I hope this helps you in future events.

Related

How to make a one-pager navigation with waypoints to enable/disable nav elements?

I'm stuck at my one-pager navigation logic. As you can see in my detailed example below, I already have a dynamic navigation depending on the scroll position. Also, when you click a navigation item, you are getting scrolled down to the specific section.
What I'm stuck at is the point to add/remove the active class to the navigation item. Somehow, I can't find a logic in my brain to make this a smart part of my navigation. I know that I can make some static JS code, but that's not what I want.
At least, I just want to add another menu item and an element containing the data-waypoint attribute.
It's not an option to add this to the item click functionality, since the user can scroll down manually, which then don't get recognized!
(function($) {
$(document).ready(function() {
let nav = $('#nav');
let navOffsetTop = nav.offset().top;
$(window).scroll(function() {
if ($(this).scrollTop() >= navOffsetTop) {
nav.addClass('sticky');
} else {
nav.removeClass('sticky');
}
// Somehow add logic here for changing active classes...
if ($(this).scrollTop() >= $('#content').offset().top) {
//console.log('Reached');
}
});
$('.nav-item').click(function() {
let navPosition = nav.css('position');
let navOuterHeight = nav.outerHeight();
let scrollTo = $(this).data('scroll-to');
let scrollTop = $(`[data-waypoint=${scrollTo}]`).offset().top - navOuterHeight - 15;
if (navPosition === 'static') {
scrollTop = scrollTop - navOuterHeight - 30;
}
$([document.documentElement, document.body]).animate({
scrollTop: scrollTop
}, 500);
});
});
})(jQuery);
#page {
width: 100%;
padding-left: 50px;
padding-right: 50px;
box-sizing: border-box;
border: 1px solid;
}
#container {
width: 100%;
height: 1500px;
}
#nav {
width: 100%;
background-color: #aaa;
margin-bottom: 30px;
z-index: 1;
display: flex;
justify-content: space-between;
}
#nav .nav-item {
padding: 20px;
display: flex;
justify-content: center;
flex: 1;
cursor: pointer;
}
#nav .nav-item.active {
color: #fff;
}
#nav.sticky {
position: fixed;
top: 0;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="page">
<h1>Lorem Impsum page</h1>
<div id="nav">
<div class="nav-item active" data-scroll-to="home">Home</div>
<div class="nav-item" data-scroll-to="content">Content</div>
<div class="nav-item" data-scroll-to="about">About</div>
</div>
<div id="container">
<div id="home" data-waypoint="home">
<h2>Home</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
<div id="content" data-waypoint="content">
<h2>Content</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
<div id="about" data-waypoint="about">
<h2>About</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
</div>
</div>
I'm happy to share my answer I've found. I was first looking for a simple solution, but ended up using Waypoints jQuery library.
This is my solution. I hope it helps someone:
(function($) {
$(document).ready(function() {
let nav = $('#nav');
let navOffsetTop = nav.offset().top;
let navItem = $('.nav-item', nav);
$(window).on('resize, scroll', function() {
initNav(nav, navOffsetTop);
initWaypoints(nav, navItem);
});
$(window).resize(function() {
setNavHeight(nav);
});
navItem.click(function() {
let navOuterHeight = nav.outerHeight();
let scrollTo = $(this).data('scroll-to');
let scrollTop = $(`[data-waypoint=${scrollTo}]`).offset().top - navOuterHeight - 10;
$([document.documentElement, document.body]).animate({
scrollTop: scrollTop
}, 500);
});
setNavHeight(nav);
initNav(nav);
});
function setNavHeight(nav) {
let navItems = $('#nav-items', nav);
nav.css('min-height', `${navItems.outerHeight()}px`);
}
function initNav(nav, navOffsetTop) {
let navItems = $('#nav-items', nav);
let windowScrollTop = $(window).scrollTop();
if (windowScrollTop >= navOffsetTop) {
navItems.addClass('sticky');
} else {
navItems.removeClass('sticky');
}
}
function initWaypoints(nav, navItem) {
$('.block-waypoint').waypoint(function() {
let waypoint = $(this.element).data('waypoint');
let navItemWaypoint = $(`.nav-item[data-scroll-to=${waypoint}]`, nav);
navItem.removeClass('is-active');
if (navItemWaypoint.length) {
navItemWaypoint.addClass('is-active');
}
}, {
offset: 69
});
}
})(jQuery);
#page {
width: 100%;
padding-left: 50px;
padding-right: 50px;
box-sizing: border-box;
border: 1px solid;
}
#container {
width: 100%;
height: 1500px;
}
#nav {
margin-bottom: 30px;
}
#nav-items {
width: 100%;
background-color: #aaa;
margin-bottom: 30px;
z-index: 1;
display: flex;
justify-content: space-between;
}
#nav-items.sticky {
position: fixed;
top: 0;
left: 0;
}
.nav-item {
padding: 20px;
display: flex;
justify-content: center;
flex: 1;
cursor: pointer;
}
.nav-item.is-active {
color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script>
<div id="page">
<h1>Lorem Impsum page</h1>
<div id="nav">
<div id="nav-items">
<div class="nav-item is-active" data-scroll-to="home">Home</div>
<div class="nav-item" data-scroll-to="content">Content</div>
<div class="nav-item" data-scroll-to="about">About</div>
</div>
</div>
<div id="container">
<div id="home" class="block-waypoint" data-waypoint="home">
<h2>Home</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
<div id="content" class="block-waypoint" data-waypoint="content">
<h2>Content</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
<div id="about" class="block-waypoint" data-waypoint="about">
<h2>About</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
</div>
</div>
Also, I've wrapped the nav items into a wrapper and set the margin to the outer nav. During page init and resize, I'm setting a min-width to the outer nav to prevent any content jumping and issues with the waypoints. Otherwise, the offset and all the other calculation stuff makes a lot of problems.

HTML Overlay pass-through screen implementation

I am tying to implement a Draggable overlay screen(initially positioned at the bottom half) that passes through another screen. An example of how I would like it to look is as described here - https://medium.com/#iamWaseem99/how-to-make-swipable-draggable-overlay-views-in-swift-xcode-82a86adece9c.
Disclosure regarding the tools currently being used - TailwindCSS for styling, HTML, CSS and JS via the Stimulus JS framework.
Current approach - I have installed Hammer JS and was attempting to achieve this by tracking the "panup" event and adjust the height of both the divs to seem as through the bottom screen was passing through. This ended up being messy, was wondering if there is a cleaner approach to achieve this.
I have found a React library - https://github.com/manufont/react-swipeable-bottom-sheet, however I am currently not using the React framework so was wondering if there are any alternatives through which this can be achieved.
Thank you!
Based on the two links in your question i made a solution with Hammer.js but with "swipe" and top instead of "panup" and height. I don't know what is messy for you, but this is imo very clean:
hammerOverlay.on('swipe', (e) => {
overlay.style.top = ( e.deltaY < 0 ) ? 0 : (window.innerHeight - triggerHeight) + 'px';
});
Working example:
const overlay = document.querySelector('#overlay');
const triggerHeight = document.querySelector('#trigger').clientHeight;
const hammerOverlay = new Hammer(overlay);
hammerOverlay.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL });
hammerOverlay.on('swipe', (e) => {
overlay.style.top = ( e.deltaY < 0 ) ? 0 : (window.innerHeight - triggerHeight) + 'px';
});
#wrapper {
position: relative;
}
#overlay {
position: fixed;
top: calc(100% - 50px);
background-color: #ddd;
transition: top 300ms;
}
#trigger h3 {
height: 50px;
margin: 0;
text-align: center;
background-color: #eee;
}
<script src="https://hammerjs.github.io/dist/hammer.js"></script>
<div id="wrapper">
<div id="overlay">
<div id="trigger"><h3>Swipeable bottom sheet</h3></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
</div>
</div>
If you want an arrow like that in your first link, here is a solution with css arrows:
const overlay2 = document.querySelector('#overlay2');
const triggerHeight2 = document.querySelector('#trigger2').clientHeight;
const hammerOverlay2 = new Hammer(overlay2);
hammerOverlay2.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL });
hammerOverlay2.on('swipe', (e) => {
if( e.deltaY < 0 ) {
overlay2.style.top = 0;
overlay2.querySelector('.arrow').classList.remove('up');
overlay2.querySelector('.arrow').classList.add('down');
}
else {
overlay2.style.top = (window.innerHeight - triggerHeight2) + 'px';
overlay2.querySelector('.arrow').classList.remove('down');
overlay2.querySelector('.arrow').classList.add('up');
}
});
#wrapper {
position: relative;
}
#overlay2 {
position: fixed;
top: calc(100% - 50px);
background-color: #ddd;
transition: top 300ms;
}
#trigger2 {
display: flex;
justify-content: center;
align-items: center;
height: 50px;
background-color: #eee;
}
.arrow {
display: inline-block;
padding: 3px;
border: solid black;
border-width: 0 3px 3px 0;
}
.up {
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
}
.down {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
<script src="https://hammerjs.github.io/dist/hammer.js"></script>
<div id="wrapper">
<div id="overlay2">
<div id="trigger2"><i class="arrow up"></i></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
</div>
</div>

how to wrap keywords in html code with tooltip

What could be the best way to mark some keywords in an html code.
As an Example, I have this html code:
$text = '
<h1>Lorem Ipsum</h1>
<p>Lorem ipsum dolor sit āmet, consetetur sadipscing elitr, sed diam nonumy<br>
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</p>
<p><img src="test.jpg" alt="Lorem Ipsum">
<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,<br>
one, nò sea takimata 1 sanctus est Lorem ipsum dolor sit amet. Lörem ipsum dolor sit amet,<br>
consetetur sadipscing elitr, sed diam lor­em ipsum nonumy eirmod tempor invidunt ut labore et<br>
dolore magna aliquyam erat, sed diam voluptua.
</p>
';
And i would like to highlight the word "Lorem Ipsum" like this: <span class="tooltip">Lorem Ipsum</span>
Since the keywords originate from a database, it can happen that certain words only occur once and therefore twice:
$keywords = ['Lorem Ipsum', 'Lorem']
In this case, there should only be one marker. Because I don't want a code like this:
<span class="tooltip"><span class="tooltip">Lorem</span> Ipsum</span>
Also all tag attributes like title and altshould be ignored. The same should apply to links, because I don't wan't a double function like hover and click.
So the marked result should look like this:
$text = '
<h1><span class="tooltip">Lorem Ipsum</span></h1>
<p><span class="tooltip">Lorem ipsum</span> dolor sit āmet, consetetur sadipscing elitr, sed diam nonumy<br>
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</p>
<p><img src="test.jpg" alt="Lorem Ipsum">
<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,<br>
one, nò sea takimata 1 sanctus est Lorem ipsum dolor sit amet. Lörem ipsum dolor sit amet,<br>
consetetur sadipscing elitr, sed diam <span class="tooltip">lor­em ipsum</span> nonumy eirmod tempor invidunt ut labore et<br>
dolore magna aliquyam erat, sed diam voluptua.
</p>
';
As you can see, the keyword Lorem Ipsum should also match lorem ipsum in lowercase.
I would like to know what is the most promising way to solve this problem. PHP and Javascript would be possible. Could someone help me with an approach? Has anyone ever had to solve this problem?
This is similar to bad words filter using php Using Google to search for it.
this function will determine if your text contain any of the words and replace it with * this is pretty much similar to what you looking for and same approach you will have to do.
Check if your text contain the word from the array
A. Yes Contain, you need to clean that word from your text of all html tags
you can use something like this strip_tags("Hello <b>world!</b>");
and then replace with whatever you want or just wrap it with <Mark>
B. No Doesn't contain, then you will continue.
Your string case Upper or Lower you can fix it by using
lcfirst('January'); // january
ucfirst('January'); // January
ucwords('a title without caps'); // A Title Without Caps
Example Function will change your words in the array to *
function filterwords($text){
$filterWords = array('Lorem Ipsum','Lorem','Else');
$filterCount = sizeof($filterWords);
for($i=0; $i<$filterCount; $i++){
$text = preg_replace('/\b'.$filterWords[$i].'\b/ie',"str_repeat('*',strlen('$0'))",$text);
}
return $text;
}
Usage
echo filterwords("
<h1><mark>Lorem Ipsum</mark></h1>
<p><mark>Lorem ipsum</mark> dolor sit āmet, consetetur sadipscing elitr, sed diam nonumy<br>
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</p>
<p><img src="test.jpg" alt="Lorem Ipsum">
<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,<br>
one, nò sea takimata 1 sanctus est Lorem ipsum dolor sit amet. Lörem ipsum dolor sit amet,<br>
consetetur sadipscing elitr, sed diam <mark>lor­em ipsum</mark> nonumy eirmod tempor invidunt ut labore et<br>
dolore magna aliquyam erat, sed diam voluptua.
</p>
");
Update if you want to highlight also you can do this using JS
function highlight(text) {
var inputText = document.getElementById("inputText");
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML;
}
}
function highlight(text) {
var inputText = document.getElementById("inputText");
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML;
}
}
.highlight {
background-color: yellow;
}
<button onclick="highlight('fox')">Highlight</button>
<div id="inputText">
The fox went over the fence
</div>
You can solve this simple by using the regular expression
/(>.)(Lorem Ipsum)(.?<)/gi
Check this

Mark.js not highligting the text

I am trying to use mark.js for highlighting text in a specified container.
var searchKeyword = "ipsum";
$(".box").mark(searchKeyword, options);
<div class="box">
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
</p>
</div>
Mark.Js: https://markjs.io/
Codepen example: https://codepen.io/anon/pen/eVMZyb
Working example
var searchKeyword = "ipsum";
//$(".box").mark(searchKeyword, options);
$(".box").mark(searchKeyword, {
"element": "span",
"className": "highlight"
});
https://codepen.io/anon/pen/mXxPQW

Show more and show less by Button

I want to create a button named Read More
Which will display some more content when clicked. When it displays the content, the button text should be changed to be Read less.
$(".read-more a").on("click", function() {
var $link = $(this);
var $content = $link.parent().prev("div.text-content");
var linkText = $link.text();
$content.toggleClass("short-text, full-text");
$link.text(getShowLinkText(linkText));
return false;
});
function getShowLinkText(currentText) {
var newText = '';
if (currentText.toUpperCase() === "READ MORE") {
newText = "Read More";
} else {
newText = "Read Less";
}
return newText;
}
div.text-container {
margin: 0 auto;
width: 75%;
}
.text-content{
line-height: 1em;
}
.short-text {
overflow: hidden;
height: 2em;
}
.full-text{
height: auto;
}
h1 {
font-size: 24px;
}
.read-more {
padding: 10px 0;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="text-container">
<div class="text-content short-text">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<div class="read-more">
Read More
</div>
</div>
Does anyone know how to fix this issue?
Any advice and/or help would be really appreciated.
(Here a jfiddle what I have tried)
I updated your answer. Please try this.
https://jsfiddle.net/4cgbLne4/12/
<div class="text-container">
<div class="text-content short-text">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<div>
<button href="#" class="read-more">Read More</button>
</div>
</div>
$(".read-more").on("click", function() {
var $link = $(this);
var $content = $link.parent().prev("div.text-content");
var linkText = $link.text();
$content.toggleClass("short-text, full-text");
$link.text(getShowLinkText(linkText));
return false;
});
function getShowLinkText(currentText) {
var newText = '';
alert(currentText)
if (currentText.toUpperCase() === "READ MORE") {
newText = "Read Less";
} else {
newText = "Read More";
}
return newText;
}
Hope this will work for you.
I usually solve it without Javascript,
.text-container {
padding: 1em;
border: 3px double;
position: relative;
padding-bottom: 3em;
}
.text-container .read-more {
position: absolute;
bottom: .5em;
}
input.read-more-toggle { display: none; }
.read-more span { display: block; color: red; cursor: pointer; text-decoration: underline; }
.read-more span:last-child { display: none; }
input:checked + .read-more span:last-child { display: block; }
input:checked + .read-more span:first-child { display: none; }
.text-content {
overflow: hidden;
line-height: 1.5;
}
.read-more + .text-content {
max-height: 3em;
transition: max-height 1s;
}
input:checked + .read-more + .text-content {
max-height: 50em;
}
<div class="text-container">
<input type=checkbox id=more-text-toggle-1 class=read-more-toggle />
<label class="read-more" for="more-text-toggle-1">
<span>read more</span>
<span>read less</span>
</label>
<div class="text-content short-text">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
</div>
You only have to switch the "more" / "less" in your function:
function getShowLinkText(currentText) {
var newText = '';
if (currentText.toUpperCase().trim() === "READ MORE") {
newText = "Read Less";
} else {
newText = "Read More";
}
return newText;
}
Fiddle: https://jsfiddle.net/4cgbLne4/5/
You can try this
HTML
<div class="text-container">
<div class="text-content short-text">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<div class="read-more">
<button>Read More</button>
</div>
</div>
Jquery
$(".read-more button").on("click", function() {
var $content = $link.parent().prev("div.text-content");
$content.toggleClass("short-text, full-text");
if ($(this).text() == 'Read More')
$(this).text('Read Less');
else
$(this).text('Read More');
return false;
});
Example Fiddle - UPDATED
There is a mistake in toggling More and Less text:
$(".read-more a").on("click", function() {
var $link = $(this);
var $content = $link.parent().prev("div.text-content");
var linkText = $link.text();
$content.toggleClass("short-text, full-text");
$link.text(getShowLinkText(linkText));
});
function getShowLinkText(currentText) {
var newText = '';
if (currentText.toUpperCase() == "READ MORE") {
newText = "Read Less";
} else {
newText = "Read More";
}
return newText;
}
.short-text{color:#000000}
.full-text{color:#ff8800}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="text-container">
<div class="text-content short-text">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<div class="read-more">
Read More
</div>
</div>
For <button> get text by .text() and set text by .html('text')
For <input type="button"> get text by .val() and set text by .val('text')
Just added one token into this and changed condition on click of a tag
var token = 1;
$(".read-more a").on("click", function() {
var $link = $(this);
var $content = $link.parent().prev("div.text-content");
var linkText = $link.text();
$content.toggleClass("short-text, full-text");
$link.text(getShowLinkText(linkText));
if(token == 1)
{
$(this).text("Read Less");
token = 0;
}
else
{
$(this).text("Read More");
token = 1;
}
return false;
});
Here is jsFiddle

Categories

Resources