How to create tooltip over text selection without wrapping? - javascript

My end goal is to create a tooltip over a text selection. The user will then be able to interact with the tooltip similar to . Please note that I was able to accomplish this by wrapping selected text in a tag and then creating the tooltip on it however this is no longer an option for me due to some other requirements and functionality issues. If you notice in the image above in element inspector, the selected text is not wrapped in any kind of tag, the tooltip is just created over the selection. I have already looked at this and it will not work for me because mouse position may not be the same as the end of selection. I need the actual selection position.
General question: What is the best way to accomplish this?
More specific questions:
Should I be using the coordinates of the selection? If so is there a way to get the coordinates of the top corners of the rectangular selection so I can find the mid point and create a the tooltip over that.
Is there a way to get that selection as an element? So I can just place a tooltip over that? (Note the selection can be multiple nodes)

Assuming something selected
var selection = window.getSelection(), // get the selection then
range = selection.getRangeAt(0), // the range at first selection group
rect = range.getBoundingClientRect(); // and convert this to useful data
rect is now a Object which holds the positions relative the the current scroll coordinates of the Window. More info on this here. If you want to be even more precise, you can use getClientRects which returns a list of such Objects, which you would then have to put together to form the area of the selection.
Now, to draw a box around it (I'll take the easy route using fixed for demonstration purposes)
var div = document.createElement('div'); // make box
div.style.border = '2px solid black'; // with outline
div.style.position = 'fixed'; // fixed positioning = easy mode
div.style.top = rect.top + 'px'; // set coordinates
div.style.left = rect.left + 'px';
div.style.height = rect.height + 'px'; // and size
div.style.width = rect.width + 'px';
document.body.appendChild(div); // finally append
You will probably want to take into consideration the scroll position so you can use absolute positioning. If there are no other scrollable elements, this means you just need to factor in the values of window.scrollX and window.scrollY, which are the position of the window's x and y coordinates in pixels at the time they're accessed.
var div = null;
function drawBorderAroundSelection() {
var selection = window.getSelection(), // get the selection then
range = selection.getRangeAt(0), // the range at first selection group
rect = range.getBoundingClientRect(); // and convert this to useful data
if (rect.width > 0) {
if (div) {
div.parentNode.removeChild(div);
}
div = document.createElement('div'); // make box
div.class = 'rect';
div.style.border = '2px solid black'; // with outline
div.style.position = 'fixed'; // fixed positioning = easy mode
div.style.top = rect.top + 'px'; // set coordinates
div.style.left = rect.left + 'px';
div.style.height = rect.height + 'px'; // and size
div.style.width = rect.width + 'px';
document.body.appendChild(div); // finally append
}
}
window.onmouseup = drawBorderAroundSelection;
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut dolor porta neque vulputate auctor et a ligula. Quisque bibendum risus magna, eget feugiat erat faucibus sed. Phasellus sed massa elementum, laoreet ipsum non, dignissim orci. Aenean lobortis
nunc et purus molestie, vel consectetur ligula dapibus. In ut lorem mattis, commodo nisi aliquam, porta ante. Curabitur sit amet libero sed justo finibus porttitor. Donec ac est ultrices, pretium diam sed, blandit nunc. Morbi consequat finibus augue
vel ultricies. Vestibulum efficitur ante vitae cursus accumsan. Vestibulum rutrum ex ex, a egestas nisi malesuada eu. Pellentesque fermentum, ante id convallis luctus, tellus lectus viverra diam, sit amet convallis ligula lorem sit amet neque.
</p>

$(document).ready(function () {
function tweetButtonClick() {
let selectedText = document.getSelection().toString();
/*window.open(
"https://twitter.com/intent/tweet?url=https://www.linkedin.com/in/harsha-vardhan-ch-245197bb/&text=" +
selectedText
);*/
console.log("This is your selected text: ",selectedText);
}
const textSelectionTooltipContainer = document.createElement("div");
textSelectionTooltipContainer.setAttribute(
"id",
"textSelectionTooltipContainer"
);
textSelectionTooltipContainer.innerHTML = `<button id="textShareTwitterBtn">TWEET</button>`;
const bodyElement = document.getElementsByTagName("BODY")[0];
$("body").on("click", "#textShareTwitterBtn", tweetButtonClick);
bodyElement.addEventListener("mouseup", function (e) {
var textu = document.getSelection().toString();
if (!textu.length) {
textSelectionTooltipContainer.remove();
}
});
document
.getElementById("textToSelect")
.addEventListener("mouseup", function (e) {
let textu = document.getSelection().toString();
let matchu = /\r|\n/.exec(textu);
if (textu.length && !matchu) {
let range = document.getSelection().getRangeAt(0);
rect = range.getBoundingClientRect();
scrollPosition = $(window).scrollTop();
containerTop = scrollPosition + rect.top - 50 + "px";
containerLeft = rect.left + rect.width / 2 - 50 + "px";
textSelectionTooltipContainer.style.transform =
"translate3d(" + containerLeft + "," + containerTop + "," + "0px)";
bodyElement.appendChild(textSelectionTooltipContainer);
}
});
});
#textSelectionTooltipContainer {
will-change: transform;
position: absolute;
width: 100px;
height: 40px;
background: #f7d39d;
top: 0px;
left: 0px;
display: flex;
padding: 5px 10px;
box-sizing: border-box;
justify-content: center;
}
#textSelectionTooltipContainer button {
font-size: 14px;
border: 1px solid black;
background: none;
cursor: pointer;
margin: 0 2px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel='stylesheet' href='shareText.css' />
<title>Text Share Feature</title>
<script>
</script>
</head>
<body>
<div id="textToSelect">
<h1>HTML Ipsum Presents</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,
sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
elit sit amet quam. Vivamus pretium ornare est.</p>
<p>
Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
<h1>HTML Ipsum Presents</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,
sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
elit sit amet quam. Vivamus pretium ornare est.</p>
<p>
Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
<h1>HTML Ipsum Presents</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,
sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
elit sit amet quam. Vivamus pretium ornare est.</p>
<p>
Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
<h1>HTML Ipsum Presents</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,
sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
elit sit amet quam. Vivamus pretium ornare est.</p>
<p>
Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
</div>
<script src="shareText.js"></script>
</body>
</html>
window.open lets you open the twitter page(https://twitter.com/intent/tweet) where you can share the selected text and also url.

Related

How to make ::selection background and text change randomly based on specific colors

I'm trying to change the ::selection background and text of my website using JS.
I want to make the selection background and text change randomly based on the colors I already chose.
I have the color changed using just CSS, like this:
::selection {
background-color: #ffce00;
color: #000;
}
::-moz-selection {
background-color: #ffce00;
color: #000;
}
::-o-selection {
background-color: #ffce00;
color: #000;
}
::-ms-selection {
background-color: #ffce00;
color: #000;
}
::-webkit-selection {
background-color: #ffce00;
color: #000;
}
But I want the color to be changed in each new selection made, like this :
I'd appreciate it if anyone could help.
Thank you.
You could use insertAdjacentHTML to overwrite the previous style with Javascript:
window.colors = ['#9ACD32','Chocolate','DeepPink','LightSkyBlue','BurlyWood','GreenYellow','Plum','Coral','CornflowerBlue','IndianRed']
window.order = 0
document.addEventListener("mousedown", function() {
document.head.insertAdjacentHTML('beforeend', '<style>::selection { background-color:' + window.colors[window.order] + '} ::-moz-selection { background-color:' + window.colors[window.order] + '} ::-o-selection { background-color:' + window.colors[window.order] + '} ::-ms-selection { background-color:' + window.colors[window.order] + '} ::-webkit-selection { background-color:' + window.colors[window.order] + '}</style>');
window.order = window.order + 1
if (window.order > window.colors.length - 1){
window.order = 0
}
});
<p>Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. </p>
<p>Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. Text text text and more text. </p>
Am not sure if this is what you want, but please below my solution.
const containerBlock = document.querySelector('.random-colors');
containerBlock.addEventListener("mousedown", () => {
const mode = containerBlock.getAttribute('mode') || 1;
const modeNumber = +mode;
containerBlock.setAttribute('mode', modeNumber === 6 ? 1 : modeNumber + 1);
});
.random-colors[mode="1"]::selection {
background-color: #ffce00;
color: #000;
}
.random-colors[mode="2"]::selection {
background-color: red;
color: #000;
}
.random-colors[mode="3"]::selection {
background-color: blue;
color: #000;
}
.random-colors[mode="4"]::selection {
background-color: cyan;
color: #000;
}
.random-colors[mode="5"]::selection {
background-color: pink;
color: #000;
}
.random-colors[mode="6"]::selection {
background-color: violet;
color: #000;
}
<div class="random-colors" mode="1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In hendrerit condimentum faucibus. Mauris a hendrerit dolor. Pellentesque eget massa dignissim, fermentum enim sit amet, rutrum massa. Sed in porttitor felis. Quisque feugiat ultricies tortor, vel
blandit quam tempor vel. In ac dapibus nibh. Nunc sit amet scelerisque sapien, a porttitor eros. In efficitur condimentum diam, non tempus massa finibus sed. Nam cursus turpis augue, ut varius tellus venenatis eu. Vestibulum blandit felis eget aliquet
mattis. Aenean leo ipsum, volutpat nec ultricies a, mattis at diam. Sed a blandit diam. Nunc rutrum viverra condimentum. Sed at semper arcu. Cras non auctor massa. Pellentesque mollis egestas diam, nec ullamcorper arcu commodo vel. Curabitur sed porta
urna, ac tempus sem. Donec pharetra, nulla ac pellentesque mollis, magna lacus suscipit leo, sit amet euismod orci quam ac erat. Sed tempus consectetur tellus viverra condimentum. Curabitur accumsan vitae dui sed tincidunt. Nullam lorem ante, sollicitudin
eu volutpat at, iaculis vitae sem. Aliquam et elementum velit, sit amet elementum odio. Morbi ut cursus velit. Phasellus lacinia, velit a varius aliquam, justo dui egestas dolor, sagittis auctor tellus nisl vel ex. Morbi placerat elit in tortor euismod
scelerisque. Nam tempor turpis vel nunc convallis, vel ullamcorper quam feugiat. Praesent congue est odio, sed gravida purus ornare quis. Quisque sed commodo nunc. Mauris enim enim, euismod in nisi vel, tristique molestie turpis. Ut maximus erat tellus,
sed pellentesque est pellentesque non. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla placerat felis eu ex sodales, ut sagittis lorem molestie. Curabitur condimentum ipsum tellus, eget tristique purus cursus
sodales. Proin sodales sem sed augue viverra, non egestas lorem bibendum. Nullam odio leo, convallis sit amet posuere ut, cursus ac leo. Phasellus tempor, urna sit amet elementum luctus, ex sem ultrices justo, quis placerat urna lectus quis mauris.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Quisque gravida nec justo nec pulvinar. Curabitur quis luctus leo. Ut malesuada et magna et laoreet. Fusce laoreet blandit semper. Morbi et nibh condimentum,
blandit arcu at, tristique nunc. Aliquam tincidunt vehicula diam, nec porta elit mattis non. Nunc ut sodales erat. Suspendisse placerat, risus in iaculis blandit, libero libero porta arcu, ac cursus purus enim non urna. Quisque rutrum auctor elit quis
ultricies. Phasellus tincidunt nec mi et facilisis. Mauris faucibus faucibus massa in dignissim. Sed turpis nisl, ornare et egestas egestas, porttitor at lectus. Etiam lobortis ante orci, et facilisis quam scelerisque sit amet. Etiam eu rhoncus lorem.
Vivamus imperdiet mi vitae ipsum convallis mattis. Morbi non metus ac odio pellentesque scelerisque.
</div>
p:nth-child(4n+1)::selection {
color: red;
}
p:nth-child(4n+2)::selection {
color: green;
}
p:nth-child(4n+3)::selection {
color: orange;
}
p:nth-child(4n+4)::selection {
color: blue;
}
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, est!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, est!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, est!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, est!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, est!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, est!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, est!</p>
Try to use nth-child
You can update css variable through Javascript as well.
let root = document.documentElement;
document.querySelector('p').addEventListener("mousedown", e => {
const randomColor = Math.floor(Math.random()*16777215).toString(16);
root.style.setProperty('--highlight-color', '#'+randomColor);
});
:root {
--highlight-color: red;
}
p::selection {
background: var(--highlight-color);
}
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus.</p>

Wrap content based on window.innerHeight in jQuery?

My website is very text-heavy, and I want to break it into pieces automatically based on the content height, like google docs or word does.
So I figured I'd use window.innerHeight to get the full height, and do something like:
$("content").ready(function(){
from(window.innerHeight == 1,window.innerHeight == 70%){
$(this).wrapInner('<div class="wrapper"> </div>').append('<div class="endpage"></div>')
}
from($(".endpage").innerHeight, $(".endpage").innerHeight + 70%){
$(this).wrapInner('<div class="wrapper"> </div>').append('<div class="endpage"></div>')
}})
Where the .wrapper div needs to wrap the elements that fill 70% of the screen like so:
<div class="wrapper">
//content filling 70% of the screen height
</div>
<div class="wrapper">
//content filling 70% of the screen height
</div>
But of course, it doesn't work.
How would I do this?
EDIT:
As requested, here is a snippet:
$("content").ready(function() {
from(window.innerHeight == 1, window.innerHeight == 70 % ) {
$(this).wrapInner('<div class="wrapper"> </div>').append('<div class="endpage"></div>')
}
from($(".endpage").innerHeight, $(".endpage").innerHeight + 70 % ) {
$(this).wrapInner('<div class="wrapper"> </div>').append('<div class="endpage"></div>')
}
})
#import url("https://fonts.googleapis.com/css?family=Lora:400,400i,700,700i");
#import url("https://fonts.googleapis.com/css?family=Raleway:400,400i,700,700i");
h1,
h2,
h3,
h4,
h5,
h6,
th,
label {
font-family: "Raleway", sans-serif;
font-weight: 400;
text-align: left;
color: #0a0a0a;
line-height: 1.5em;
}
p,
td {
margin: 0;
font-size: 1.3em;
}
p+p {
text-indent: 2em;
}
ol,
ul {
font-size: 1.3em;
padding: 0em 1em;
margin: 1em 0em;
}
ul ul,
ol ol {
font-size: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="content">
<h1>lorem Ipsum</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sed dui vel erat ornare tristique. Nulla tristique rutrum auctor. Etiam sed diam quam. Mauris suscipit tortor ut felis pharetra, eget semper lorem suscipit. Pellentesque sit amet mollis nulla.
Vivamus at est congue, commodo ex id, aliquet dolor. Integer lobortis efficitur velit. Nam vehicula mattis lectus, at malesuada mauris convallis elementum.</p>
<ul>
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sed dui vel erat ornare tristique. Nulla tristique rutrum auctor. Etiam sed diam quam. Mauris suscipit tortor ut felis pharetra, eget semper lorem suscipit. Pellentesque sit amet mollis nulla.
Vivamus at est congue, commodo ex id, aliquet dolor. Integer lobortis efficitur velit. Nam vehicula mattis lectus, at malesuada mauris convallis elementum.</li>
<ul>
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sed dui vel erat ornare tristique. Nulla tristique rutrum auctor. Etiam sed diam quam. Mauris suscipit tortor ut felis pharetra, eget semper lorem suscipit. Pellentesque sit amet mollis
nulla. Vivamus at est congue, commodo ex id, aliquet dolor. Integer lobortis efficitur velit. Nam vehicula mattis lectus, at malesuada mauris convallis elementum.</li>
</ul>
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sed dui vel erat ornare tristique. Nulla tristique rutrum auctor. Etiam sed diam quam. Mauris suscipit tortor ut felis pharetra, eget semper lorem suscipit. Pellentesque sit amet mollis nulla.
Vivamus at est congue, commodo ex id, aliquet dolor. Integer lobortis efficitur velit. Nam vehicula mattis lectus, at malesuada mauris convallis elementum.</li>
<ul>
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sed dui vel erat ornare tristique. Nulla tristique rutrum auctor. Etiam sed diam quam. Mauris suscipit tortor ut felis pharetra, eget semper lorem suscipit. Pellentesque sit amet mollis
nulla. Vivamus at est congue, commodo ex id, aliquet dolor. Integer lobortis efficitur velit. Nam vehicula mattis lectus, at malesuada mauris convallis elementum.</li>
</ul>
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sed dui vel erat ornare tristique. Nulla tristique rutrum auctor. Etiam sed diam quam. Mauris suscipit tortor ut felis pharetra, eget semper lorem suscipit. Pellentesque sit amet mollis nulla.
Vivamus at est congue, commodo ex id, aliquet dolor. Integer lobortis efficitur velit. Nam vehicula mattis lectus, at malesuada mauris convallis elementum.</li>
<ul>
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sed dui vel erat ornare tristique. Nulla tristique rutrum auctor. Etiam sed diam quam. Mauris suscipit tortor ut felis pharetra, eget semper lorem suscipit. Pellentesque sit amet mollis
nulla. Vivamus at est congue, commodo ex id, aliquet dolor. Integer lobortis efficitur velit. Nam vehicula mattis lectus, at malesuada mauris convallis elementum.</li>
</ul>
</ul>
</div>
You could try to define your sections individually:
var wph = $(".wrapper").height(); //this could be window.innerHeight
if( wph > 50 ){
$(".wrapper").wrapInner("<div class='pager'></div>");
}
Then you could define a value using str.length:
$(".wrapper").text().length;
This could help to layout your content.

Convert multi-line wrapped paragraphs into single line paragraphs

Let's say we have this text inside a single <p> that uses the entire screen space:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vestibulum
sem consectetur, tempor massa quis, bibendum mauris. Curabitur et leo
pharetra, condimentum mi vel, gravida mi. Integer pulvinar nibh in
laoreet auctor. Donec in tortor in augue maximus fermentum et non erat.
Sed auctor feugiat dolor eget efficitur. Vivamus nec urna lorem. Duis
lobortis semper tempor. Vestibulum dolor lectus, consectetur.
If we were using a smaller display, it would look like something this:
Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Sed vestibulum sem
consectetur, tempor massa quis, bibendum
mauris. Curabitur et leo pharetra,
condimentum mi vel, gravida mi. Integer
pulvinar nibh in laoreet auctor. Donec
in tortor in augue maximus fermentum et
non erat. Sed auctor feugiat dolor eget
efficitur. Vivamus nec urna lorem. Duis
lobortis semper tempor. Vestibulum dolor
lectus, consectetur.
The paragraph has now more lines than before. With that said, I want to convert this single paragraph into one <p> per line to apply different styling to each one of them, but also taking into acount that the number of lines can change from the viewport/browser window size. This is so that the text styling can be responsive.
HTML:
<p>Lorem ipsum dolor sit amet, consectetur</p>
<p>adipiscing elit. Sed vestibulum sem</p>
<p>consectetur, tempor massa quis, bibendum</p>
<p>mauris. Curabitur et leo pharetra,</p>
<p>condimentum mi vel, gravida mi. Integer</p>
<p>pulvinar nibh in laoreet auctor. Donec</p>
<p>in tortor in augue maximus fermentum et</p>
<p>non erat. Sed auctor feugiat dolor eget</p>
<p>efficitur. Vivamus nec urna lorem. Duis</p>
<p>lobortis semper tempor. Vestibulum dolor</p>
<p>lectus, consectetur.</p>
I'm looking for a pure JavaScript (aka no jQuery) solution.
document.body.addEventListener("load", function(){
var defaultCharacterWidth = 8; //8 px
var textboxWidth = document.querySelector(".orgText").offsetWidth;
var breakIndex = Math.floor(textboxWidth/defaultCharacterWidth);
var i = 0;
var savedIndex = 0;
var whitespace = 0;
document.querySelector(".orgText").textContent.match(/[\s\S]/g).forEach(function(element, index){
if (element.match(/\s/))
{
whitespace = index;
}
if (i == breakIndex)
{
i = -1;
//get nearest whitespace
document.querySelector(".textcontainer").innerHTML += "<p>" + document.querySelector(".orgText").value.slice(savedIndex, whitespace) + "</p>";
savedIndex = whitespace; //save the last whitespace
}
i++;
});
}, true);
<textarea class="orgText" style="overflow:hidden;width:100%">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vestibulum sem consectetur, tempor massa quis, bibendum mauris. Curabitur et leo pharetra, condimentum mi vel, gravida mi. Integer pulvinar nibh in laoreet auctor. Donec in tortor in augue maximus fermentum et non erat. Sed auctor feugiat dolor eget efficitur. Vivamus nec urna lorem. Duis lobortis semper tempor. Vestibulum dolor lectus, consectetur.
</textarea>
<div class="textcontainer">
</div>
This is a little testcode. It uses the fact that a textarea has a fixed character width. But that's not the case for most fonts. The above code iterates over every character and checks if it's exceeds the width of the container based upon the detection of a whitespace character.
You can also use the code below to calculate the width of a string.
function getPixelLengthOfString()
{
var tempNode = document.createElement("span");
tempNode.innerHTML = this;
document.body.appendChild(tempNode);
var stringPixelLength = tempNode.offsetWidth;
document.body.removeChild(tempNode);
return stringPixelLength;
}
These pieces of code should point you in a direction of the correct answer.

Text Highlight using Xpath

I am highlighting selected text by using the following xpath and offsets.
Here is an example selection of text I am using to debug.
[{
commonAncestorContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]",
startContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]",
startOffset:0,
endContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]",
endOffset:1,
color: "purple"
}]
This selection above works nicely and highlights the selected paragraph.
Now here is the part I am stuck on, as soon as I add text to the paragraph it fails to highlight the text.
Here is the example with selected paragraph and text, so in theory this should only select the text inside the paragraph that you selected. Changes are marked in bold
[{
commonAncestorContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0]",
startContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0]",
startOffset:288,
endContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0]",
endOffset:330,
color: "purple"
}]
test.html (this uses highlight.show)
function highlightTest() {
$MON.highlight.show([
{
commonAncestorContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0001]",
startContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0001]",
startOffset:0,
endContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0001]",
endOffset:1,
color: "yellow"
},
{
commonAncestorContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0]",
startContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0]",
startOffset:288,
endContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0]",
endOffset:330,
color: "purple"
}
]);
highlight.js(this uses xpath.element)
show: function(selections)
{
for (var i in selections)
{
var selection = selections[i];
var ancestor = $MON.xpath.element(selection["commonAncestorContainer"]);
ancestor.contentEditable = "true";
var col = selection["color"] ? selection["color"] : "yellow";
var range = document.createRange();
var startElement = $MON.xpath.element(selection["startContainer"]);
var startOffset = selection["startOffset"];
var endElement = $MON.xpath.element(selection["endContainer"]);
var endOffset = selection["endOffset"];
range.setStart(startElement, startOffset);
range.setEnd(endElement, endOffset);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
document.execCommand("HiliteColor", false, col);
window.getSelection().removeAllRanges();
ancestor.contentEditable = "false";
}
}
xpath.js
(this returns the corresponding element given the xpath, back to highlight.js)
element: function (expr) {
var resolver = function (prefix) {
if ("xhtml" == prefix) {
return "http://www.w3.org/1999/xhtml";
}
}
var result = document.evaluate(expr, document, resolver, 9, null).singleNodeValue;
return result;
}
HTML
<body>
<p>
1 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tellus ligula, ullamcorper vitae elementum sed, rhoncus a ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et pulvinar augue. Proin non semper mi. Nullam justo velit, vehicula eu congue vitae, tincidunt sit amet urna. Aliquam blandit rutrum dignissim. Donec dapibus nisl arcu, eu eleifend tellus lobortis quis. Praesent quis hendrerit diam. Quisque ultricies lorem et turpis aliquam ornare. Phasellus dolor purus, lacinia eget porta vel, iaculis ac nisl. Phasellus vestibulum faucibus erat sit amet interdum.
</p>
<p>
2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tellus ligula, ullamcorper vitae elementum sed, rhoncus a ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et pulvinar augue. Proin non semper mi. Nullam justo velit, vehicula eu congue vitae, tincidunt sit amet urna. Aliquam blandit rutrum dignissim. Donec dapibus nisl arcu, eu eleifend tellus lobortis quis. Praesent quis hendrerit diam. Quisque ultricies lorem et turpis aliquam ornare. Phasellus dolor purus, lacinia eget porta vel, iaculis ac nisl. Phasellus vestibulum faucibus erat sit amet interdum.
</p>
<p>
3 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tellus ligula, ullamcorper vitae elementum sed, rhoncus a ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et pulvinar augue. Proin non semper mi. Nullam justo velit, vehicula eu congue vitae, tincidunt sit amet urna. Aliquam blandit rutrum dignissim. Donec dapibus nisl arcu, eu eleifend tellus lobortis quis. Praesent quis hendrerit diam. Quisque ultricies lorem et turpis aliquam ornare. Phasellus dolor purus, lacinia eget porta vel, iaculis ac nisl. Phasellus vestibulum faucibus erat sit amet interdum.
</p>
<p>
4 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tellus ligula, ullamcorper vitae elementum sed, rhoncus a ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et pulvinar augue. Proin non semper mi. Nullam justo velit, vehicula eu congue vitae, tincidunt sit amet urna. Aliquam blandit rutrum dignissim. Donec dapibus nisl arcu, eu eleifend tellus lobortis quis. Praesent quis hendrerit diam. Quisque ultricies lorem et turpis aliquam ornare. Phasellus dolor purus, lacinia eget porta vel, iaculis ac nisl. Phasellus vestibulum faucibus erat sit amet interdum.
</p>
<p>
5 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tellus ligula, ullamcorper vitae elementum sed, rhoncus a ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et pulvinar augue. Proin non semper mi. Nullam justo velit, vehicula eu congue vitae, tincidunt sit amet urna. Aliquam blandit rutrum dignissim. Donec dapibus nisl arcu, eu eleifend tellus lobortis quis. Praesent quis hendrerit diam. Quisque ultricies lorem et turpis aliquam ornare. Phasellus dolor purus, lacinia eget porta vel, iaculis ac nisl. Phasellus vestibulum faucibus erat sit amet interdum.
</p>
<p>
6 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tellus ligula, ullamcorper vitae elementum sed, rhoncus a ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et pulvinar augue. Proin non semper mi. Nullam justo velit, vehicula eu congue vitae, tincidunt sit amet urna. Aliquam blandit rutrum dignissim. Donec dapibus nisl arcu, eu eleifend tellus lobortis quis. Praesent quis hendrerit diam. Quisque ultricies lorem et turpis aliquam ornare. Phasellus dolor purus, lacinia eget porta vel, iaculis ac nisl. Phasellus vestibulum faucibus erat sit amet interdum.
</p>
</body>
Log on text selection, gets the selected xpath
38:Selected text: Lorem
44:Collapsed: false
45:Ancestor container: /xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0001]
46:Start container: /xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0001]
47:Start offset: 7
48:End container: /xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[0001]
49:End offset: 12
Update (my problem was)
I had to add
document.designMode = "on";
before i set the hilite color
here is a link to js fiddle
http://jsfiddle.net/E2BbX/11/
XPath indexes are one-based. Try
startContainer: "/xhtml:html[0001]/xhtml:body[0001]/xhtml:p[0002]/text()[1]
and so on.

jQuery Expand/Collapse with header

I have tried using the accordion plugin, but it does not work, and I know there is a simpler solution using pure jQuery.
In essence, I would like it so that when you click a <h2> with the class="expand", it should 'expand' the next div with class="collapse". All the divs should be collapsed by default.
Any help would be much appreciated, thanks in advance!
For testing purposes see this jsFiddle demo.
const $headers = $('.header');
const $contents = $('.content');
$headers.on("click", function() {
const $cont = $(this).next(".content");
$contents.not($cont).slideUp(); // Hide all
$cont.slideToggle(); // Toggle one
});
.header { background: #ddd; cursor: pointer; margin: 0; }
.content{ display:none; }
<h2 class="header">Click to expand and collapse</h2>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean bibendum dolor nec nunc aliquam placerat. Nullam vehicula nibh felis. Nulla tincidunt aliquam nisl nec sagittis. Donec convallis hendrerit nisl, ut lacinia elit sagittis a. Nullam sollicitudin
ultricies nibh, tincidunt adipiscing erat tristique vitae. Sed id ipsum ac ipsum fringilla molestie et sit amet elit. Cras commodo augue id dolor suscipit commodo. Ut varius porta orci, quis dignissim ante adipiscing et. Pellentesque rhoncus purus ut
tortor tempus auctor.</div>
<h2 class="header">Click to expand and collapse 2</h2>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean bibendum dolor nec nunc aliquam placerat. Nullam vehicula nibh felis. Nulla tincidunt aliquam nisl nec sagittis. Donec convallis hendrerit nisl, ut lacinia elit sagittis a. Nullam sollicitudin
ultricies nibh, tincidunt adipiscing erat tristique vitae. Sed id ipsum ac ipsum fringilla molestie et sit amet elit. Cras commodo augue id dolor suscipit commodo. Ut varius porta orci, quis dignissim ante adipiscing et. Pellentesque rhoncus purus ut
tortor tempus auctor.</div>
<h2 class="header">Click to expand and collapse 3</h2>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean bibendum dolor nec nunc aliquam placerat. Nullam vehicula nibh felis. Nulla tincidunt aliquam nisl nec sagittis. Donec convallis hendrerit nisl, ut lacinia elit sagittis a. Nullam sollicitudin
ultricies nibh, tincidunt adipiscing erat tristique vitae. Sed id ipsum ac ipsum fringilla molestie et sit amet elit. Cras commodo augue id dolor suscipit commodo. Ut varius porta orci, quis dignissim ante adipiscing et. Pellentesque rhoncus purus ut
tortor tempus auctor.</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
It hides all opened elements before collapsing the closed one.
And it toggles the open state if the element is opened.
This is simple, just use the below
$('.expand').click(function() {
$(this).next('.collapse').slideToggle(); // or use .toggle() for no animation
});
Fiddle: http://jsfiddle.net/garreh/WQYc7/2/
To be collapsed by default just add the below css:
.collapse {
display: none;
}
Use jQuery, I've updated your Fiddle.
HTML:
<div id="accordion">
<h2 class="toggle">Click to expand and collapse</h2>
<div class="pane">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean bibendum dolor nec nunc aliquam placerat. Nullam vehicula nibh felis. Nulla tincidunt aliquam nisl nec sagittis. Donec convallis hendrerit nisl, ut lacinia elit sagittis a. Nullam sollicitudin ultricies nibh, tincidunt adipiscing erat tristique vitae. Sed id ipsum ac ipsum fringilla molestie et sit amet elit. Cras commodo augue id dolor suscipit commodo. Ut varius porta orci, quis dignissim ante adipiscing et. Pellentesque rhoncus purus ut tortor tempus auctor.
</div>
<h2 class="toggle">Click to expand and collapse 2</h2>
<div class="pane"><br>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean bibendum dolor nec nunc aliquam placerat. Nullam vehicula nibh felis. Nulla tincidunt aliquam nisl nec sagittis. Donec convallis hendrerit nisl, ut lacinia elit sagittis a. Nullam sollicitudin ultricies nibh, tincidunt adipiscing erat tristique vitae. Sed id ipsum ac ipsum fringilla molestie et sit amet elit. Cras commodo augue id dolor suscipit commodo. Ut varius porta orci, quis dignissim ante adipiscing et. Pellentesque rhoncus purus ut tortor tempus auctor.
</div>
</div>
​
Javascript:
<script>
$(document).ready(function() {
$('#accordion h2').click(function() {
var $nextDiv = $(this).next();
var $visibleSiblings = $nextDiv.siblings('div:visible');
$(this).toggleClass('current').siblings('h2').removeClass('current');
if ($visibleSiblings.length ) {
$visibleSiblings.slideUp('fast', function() {
$nextDiv.slideToggle('fast');
});
} else {
$nextDiv.slideToggle('fast');
}
});
});​
</script>
CSS:
.toggle {
background: gray;
padding: 5px;
cursor: pointer;
}
.pane { display: none; }
​.current { background: green }

Categories