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)
})
Related
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>
hi i would like to select the parent div of currently placed cursor in a contenteditable div.
the process is, there are multiple contenteditable div in a page. i'd like to select the div which the caret/ cursor is currently positioned. so that using jquery i could change the css.
following is my html code of the div:
<button id="changer">change color</button>
<div id="container">
<div class="section" contenteditable="true">
<p>this is my editable paragraph</p>
</div>
<div class="section" contenteditable="true">
<p>this is my editable paragraph 2</p>
</div>
</div>
following is my jquery code so far:-
$('#changer').click(function(){
document.activeElement.css({'background':'black'});
});
but this gives me the error :- Uncaught TypeError: undefined is not a function
edit:-
the process is when the user clicks a button a color palette lightbox will appear. on click of any of the color on the color palette. the jquery is going to select the currently focused contenteditable div. and change the css.
i want to know how to select the currently focused contenteditable div using jquery.
So the code below console logs the text inside the contenteditable div which is focused. if you write $(this) inside the event handler it will reference the currently div focused
$('[contenteditable="true"]').focus(function(){
console.log($(this).text()); // for example, do whatever you please here
// you said you want to find the parent div of the element focused
var $parent = $(this).parent();
// now $parent is a reference of the parent div of the focused element
});
The tricky thing is that when the user clicks the button, the contenteditable is not focused anymore. so let's make a variable where we store our last focused contenteditable div , and when the user clicks a button, the changes will be made on that very variable.
like so :
var lastFocused;
$('[contenteditable="true"]').focus(function(){
lastFocused = $(this);
});
$('#changer').on('click', function(){
console.log(lastFocused);
lastFocused.css('background-color', 'red');
})
see codepen : here
So I think what you are trapped is how to get the div[contenteditable] which was focused.
The idea is to store the item when it was trigger by a focus event.
$(function() {
var $focus_item = null;
$('[contenteditable]').focus(function() {
$focus_item = $(this);
});
$('#changer').click(function(){
$focus_item.css({'background':'black'});
});
});
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.
I have an ASP.NET repeater, which contains 3 divs inside the ItemTemplate.
Each div, in turn has a number of html elements. I would like to reference an element in the first div (the 3 divs are placed vertically and parallel to each other from left to right).
I have a button in the 3rd div. When pressed, I want to be able to select an element which is contained within the first div.
This is the code I've got so far:
$("#editButton").click(function () {
var nameBox = $(".nameBox", $(this).parent());
});
I'm not really sure how to select the element within the first div though. Could anyone kindly suggest some code please?
Just get the siblings and find the element with the class name.
Assuming your markup is like this:
<div>
<div class="namebox">found me</div>
</div>
<div>
</div>
<div>
<input type="button" id="btn" value="click"/>
</div>
$("#editButton").click(function () {
var nameBox = $(this).parent().siblings(':eq(0)').find('.nameBox');
});
jsFiddle Example
Why dont you assign an id to the div? Or use the first selector http://api.jquery.com/first-child-selector/
I am working with Flexigrid plugin with JQuery. Ok so I have a div with two span elements, they would contain the text/display text for the buttons that flexigrid provides. The problem is, there is no mechanism to add ids to those buttons, except for adding different text.
<div class="tdiv2>
<div class="fbutton">
<div>
<span class="view" style="padding-left: 20px;">Add</span>
</div>
</div>
<div class="fbutton">
<div>
<span class="view" style="padding-left: 20px;">Delete</span>
</div>
</div>
</div>
This is how the buttons are arranged. So onclick of that button, I get the text inside the span, as Add and Delete. Now I want to add a class tag to that span, to differentiate between the active button and the other one.
So I came up with the idea, that if I could get span-text that matches to the text being returned, I could add the class to that span.
But when I do
alert($('.tDiv2 span').html());
I am only getting the text of the first span and not the second one. Could somebody help me with getting the html of both spans and not just the first one.
Try this >
$('.tDiv2 span').each(function(index, el) { alert($(el).html()); });
You need each.
$('.tDiv2 span')each(function(node){ alert(node.html()); });
However, I would like to point out that this approach is likely to cause accessibility problems for screen reader users. If you absolutely must re-invent buttons for some reason, then use ARIA attributes so that your blind visitors have some hope of getting it to work right.
jQuery automatically selects the first element in a series if you try to get a property like html or text from it. to get the second (or any number) try:
alert($('.tDiv2 span').eq(1).html()); //returns 2nd element's html content
You can substitute any 0 based index in for 1.