how do you deselect a word when clicking on it again? - javascript

How to deselect a word after making it clickable
What I want to do is add (I'm assuming) another JS so when they click on the word again, it'll appear back to normal without the black background?

Rather than setting inline values for your code, just create a CSS class to handle this, then toggle as necessary.
element.onclick = () => {
element.classList.toggle('highlighted');
}
And the class ...
.highlighted {
background-color: black;
color: white;
}
A messier solution would be to add an if/else statement to your onclick function.
element.onclick = () => {
if (element.style.background == '#000') {
element.style.background = '#fff';
}
else {
element.style.background = '#000';
}
}
The .split() function actually removes your spaces, so just make sure you fix that when appending everything back together as well.
inputValue.split(" ").forEach(word => {
const element = document.createElement("span");
element.innerHTML = word + ' ';
...
I've mocked up the class solution at codepen.io.

Related

JavaScript and css: highlight multiple words all with same background

I'm trying to make a basic web application where people can highlight multiple words (i.e., click on the first word, then click on a word further on, and everything will be highlighted, even on another line).
So far I was able to wrap all of the words in tags and set a click event listener to each one which changes it's className to "highlight" which is just background-color:yellow.
The problem is that only the background of that individual word is highlighted, but i want everything in between the two (or more, even on different lines) words to be highlighted.
To complicate things a little more, i also have punctuation and maybe other stuff inbetween the words, which are not surrounded by span tags, but I want everything between the words to have a different background color/ be selected.
I was thinking of just putting the necessary words that are selected in they're own, separate span tag, but then, I'm not sure how to make it dynamically change exactly, and i also want the user to save the selections and then re-select them with a button or something, so that means that one word could be in 2 different phrases, and I'm not sure how one word could be in two different span tags....
So basically: how can I select multiple words in JavaScript including highlighting everything inbetween the two words?
EDIT
There was a request for some of the code I've tried, so I've attempted to simplify the relevant sections:
var h= eid("HebrewS");
var currentPhrase=[];
var equal=false;
var shtikles = [
];
h.innerHTML = h.innerHTML.replace(/([\u0590-\u05FF\"\']+)/g,'<span class="shtikle""">$1</span>');
var words = q("#HebrewS span");
words.forEach(function(item, idx){
shtikles[idx] = {obj:item, id:idx, heb:item.innerHTML, translation:"means "+ idx};
item.addEventListener("click", function(e) {
if(currentPhrase.length == 0) {
currentPhrase.push(idx);
currentPhrase[1]=idx;
equal=true;
}
else {
currentPhrase[1]=idx;
if(currentPhrase[1] < currentPhrase[0]) {
currentPhrase.reverse();
}
if(currentPhrase[0]==currentPhrase[1])
if(!equal) {
equal=true;
} else {
currentPhrase = new Array();
equal=false;
}
else
equal=false;
}
selectPhrase(currentPhrase);
});
function selectPhrase(p) {
for(var i =0;i<shtikles.length;i++) {
if(shtikles[i].obj)
if(p.length > 0) {
if(i < p[0] || i > p[1]) {
if(shtikles[i].obj.className != "shtikle") {
shtikles[i].obj.className ="shtikle";
}
}
} else {
shtikles[i].obj.className = "shtikle";
}
}
for(var i = p[0]; i <= p[1]; i++) {
shtikles[i].obj.className="phrasePart";
}
}
function q(a) {
return document.querySelectorAll(a);
}
function eid(id) {
return document.getElementById(id);
}
Now for the html:
<div style="" id ="HebrewS">today I will show,. you how] to read.. {Maamarim! וחזקת והיית לאיש1, הנה ידוע2 שהמאמר שאמר אדמו"ר (מהורש"ב) נ"ע ביום השביעי3 דחגיגת הבר מצוה של בנו יחידו כ"ק מו"ח אדמו"ר, י"ט תמוז4 תרנ"ג [שמאמר זה הוא סיום וחותם ההמשך תפילין דמארי עלמא5 שהתחיל לומר בי"ב תמוז, יום הבר מצוה] היתה התחלתו בפסוק זה. – השייכות דפסוק זה (וחזקת והיית לאיש) לבר מצוה בפשטות היא, ע"פ הידוע6 דזה שבן שלש עשרה (דוקא) מחוייב במצוות הוא כי אז דוקא נק' בשם איש. וצריך להבין, דמכיון שבן י"ג שנה נעשה איש (ע"פ טבע), מהי ההדגשה לומר (בחגיגת בר מצוה) וחזקת והיית לאיש. וגם צריך להבין, הרי המעלה דבן י"ג שנה היא שאז נעשה בר דעת7, דדעת הוא במוחין, ובפרט לפי המבואר בהמאמר ד"ה איתא במדרש תילים תרנ"ג [שהוא אחד המאמרים שחזר אותם כ"ק מו"ח אדמו"ר בחגיגת הבר שלו]8 שהמעלה דבן י"ג שנה היא שאז יש לו עצם המוחין9, ומהו הדיוק בבן י"ג שנה בהתואר איש שמורה10 על המדות
Now css:
<style type="text/css">
.shtikle:hover{
background-color:yellow;
}
.phrasePart{
background-color: purple;
border: 0px solid black;
}
</style>
I haven't tested the simplified version of the code, but if you try it out should work.
The basic point is :it selects each word individually, but doesn't highlight the stuff between the words (and I don't want to put all of the words in the current phrase into they're own span, because I want to save the phrase and have it selectable later, and also with multiple phrases some words might be in both)
Split everything into single nodes and then work with ranges. Simple implementation might look like below. It works on two clicks (right click removes selections) and is ready to implement click and slide (you'll have to implement mouseenter event listener with some boolean flag). So the point is that after every click id of each node is checked and either it becomes starting point of a range or closes the range with a for loop that adds class for every node in between.
You might then store id ranges somewhere there and activate them on eg. button click.
//EDIT
check edit below, this is totally messy, but I believe it should fit your needs.
const txt = 'this is some word in a wordy place where all words are kind of, well... this is some word in a wordy place where all words are kind of something so: this is some word in a wordy place where all words are kind of, and then -> this is some word in a wordy place where all words are kind of nothing';
let startIndex = null;
let lines = document.querySelector('.lines');
lines.innerHTML = txt.split(' ').map((z, i) => {
return (z.replace(new RegExp("\\w+|\\W+", "g"), (t) => { return /\w+/.test(t) ? `<span data-id="${i}" data-word>${t}</span>` : `<span data-id="${i}">${t}</span>` }));
}).join(' ');
nodes = Array.prototype.slice.call(document.querySelectorAll('.lines span'));
nodes.forEach(z => {
if(z.hasAttribute('data-word')) {
z.addEventListener('mousedown', (e) => {
const id = Number(e.target.getAttribute('data-id'));
if (startIndex === null) {
startIndex = id;
e.target.classList.add('active');
} else {
const range = id > startIndex ? [startIndex, id] : [id, startIndex];
for(let i = range[0]; i<= range[1]; i++) {
(Array.prototype.slice.call(document.querySelectorAll('span[data-id="' + i + '"]'))).forEach(e => e.classList.add('active'));
};
startIndex = null;
}
});
}
});
window.oncontextmenu = function ()
{
startIndex = null;
nodes.forEach(z => z.classList.remove('active'))
return false;
}
.lines {
user-select: none;
}
.lines span {
display: inline-block;
padding:3px;
box-decoration-break: clone;
transition:.2s;
}
.lines span.active {
background: salmon;
box-shadow: 3px 0 0 salmon, -3px 0 0 salmon;
}
[data-word] {
cursor:pointer;
}
<div class="lines"></div>

Javascript Replace HTML tag on a page

I need a Simple script that searches a HTML for a certain code so its not displayed.
My current code only replaces the whole text. But if a person changes 1 item, it can't find it.
Is there a way to make a Wild Card, to find text like:
Thesite
...and if it finds something with
<*yourdomain*</a>
then it replaces the whole <a href....>..</a> with Blank?
My current code is :
function checkLoad(){
if (document.readyState === "complete") {
document.body.innerHTML = document.body.innerHTML.replace(
'<p style="text-align:center;">My Website is redriv</p>',
""
);
} else {
setTimeout('checkLoad();', 500)
}
}
If you want to base this just on the href, you can do it with a CSS rule:
a[href=http://www.yourdomain.com] { display: none; }
To find any href containing 'yourdomain', then use *=:
a[href*=yourdomain] { display: none; }
If you want to include a check of the anchor text as well, you need JS:
function array(a) { return Array.prototype.slice.call(a); }
function check(a) { return /yourdomain/.test(a.textContent); }
function hide (a) { a.style.display = 'none'; }
var selector = 'a[href*=yourdomain]';
var anchors = array(document.getQuerySelector(selector));
anchors . filter(check) . forEach(hide);
No, don't use regexp for this or any other HTML manipulation.
RegEx would be the easiest solution here, something like <a.*yourdomain.*?\/a> should do the trick. It will remove anchor tags that contain yourdomain inside them (both as attributes and attribute values - you didn't specify how accurate you want it, so everything gets triggered). See it here:
var html = 'ThesiteGood URLGood URL';
var replaced = html.replace(/<a.*yourdomain.*?\/a>/, '');
document.getElementById('f').textContent = html;
document.getElementById('r').textContent = replaced;
p {color: #777}
span {color: black}
<p>Sample markup: <span id="f"></span></p>
<p>After RegEx: <span id="r"></span></p>
Used one-line sample markup on purpose so you can see it won't touch the other anchors.
So your full code would be:
function checkLoad(){
if (document.readyState === "complete") {
document.body.innerHTML = document.body.innerHTML.replace(/<a.*yourdomain.*?\/a>/, '');
} else {
setTimeout('checkLoad();', 500)
}
}

How can I disable hover state on mousedown or on dragstart?

I have a list of nodes (divs) that can be re-arranged via drag-and-drop. Sample code is listed below. Normally, I want to highlight the hovered node with one class (for simplicity, let's say blue background, ":hover" pseudo class), but when a node is dragged I want to highlight with a different class (red, "dragged" class).
I'm having two problems with this:
In dragstart() I apply "dragged" class to the node, but it doesn't take the effect immediately. I can change the background color by modifying style.backgroundColor directly, but I was hoping there's a more straightforward css solution to redraw a node after adding a class.
Hover state gets messed up once I change the order of nodes. As you can see, if you drag node from top to bottom hovered state follows that node (masking "dragged" class), but if you drag from bottom to top hovered state jumps to the original index (index of the node that received mousedown) and now "dragged" class shows up.
I tried various things but to no avail. As far as I can tell there's no way to remove or suspend :hover pseudo class, and I can't figure out if there's a way to force hover on a certain node (I tried simple things like setting focus to make the node active).
The second problem is the real issue, but I would appreciate if anyone can comment on how to resolve both issues. Thanks in advance.
<html>
<head>
<style>
.node {
border: 1px solid gray;
height: 26px;
width:300px;"
}
.node:hover {
background-color: #4444ff;
}
.dragged {
background-color: #ff4444;
}
</style>
</head>
<body>
<div id='cont' style="width: 300px;"></div>
</body>
<script>
(function(){
var html = '';
for (var i = 1; i < 11; i++) {
html += '<div id="' + i + '"draggable="true" ondragstart="dragstart(event)" ondragenter="dragenter(event)" ondragend="dragend(event)" class="node">item' + i + '</div>';
}
document.getElementById('cont').innerHTML = html;
})();
function dragstart(event) {
event.target.className += ' dragged';
event.dataTransfer.setData('text/html', event.target.id);
}
function dragenter(event) {
var sourceId = event.dataTransfer.getData('text/html');
var targetId = event.target.id;
if (targetId === sourceId) {
return true;
}
var sourceNode = document.getElementById(sourceId);
var targetNode = document.getElementById(targetId);
var sourceIndex = Array.prototype.indexOf.call(sourceNode.parentNode.childNodes, sourceNode);
var targetIndex = Array.prototype.indexOf.call(targetNode.parentNode.childNodes, targetNode);
if (targetIndex > sourceIndex) {
targetNode.parentNode.insertBefore(targetNode, sourceNode);
} else {
targetNode.parentNode.insertBefore(sourceNode, targetNode);
}
}
function dragend(event) {
event.target.className = event.target.className.replace(' dragged', '');
}
</script>
</html>
First issue :
In the CSS, add !important at the end of your .dragged's background-color.
Second issue :
Apparently, Chrome have an odd behaviour with event.dataTransfer.setData()
I just tested by replacing setData('text/html'... by setData('Text'...
and it actually does work in my Chrome (36 osx).
Of course you'll have to change the getData() parameters to "Text" too
Edit from comments
Due to Chrome restrictions about dataTransfer.setData() I wasn't able to make a working fiddle for last code.
But it does work for me in a standalone page.
The easiest solution would be to use a global variable that will store your element.
var draggedItem;
function dragstart(event) {
event.target.className += ' dragged';
draggedItem = event.target;
}
function dragenter(event) {
var sourceId = draggedItem.id;
var targetId = event.target.id;
...
Here is a working fiddle : http://jsfiddle.net/2Kgvh/
This was turning into a css and cross-browser nightmare, so I resorted to jQuery and its Sortable Widget implementation.

Changing color of letters one by one in a html text when hovering

Now that my brain aches after trying by myself and searching all over without finding any answer.
i ask you.
I am trying to change the colors of the single letters in a text which is contained inside a <h5>Hello</h5> When the pointer is hovering over each single one, I can manage this by spamming alot of <span></span> and put letter by letter inside each <span></span>, then using CSS to just change color when hovering.
BUT
I want to do this by using Javascript.
Here i've accomplished extracting every single letter in a <h5>, but I am not getting them to change color when I hover each one of them.
$('h6').ready(
function () {
var T = $('h6').text();
for (letters in T) {
$(T[letters]).hover(
function () {
$(T[letters]).toggle("color", "red");
})
}
});
So with the great help of GolezTrol i achieved victory doing what i wanted to do!
Though i use Css instead of the javascript to handle the hover =)
result - java - syntax:
$(function () {
$('h2').each(
function () {
//Extract text from html, and attach it to "Txt" variable.
var Txt = $(this).text();
//Empty var-string waiting for loop.
var Gtxt = '';
//Loop through text to add <span id="green> on every letter.
for (i in Txt) {
//add letter by letter to Gtxt ( <span id="green"> letter </span> )
Gtxt = (Gtxt + '<span id="green">' + Txt[i] + '</span>');
//IF for Newline on period.
if (Txt[i] == '.') {
Gtxt = (Gtxt + '<br>');
}
}
//Add processed text to Html $('h2')
$(this).html(Gtxt);
});
});
CSS:
#green{
color: "color"
}
#green:hover{
color: "green"
}
var T = $('h6').text();
That line just gets the text of the element into a string. So the code after that, if it would work at all, just works on the in-memory string and won't be visible in your browser.
To make this work, you will have to do the same you did by hand: add a span around each of the letters and give each span a different color.
You can do this with the following HTML: ;)
<h6>Hello world</h6>
Javascript to embed all letters in a span inside every h6 in the document.
// Function that embeds each letter with a span. Maybe this can be done
// simpler, but it works.
$(function()
{
$('h6').each(function(){
var txt = $(this).text();
var html = '';
for (t in txt)
{
html = html + '<span>' + txt[t] + '</span>';
}
// Put the generated HTML back in the document.
$(this).html(html);
});
});
Javascript to handle the hover:
Of course you can do this by simply declaring CSS as well if you are just toggling colors, but if you want to have more complex effects or random colors, this might be your Javascript solution:
// Attaches hover events to each span within a h6. Using document.on, this
// event will work for any span this is or will be in the document.
$(document).on('hover', 'h6 span', function(event){
// 'hover' is a shorthand. The event is linked to mouseenter and mouseleave, so
// you'll have to check event.type to see which one it is.
if (event.type == 'mouseenter')
$(this).css('color', 'red');
else
$(this).css('color', 'blue');
});
JS Fiddle:
http://jsfiddle.net/KdzQ7/

Show/Hide <span> tags

I want to hide tags with a specific id or class using javascript. I have kept a single ID and CLASS for every span tag called "ch"(adding different ID and CLASS to each span is very difficult for me)
I have a checkbox which will toggle the visibility of the .
Now here's the problem:
- I click the checkbox once, everything hides fine
- Click it the second time(to show the again), all the content in the tag goes to the left of the screen.
- Click it again and everything goes berserk
I want the code to show/hide the span tags when clicked and when the spans are hidden, I don't want that line to remain there. I want that entire line to be removed, and when it's set for visible again, I want these lines to reappear. I hope someone can help me. Below is the code:
function sh_chords() {
tmp_log += "sh_c|";
var b = document.getElementById("showing_chords").checked;
for (i = 1; i <= lcnt; i++) {
el = document.getElementById("ch");
try {
if (!b) {
el.style.color = "black";
el.style.cursor = "default";
$(".ch").hide();
} else {
el.style.color = "#0000FF";
el.style.cursor = "pointer"
$(".ch").show();
}
} catch (d) {}
}
}
Since you are using jquery, you can use it's helper function which is specifically for toggling visibility.
$('.ch').toggle( $('#showing_chords').prop('checked') );

Categories