I have the following html element:
<h1>Some text</h1>
I need to detect a click and recognize whether it landed on the text part or the blank part of the element.
To preserve consistency of the rest of the app I cannot change the display of this element to inline or inline-block.
I also cannot modify the inner html of this element so splitting it into two <span> elements is not an option either.
The text inside this element is not constant and is in fact editable.
Can I detect a click only on the visible (text) part of this heading?
QUESTION "I also cannot modify the inner html of this element so splitting it into two elements is not an option either." does this mean after the fact or before the fact? i.e is it that you cannot alter the HTML or that you can't go in and mutate the HTML via JS ?
Current Solution:
I parse all elements with the .clickable identifier, remove & rebuild their text contents and place spans around them - this way i can add click listeners to the individual text/span elements - giving me access to the text itself.
const clickables = document.querySelectorAll('.clickable')
clickables.forEach(el => new Clickable(el))
function Clickable (el) {
const _handleClick = ({target}) => console.log(target.innerHTML)
const texts = el.textContent.split(/\s/)
el.innerHTML = ''
texts.forEach(t => {
const span = document.createElement('span')
span.innerHTML = `${t} `
span.addEventListener('click', _handleClick)
el.appendChild(span)
})
}
<h1 class="clickable">Some text</h1>
<h2 class="clickable">Some! more! text2</h1>
By the use of Jquery you can use the .click function to know if the h1 tag is clicked.
$('#test').click(function(){
alert("Clicked!");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id='test'>TEST</h1>
Related
This question already has an answer here:
How to get the selected element inside a contenteditable element
(1 answer)
Closed 10 months ago.
I have a sample at Finding currently focused span in an editable div.
The editable div i.e. a div having the attribute contenteditable="true", contains 3 different spans with each span wrapped in a div. A user could position the cursor in any one of the three spans. My goal is to find out which span is being edited when user clicks on a span content to start editing or types into it. I would like this to work on desktop or mobile devices.
I tried getting the span using document.activeElement as you can see in my code sample, but it gets the editable div and not the current span. I was looking for a JavaScript solution to this problem.
Question:
How would I get the id of span element whose text is being edited using JavaScript?
Html code
<div id="input" contenteditable="true" onfocus="findCurrentSpan(this)">
<div>
<span id="first">first span</span>
</div>
<div>
<span id="second">second span</span>
</div>
<div>
<span id="third">third span</span>
</div>
</div>
<p id="info" style="color:green">
</p>
Javascript code
function findCurrentSpan(editor) {
var element = document.getElementById("input");
var currentSpan = document.activeElement;
document.getElementById("info").innerHTML = "Active element's id is " + currentSpan.id;
}
The Problem is, that you are going to select the active element from the whole Page, that's why it is called document.activElement.
Have a look a this SO Question Get and set cursor position with contenteditable div
In your example findCurrentSpan(this) this is referring to the function findCurrentSpan() so this.id will have the value input.
<div id="input" contenteditable="true" onfocus="findCurrentSpan(this)">
To solve your problem, I recommend you bind an onfocus event to all of input's children (explanation on how the onfocus event works in javascript).
This is how you select all the span elements inside input:
var children = document.getElementById("input").querySelectorAll('span');
After selecting the elements you want to bind an event to. Use a loop to bind an event to all the elements. As far as I know span doesn't implement a focus state so we will have to use click.
children.forEach(function(e) {
document.getElementById(e.id).addEventListener("click", findCurrentSpan)
})
The code will look like this:
function findCurrentSpan() {
console.log(this.id)
document.getElementById("info").innerHTML = "Active element's id is " + this.id;
}
var children = document.getElementById("input").querySelectorAll('span');
children.forEach(function(e){
document.getElementById(e.id).addEventListener("click", findCurrentSpan)
})
I want to see if there is a way to define the second div without defining an ID for the element or without using an attribute, and perform the append operation inside it, for example, to say that the p element should be appended inside the second div without using id And any other attribute, let's mention the second div.
More details are in the code *
function createEle() {
var c = document.createElement('p');
// In this section, I want to point to that div and use append without using an ID or any other attribute
return ?
}
createEle();
<section>
<div>
<div>I want the p tag to be appended in this div</div>
</div>
</section>
You can use a selector string instead, with only tag names. Eg section > div > div will select the nested div (it'll select a div which is a child of a div, which is a child of a section):
function createEle() {
const inner = document.querySelector('section > div > div');
inner.appendChild(document.createElement('p')).textContent = 'foo';
}
createEle();
<section>
<div>
<div>I want the p tag to be appended in this div</div>
</div>
</section>
<div class='one'>THis is first div</div>
<div class='one'>THis is the second div</div>
So I want to get the text inside these two divs one by one. So with each loop it only gets the current element of the div.
const searchResult = selector("div[class='one']")
.each((index, element) => {
let selection = selector(element);
return selection.text();
})
.get(index);
So with each div with class="one", I want to return the text of that div only, above is my current code, but it doesn't seem to work, it seems that the .get() isn't right.
I think you want map:
$(div.one).map((i, div) => $(div).text()).get()
I'm trying to switch the positions of two divs with an onclick event.
The divs have the same basic format (width, height), but an additional class and id change the way they look.
So, I have two functions that successfully change the id and class names, but there is no visual change.
Here they are:
function whenClickedFilled(){
console.log("filled");
this.firstElementChild.id = "empty";
this.firstElementChild.className = "puzzlepiece emptyDivClass";
}
function whenClickedEmpty(){
console.log("empty");
this.firstElementChild.id = "filled";
this.firstElementChild.className = "puzzlepiece";
}
I'd like to know what the best way is to alternate between classes/ids onclick.
Here is my js fiddle.
I think what you're really looking to do is not swaping the class and id, but swap the elements themselves. This will make sure the numbers contained within the div's is also transfer with the swap.
You still need to implement the logic checks to see if the element should be able to swap with the empty block and there looks like theres a bug when you click empty space itself. But, this should get you on the right track. I recommend placing a debugger statement to step through the code with dev tools open. It will help understand whats taking place. Good luck.
function whenClickedFilled(){
console.log("filled");
//Get the div element and parent
//Then determine the parent of the empty div
var clickedDiv = this.firstChild; //this refers to the TD clicked, get the child div element
var clickedDivParent = this; //this is TD
var emptyDivParent = emptyDiv.parentElement; //stored the empty div reference into a global, retrieve the parent as this could change
//Remove the empty and clicked div's from their container
emptyDivParent.removeChild(emptyDiv)
clickedDivParent.removeChild(clickedDiv);
//Add the elements back to the containers but swapped
clickedDivParent.appendChild(emptyDiv);
emptyDivParent.appendChild(clickedDiv);
}
http://jsfiddle.net/tWrD2/
I'm trying to switch the positions of two divs with an onclick event
If you want to swap two adjacent nodes, you can do something as simple as:
function swapAdjacent(el0, el1) {
el0.parentNode.insertBefore(el1, el0);
}
If you want to swap any two elements in the DOM, you can do something like:
// Swap the postion in the DOM of el0 and el1
function swapElements(el0, el1) {
// Create a temp node that can replace el0
var tmp = el0.cloneNode(false);
// Replace el0 with tmp
el0.parentNode.replaceChild(tmp, el0);
// Replace el1 with el0
el1.parentNode.replaceChild(el0, el1);
// Replace temp node with el1
tmp.parentNode.replaceChild(el1, tmp);
}
and some test markup:
<div id="d0">div 0</div>
<div id="d1">div 1</div>
<button onclick="
swapElements(document.getElementById('d0'), document.getElementById('d1'));
">Swap d0, d1</button>
<button onclick="
swapAdjacent(document.getElementById('d0'), document.getElementById('d1'));
">Swap adjacent</button>
Of course the two elements to swap must be consistent with the surrounding elements, e.g. you can't swap an option element with a div and expect everything to work, but you can probably swap a span with a div.
If you want to swap elements by clicking on one or the other:
<div id="d0" onclick="swapElements(this, document.getElementById('d1'))">div 0</div>
<div id="d1" onclick="swapElements(this, document.getElementById('d0'))">div 1</div>
I found a nice solution provided by fuell when I was searching fo an actual html swap:
<div id="div_1">THIS IS DIV 1</div>
<div id="div_2">THIS IS DIV 2</div>
Go Swap!
$(document).ready(function() {
$(".go-swap").click(function() {
$("#div_1").removeAttr("style");
$("#div_2").removeAttr("style");
var tmp = $("#div_1").html();
$("#div_1").empty().append($("#div_2").html());
$("#div_2").empty().append(tmp);
});
});
My html is like this, I can only identify the div's class, there are no span' ids. I need to replace one href text and one image with some other text within those spans.
<div class ="myclass">
<span style="vertical-align:middle;">
</span>
<span style="vertical-align:middle;">
</span>
<span style="vertical-align:middle">
<span class="myspan">
<a href="http://testlink3">
<img title="test" class="imglink"></a>
</span>
</span>
<span>
Text - *This text needs to be replaced*
</span>
</div>
in the above code, I need to replace the img within the third span with a clickable text (which should take us to url) and the text within fourth span to a new text (keeping the url the same).
How can I get identify these specific spans when they are missing ids/classes?
We have 3 different things to do here:
How to replace the content inside a given element
This can be done very quickly:
$("selector").html("New text, same href");
Replace a given element with another
This can be done this way:
$("selector").replaceWith("<a href='somewhere.html'>I replaced an Img</a>");
Selecting the DOM elements
When you don't have an ID, nor a CSS class for your element, but you do know its position within another element plus some info about the element (like tagName), you can select the parent element and specify a relative position.
var myElement = $("parentElement").find("tagName:eq(position)");
Remember that this kind of selector ( "tagName:eq(position)") is zero indexed, so if you want to grab the third element, you need to tell jQuery tagName:eq(2).
So, let's say you parent element (not given in the question) is a div with a parent CSS class.
First thing you want to do is select this div.
var parent = $(".parent");
Then you want to find the Img within the third span.
var myImg = parent.find("span:eq(2)").find("img");
Now you can replace this element with the whatever you want
myImg.replaceWith("<a href='somewhere.html'>I replaced an Img</a>");
Note that jQuery allows you to pass HTML elements as a plain string.
Finally, you need to change the text inside the fourth span. This can be accomplished this way:
parent.find("span:eq(3)").find("a").html("New text, same href");
You could use document.querySelector to select an a based on the href:
document.querySelector("a[href='http://link4']").innerHTML = "The text you want to put in"
Since you're open to jQuery, this works too:
$("a[href='http://link4']").text("The text you want to put in")
var s = document.getElementsByTagName('span');
var i = spans[2].firstChild.children[1]; // here you find your img
i.parentNode.appendChild(<<your new text element>>);
i.parentNode.removeChild(img);// remove the image
var a = spans[3].firstChild; // here is your href
a.innerHTML = 'your new text';
You could use :nth-child() selector to select from the div you can identify.
More on :nth-child(): http://api.jquery.com/nth-child-selector/
Then select the img tag from the child span you found.