I have a page with multiple headers (h1,h2,h3). I need to get header ID and put it in URL as hash while I scroll through the page.
Example code below.
<div>
<h1 id="random_numbers_here">
<p> lorem ipsum </p>
<h1 id="random_numbers_here">
<p> lorem ipsum </p>
<h2 id="random_numbers_here">
<p> lorem ipsum </p>
<h3 id="random_numbers_here">
<p> lorem ipsum </p>
<h3 id="random_numbers_here">
<p> lorem ipsum </p>
</div>
My JS code:
$('.page').on('scroll',(function(){
var winTop = $('.page').scrollTop();
var h1 = $('h1');
var h2 = $('h2');
var h3 = $('h3');
$(h1).each(function(){
console.log(
$(this).offset().top < winTop +10
&& $(this).offset().top + $(this).height() > winTop + 10);
})
}));
When my "header detector" will work ill just $(this).attr('id') and use window.location.hash to put it in URL.
But it gives me true or false on wrong headers. On h2 it returns true while im at h3.
I have no idea how to make this work.
Related
How do I generate table of contents dynamically. following is my code but its only for one heading tag h3. I need it to work for all headings.
Here is my following sample format of the post :
<html>
<head></head>
<body>
<div id="tableofcontent"></div>
<div class="entry-content">
<h1 id="Test1">Main Heading</h1>
<p>Lorem Ipsum Lorem IpsumLorem IpsumLorem Ipsum</p>
<h2 id="Test2"> Sub Heading</h2>
<p>Lorem Ipsum Lorem IpsumLorem IpsumLorem Ipsum</p>
<h3 id ="Test3">Sub Sub Heading</h3>
<p>Lorem Ipsum Lorem IpsumLorem IpsumLorem Ipsum</p>
<h4>Sub Sub Heading</h4>
<p>Lorem Ipsum Lorem IpsumLorem IpsumLorem Ipsum</p>
</div>
</body>
</html>
How do I generate table of contents dynamically.
following is my code but its only for one heading tag h3. I need it to work for all headings.
jQuery(document).ready(function($) {
var $aWithId = $('.entry-content h3[id]');
if ($aWithId.length != 0) {
if ($aWithId.length > 0) {
$('#tableofcontent').prepend('<nav class="toc"><h3 class="widget-title">Table of Contents</h3><ol></ol></nav>');
}
}
var $aWithId = $('.entry-content h3[id]');
if ($aWithId.length != 0) {
$('.entry-content').find($aWithId).each(function() {
var $item = $(this);
var $id = $(this).attr('id');
var li = $('<li/>');
var a = $('<a/>', {
text: $item.text(),
href: '#' + $id,
title: $item.text()
});
a.appendTo(li);
$('#tableofcontent .toc ol').append(li);
});
}
});
Hi I've got a string where I want to spilt up the content "ipsum dolar" and wrap it into a span tag and have the background change to red. My code does this but it wraps the two words into separate span tags. How would i amend my code to wrap them into one span tag together? Any help on this would be appreciated.
var findWords = 'ipsum dolor';
var elem = document.querySelectorAll('p.content');
elem.forEach(function(el) {
el.innerHTML = el.textContent.split(' ').map(function(i) {
return findWords.indexOf(i) > -1 ? '<span class="matched">' + i + '</span>' : i;
}).join(' ');
});
.matched {background: red;}
<p class="content"> Lorem ipsum dolor sit amet</p>
<p class="content"> Lorem ipsum dolor sit amet</p>
Using .replace() will be better in this case:
var findWords = 'ipsum dolor';
var elem = document.querySelectorAll('p.content');
elem.forEach(function(el) {
el.innerHTML = el.textContent.replace(new RegExp(findWords, 'g'), '<span class="matched">' + findWords + '</span>');
});
.matched {background: red;}
<p class="content"> Lorem ipsum dolor sit amet</p>
<p class="content"> Lorem ipsum dolor sit amet ipsum dolor</p>
What is the best way of looping through a text block to find the index position of every element starting with icon- using javascript or jQuery.
I also want to ignore any <br> tags in the index position calculation.
I have thought about using substring to find the position of the elements.
Here is an example text block
<div class="intro">
Lorem dolor sit<br>
<span class="icon-pin"></span> consectetur<br>
adiposcing elit, sed do <span class="icon-hand"></span> lorem<br>
ipsum dolor sit amet.
</div>
What I want to get out of this is how many characters in (minus white space and tags) each [class^=icon-] is.
For example the first [class^=icon-] is 14 characters in
Thanks
I think this is what your looking for, it will find the index of the spans and ignore br
$(".intro [class^=icon-]").each(function() {
var i = $(".intro *:not(br)").index(this)
console.log(i)
})
Demo
$(".intro [class^=icon-]").each(function() {
var i = $(".intro *:not(br)").index(this)
console.log(i)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="intro">
Lorem dolor sit<br>
<span class="icon-pin"></span> consectetur<br> adiposcing elit, sed do <span class="icon-hand"></span> lorem<br> ipsum dolor sit amet.
</div>
You can achieve it with jquery each like in the example
$('[class^="icon-"]','.intro').each(function(index, element){
console.log(index,element);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="intro">
Lorem dolor sit<br>
<span class="icon-pin"></span> consectetur<br>
adiposcing elit, sed do <span class="icon-hand"></span> lorem<br>
ipsum dolor sit amet.
</div>
You can use more than 1 classes on a element. So, You can keep using your "icon-" classes and add another one to capture them like "grabber" and now you are good to go. Just find the "grabber" classes with a for loop like;
var y = "number of grabbers";
for(x:0;x<y;x++){
$('.grabber')[x].function.....
}
I'm trying to come up with a script that locates a paragraph with a class=SO-Para-Numbered-List, takes out the span element turns the paragraph into an li and then creates an ol and adds all list items within it.
This is the HTML structure
<p class="SOPara">Lorem ipsum dolor sit amet, consectetur adipisicing elit. </p>
<p class="SO-Para-Numbered-List"><span>i</span> some text </p>
<p class="SO-Para-Numbered-List"><span>ii</span> some text</p>
<p class="SO-Para-Numbered-List"><span>iii</span> some text </p>
<p class="SO-Para-Numbered-List"><span>iv</span> some text</p>
<p class="SO-Para-Numbered-List"><span>v</span> some text</p>
<p class="SO-Para-Numbered-List"><span>vi</span> some text</p>
<p class="SO-Para-Numbered-List"><span>vii</span> some text </p>
<p class="SOPara">Lorem ipsum dolor sit amet, consectetur adipisicing elit. </p>
And the jquery script
$(document).ready(function(){
//create ol
$(".SO-Para-Numbered-List").first().before("<ol class='newList'>");
//for each para item
$(".SO-Para-Numbered-List").each(function(){
//remove span
$(this).find("span").remove();
//save the text
var thisContent = $(this).text();
//replace p with li
var newText = $(this).replaceWith("<li style='list-style-type:lower-roman;' class='SOlistItem'>"+thisContent+"</li>");
//add items to list
$("ol.newList").add(newText);
});
});
I guess what I'm going for should look something like this
<ol>
<li style="list-style-type:lower-roman;" class="SOlistItem"> some text </li>
<li style="list-style-type:lower-roman;" class="SOlistItem"> some text </li>
<li style="list-style-type:lower-roman;" class="SOlistItem"> some text </li>
<li style="list-style-type:lower-roman;" class="SOlistItem"> some text </li>
</ol>
I can't figure out how to add the li to the dynamically created ol. Any thoughts?
Is there a way of having the code do the same for each set of elements on the page i.e. create a new list with numbering starting from 1 but for each group of <p class="SO-Para-Numbered-List"><span>i</span> some text </p> it encounters?
I tried setting it so that is locates the previous SOPara which is a paragraph always preceding the ones I want to turn into list items but I'm stuck
$(document).ready(function(){
$(".SO-Para-Numbered-List").each(function(){
if($(this).prev("p").hasClass("SOPara")){
$(this).before("<ol class='newList'></ol>");
$(this).siblings().nextUntil(".SOPara").each(function(){
var $this = $(this);
$(this).find("span").remove();
var listContent = $(this).text();
var newListItem = $(this).replaceWith("<li>"+listContent+"</li>");
});//end siblings function
}//end if
})//end SO Para function
});
You can user insertBefore() to get a reference to the ul and then append the lis to that
$(document).ready(function() {
var $ul = $("<ol class='newList'>").insertBefore('.SO-Para-Numbered-List:first');
//for each para item
$(".SO-Para-Numbered-List").each(function() {
$(this).find("span").remove();
var thisContent = $(this).text();
$('<li />', {
'class': 'SOlistItem',
text: thisContent
}).css({
'list-style-type': 'lower-roman'
}).appendTo($ul);
}).remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="SOPara">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
<p class="SO-Para-Numbered-List"><span>i</span> some text</p>
<p class="SO-Para-Numbered-List"><span>ii</span> some text</p>
<p class="SO-Para-Numbered-List"><span>iii</span> some text</p>
<p class="SO-Para-Numbered-List"><span>iv</span> some text</p>
<p class="SO-Para-Numbered-List"><span>v</span> some text</p>
<p class="SO-Para-Numbered-List"><span>vi</span> some text</p>
<p class="SO-Para-Numbered-List"><span>vii</span> some text</p>
<p class="SOPara">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
$(".SO-Para-Numbered-List:first").before("<ol class='newList'>");
$("p.SO-Para-Numbered-List").each(function() {
var getText = $(this).clone().children().remove().end().text();
$(".newList").append('<li>'+getText+'</li>');
}).remove();
Working Fiddle : https://jsfiddle.net/ydfyh19g/1/
try the append function:
$(document).ready(function() {
$("<ol class='newList'>").insertBefore('.SO-Para-Numbered-List:first');
//for each para item
$(".SO-Para-Numbered-List").each(function(){
//remove span
$(this).find("span").remove();
//save the text
var thisContent = $(this).text();
//add items to list
$("ol.newList").append("<li style='list-style-type:lower-roman;' class='SOlistItem'>"+thisContent+"</li>");
$(this).remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="SOPara">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
<p class="SO-Para-Numbered-List"><span>i</span> some text</p>
<p class="SO-Para-Numbered-List"><span>ii</span> some text</p>
<p class="SO-Para-Numbered-List"><span>iii</span> some text</p>
<p class="SO-Para-Numbered-List"><span>iv</span> some text</p>
<p class="SO-Para-Numbered-List"><span>v</span> some text</p>
<p class="SO-Para-Numbered-List"><span>vi</span> some text</p>
<p class="SO-Para-Numbered-List"><span>vii</span> some text</p>
<p class="SOPara">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
You're currently setting the list-style-type on the li elements, when it should be on the ol. Also the use of add() is not having the effect you're after, you should use append() instead.
To achieve what you require you can create a new ol and save it in a variable. This will then allow you to append() directly to it in the loop, while also removing the original SO-Para... elements. Try this:
var $ol = $('<ol class="newList">').insertBefore('.SO-Para-Numbered-List:first()');
$(".SO-Para-Numbered-List").each(function() {
$ol.append("<li>" + $(this).find('span').remove().end().text() + "</li>");
}).remove();
Working example
I have recently been working on a comment feature. By default, the height of the paragraph element containing the text is 80px. Overflow is set to hidden.
I have another button (labelled "See More") that expands the paragraph by changing height to 'auto'. This button should only be visible if the paragraph content is overflowing the default 80px height. Otherwise the button must not be displayed.
I have tried to do this with a javascript for loop and some JQuery code, though it doesn't work as it should. It shows or hides the button for all comment sections.
Here is the html:
<div class="commentOwnerPost">
<div class="commentPostHeader">
<h4 class="commentOwnerName">NavyFoxKid</h4>
<h4 class="commentPostDate">3 days ago</h4>
</div>
<p class="commentText"> lorem ipsum dolor sit amet consectur lorem ipsum dolor sit amet consectur
amet consectur lorem ipsum dolor sit amet consectur lorem ipsum
</p>
<div class="commentPostFooter">
<a class="btnReply">Reply</a>
<a class="btnSeeMore">See More</a>
</div>
</div>
Here is the JavaScript:
$(document).ready(function(){
var element = $('.commentOwnerPost');
for(i=0; i < element.length; i++){
var commentText = $(element[i]).children('.commentText');
if ($(commentText).offsetHeight < $(commentText).scrollHeight) {
$parent = $(commentText).parent('.commentOwnerPost');
$parent.find('.btnSeeMore').hide();
console.log('Comment text not overflowing ');
} else {
$parent = $(commentText).parent('.commentOwnerPost');
$parent.find('.btnSeeMore').show();
console.log('Comment text overflowing ');
}
$('.btnSeeMore').click(function(){
});
}
});
Thanks for taking the time to read. Any help would be appreciated.
It works perfectly for me, I simplify your code:
$(document).ready(function(){
var elements = $('.commentOwnerPost');
elements.each(function() {
var el = $(this).find('.commentText').get(0);
if(el.offsetHeight < el.scrollHeight) {
$(this).find('.btnSeeMore').show();
} else {
$(this).find('.btnSeeMore').hide();
}
});
});
.commentText { max-height: 25px; overflow:hidden;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="commentOwnerPost">
<div class="commentPostHeader">
<h4 class="commentOwnerName">NavyFoxKid</h4>
<h4 class="commentPostDate">3 days ago</h4>
</div>
<p class="commentText"> lorem ipsum dolor sit amet consectur lorem ipsum dolor sit amet consectur
amet consectur lorem ipsum dolor sit amet consectur lorem ipsum
</p>
<div class="commentPostFooter">
<a class="btnReply">Reply</a>
<a class="btnSeeMore">See More</a>
</div>
</div>
<div class="commentOwnerPost">
<div class="commentPostHeader">
<h4 class="commentOwnerName">NavyFoxKid</h4>
<h4 class="commentPostDate">3 days ago</h4>
</div>
<p class="commentText"> lorem ipsum dolor sit amet.
</p>
<div class="commentPostFooter">
<a class="btnReply">Reply</a>
<a class="btnSeeMore">See More</a>
</div>
</div>