How to get the <p> where the cursor is in? - javascript

I have a DIV element with contenteditable="true".
As i write text into this div i get multiple elements.
Here is an example link.
Question
How can I get the element which contains the cursor?
And it would be extra nice to be able to obtain the index position of the cursor (in a cross-browser supportive way).
Thanks!
Updated
By cursor index position, i don't necessarily mean X, Y coordinates. I mean string index position of a sentence, for instance.

Do you need something like that?
HTML
<section contenteditable="true" id="editable">
<h2>Go ahead, edit away!</h2>
<p>Here's a typical paragraph element</p>
<ol>
<li>and now a list</li>
<li>with only</li>
<li>three items</li>
</ol>
</section>
JS Code:
$('#editable').mousemove(function(e){
console.log(e.target.nodeName);
console.log(e.pageX + ", " + e.pageY);
});
NOTE: You could also change mousemove event to what ever you want, as an example: click, hover etc.

I think usual nodes (basically non input nodes) do not have a focused flag. But before you can write into an element you have to do a click into it. You can hook into the click event to get the node.
(e.g. with jQuery:
$('document').on('click', function() {
console.log('you have clicked on: ', $(this));
});
)

You could add onMouseOver attributes to containers, making them run a code that changes some variable for example. You could use also onMouseOut attributes to remove the value from the variable when the mouse exits the container.
This is a sample of that code:
HTML:
<!doctype html>
<html>
<head>
<title>Example page</title>
<script src="your/script/path.js"></script>
</head>
<body>
<p id="1" onMouseOver="setParagraph(this)">Example paragraph 1</p>
<p id="2" onMouseOver="setParagraph(this)">Example paragraph 2</p>
</body>
</html>
Javascript:
var mouseOverParagraph,
setParagraph = function (el) {
'use strict';
mouseOverParagraph = el.id;
}

I would imagine doing something like:
var hovered;
$('div[contenteditable] *').bind('mouseenter.editable', function(e) {
e.stopPropagation();
hovered = this;
console.log(this);
console.log($(this).index());
console.log(e.pageX);
console.log(e.pageY);
});
Just have a global variable that gets changed upon hover, stopPropagation() to make sure no parent element "takes the credit", and you get to play with this, e.pageX, e.pageY with ease.

You can use the jQuery focus selector to find which element has the cursor focus:
var focusedP = null;
$(document).on("focus","p[contenteditable]",function(){
focusedP = $(this);
})
$(document).on("blur","p[contenteditable]",function(){
focusedP = null;
})
JSFiddle
As for cursor position within the element, I can't say, but you might be able to work out what character was originally clicked by capturing the mouse click and getting the relative coords. With a static font size and line height, you could calculate from the coords what line and character it was at.

Related

How to get the target element for an 'selectionchange' dom event

I find myself in a situation where I want to get the target element that triggered the selectionChange dom event.
But judging by https://developer.mozilla.org/en-US/docs/Web/Events/selectionchange, it seems that the element in e.target is always the document object in the normal (non-input, non-textarea) case.
So does that mean I will have to manually call window.getSelection, and figure out the current cursor location and find the dom node that way?
Does anyone know of a short cut? or some working example would be nice.
If your element can become an active element, use document.activeElement to get the element we're selecting inside of. This will work with textareas, inputs, and on elements whose tabindex is set.
// NOTE: activeElement can only be found on selectable elements!
document.addEventListener('selectionchange',function(){
document.getElementById('currentTag').innerHTML = document.activeElement.tagName;
});
#currentTag{
font-weight:bold;
}
<textarea>This is sample text you can replace and move your cursor within. Whee!</textarea>
<br><input type="text" placeholder="Input">
<p tabindex="0">P tag text is the best tag text. <span color="blue">Unless you have a span.</span></p>
<ol tabindex="0">
<li tabindex="0">Item 1</li>
<li tabindex="0">Item 2</li>
</ol>
<p id="currentTag"></p>
You can use document.selection to get what is currently selected.
Example taken from http://help.dottoro.com/ljixpxji.php
<head>
<script type="text/javascript">
document.onselectionchange = OnChange;
function OnChange () {
var range = document.selection.createRange ();
if (range.text.length == 0) {
alert ("The current selection is empty");
}
else {
alert ("The contents of the current selection are\n" + range.text);
}
}
</script>
</head>
<body>
Select this text on this page!
</body>
--EDIT--
As pointed out by #user1017674 this code does not work in chrome, after a little bit of research I found document.selection should only be used in IE < 9. It seems that window.getSelection() is still going to be the best way to get it.
Ref. Does chrome supports document.selection?

dragging child element from parent element

is it possible to drag child element from parent element without parent element is overflowing?, its like i want to create a drag and drop event out from parent element but it keeps on overflowing, if its not possible? what else can i do?
current example code:
<div id="parent">
<div id = "child">Drag me out from parent!</div>
</div>
<script>
$("#child").draggable();
</script>
Ive tried different revisions but it doesnt work well, Im looking forward to this, thanks!
Maybe you can create your own draggable
$('#child').on('mousedown',function(){
$('child').css('position','fixed');
var evt=setInterval(followMouse, 50);
$('child').on('mouseup',function(){
clearInterval(evt);
$('child').off('mouseup');
});
});
function followMouse(){
// mousePosX & Y must be a string ex: 345px
$('child').css('left',mousePosX
'top',mousePosY
);
}

jQuery: if $(this) or another element blurs, then

I want to trigger a function if either the currently active element $(this) or another predefined element (e.g.: div#tooltip) blurs. However so far I've not found out how to do this. I've tried:
$(this).add('div#tooltip').live('blur', function(){
$('div#tooltip').hide();
});
Imagine that $(this) would be an input field, for example, and the predefined second element would be a tooltip div and that I would want the tooltip to hide if one of those blurs.
EDIT:
The div#tooltip contains an anchor, which should not make the div#tooltip hide if it's being clicked.
EDIT 2:
Okay, here is a more accurate explanation of my problem. I've got the $.fn.tooltip function which I apply to various text-inputs which have variable class names and id's. Therefore, this input can only be referred to as $(this) within the function.
Secondly I have the tooltip div, which is created by the function. This div goes by the ID #tooltip. This tooltip / div can contain some other elements such as anchors.
The tooltip is shown automatically when the input-field (this) is clicked. Once it's closed it won't be shown again, even if the input-field will be focused again.
What I'm trying to do is:
The tooltip must be removed when the text-input loses it's focus
EXCEPT if the cursor is within the tooltip / div or if an element within this div is being clicked.
Anyone?
Like this: http://jsfiddle.net/uu3zX/7/
HTML:
<input type="text" class="with-tooltip">
<span class="tooltip">?<a style="display:none" href="#">The tip</a></span>
JavaScript:
$('.with-tooltip').on('focus', function(){
$(this).next().children().show();
});
$('.with-tooltip').on('blur', function(){
$(this).next().children().hide();
});
$('.tooltip').hover(
function(){
$(this).children().show();
},
function(){
$(this).children().hide();
}
);
UPDATE
Added alternative solution to fit OP requriment to use this
Borrowing from IntoTheVoid's fiddle: You should wrap the input and the tooltip in a container div (or some other container element) to do this in one line:
$('.tooltip, input').on('mouseout', function(){
$(this).parent().children('.tooltip').hide();
}).on('focus mouseover', function(){
$(this).parent().children('.tooltip').show();
});
http://jsfiddle.net/mblase75/uu3zX/5/

Prevent "bubbling"? [duplicate]

This question already has answers here:
jquery stop child triggering parent event
(7 answers)
Closed 8 years ago.
I am not sure this is really bubbling, I will explain.
I have this:
<div>
<div>
text here
</div>
</div>
How to bind an on click event so that it will affect only the enclosed div? If I set it like this:
jQuery('div').bind('click', function() {
jQuery(this).css('background','blue');
});
it makes blue all the divs. If I add false as the third argument(prevent bubbling) to the bind function it does nothing.
How can I solved this?
http://api.jquery.com/event.stopPropagation/
Add event.stopPropagation(); inside the hander.
(It might be better, though, to assign an ID or class to the nested DIV so you can be sure it's the only one affected.)
You should really use identifiers like IDs or classes, but for your example, you could do this:
jQuery('div > div').bind('click', function() {
jQuery(this).css('background','blue');
});
...which will bind the handler to any div that is a direct descendant of another div.
So either make your initial selection specific to the element(s) you want to affect, or use event delegation, placing a handler on an ancestor, and testing for the element you want.
Delegation example: http://jsbin.com/ehemac/edit#javascript,live
<div id="container">
<div class="outer">
<div>
text here
</div>
</div>
<div class="outer">
<div>
text here
</div>
</div>
</div>
jQuery('#container').delegate( '.outer > div', 'click', function() {
jQuery(this).css('background','blue');
});
This uses the delegate()[docs] method that places a handler on the ancestor with the ID #container.
The first argument to .delegate() is a selector. Any elements that are clicked inside #container will have that selector compared against the element clicked. If the selector matches, the handler will be invoked.
http://jsfiddle.net/vol7ron/WzSkj/
Targeting the last descendant
Credit to Patrick DW:
jQuery('div:not(:has(div))').bind('click', function() {
jQuery(this).css('background','blue');
});
This should be all you need as it will look at all div and find those that don't have child divs (thus, they will be the last descendant of that element type. You could further filter this to make sure they have a parent that is a div, if you wanted to exclude those divs that are standalone.
Older Answer:
This is not by any means meant to be a complete/robust plugin. It serves as only an example of how to target the last element in a chain. See the revision history for a way to do it w/o the plugin. This should be modified if you wish to use it for production.
Plugin:
(function($){
$.fn.lastDescendant = function(el){
var found = jQuery(el + ':first').siblings(el).andSelf();
var prev, curr;
var stack = this;
for (var i=0,n=found.length; i<n; i++){
curr = found.eq(i).find(el);
while (curr.length){
prev = curr;
curr = curr.find(el);
}
stack = stack.add(prev);
}
return stack;
};
})( jQuery );
Example Call:
jQuery.fn.lastDescendant('div')
.click(function(){
jQuery(this).css("background","#09c");
});
Note:
this will not select the first (ancestor) element. If you want to select that as well, you could wrap the whole thing in a new div, and then do the above.
if I were to make this a production plugin, I would include checking the parameter, and allow you to be able to pass in an object and a starting point (so that siblings are not selected)
To fix this just use a more specific selector
jQuery('div > div').bind('click', function() {
jQuery(this).css('background','blue');
})
The best way to solve it would be to give your inner div an identifiable feature such as a class, e.g., <div class="inner"></div>.
Alternatively, change your selector:
$('div > div').click(function() {
$(this).css('background', 'blue');
}
try giving the inner div an id tag and refer to it...
<div><div id=foo>text goes here</div></div>
...
$('#foo').bind('click', function() {
$(this).css('background','blue');
});
HTH
-- Joe

jQuery: how to get the innermost dom element I'm hovering over, globally for the whole document body?

I'd like to detect mouse movements over the whole document body, and be able to tell exactly which part of the DOM I'm hovering over. By "Which part" I mean the innermost DOM element that the mouse is currently over.
I could bind a hover to the whole document body, but then the $(this) would give me the $(body), not the innermost element. Or I could iterate over the whole DOM recursively and bind a hover to each elements, but that would be a serious overkill IMO.
Is there an easy way to achieve this?
jQuery's event.target should do the trick:
$("body").click(function(event) {
console.log($(event.target));
});
Based on Jasie's suggestion, I ended up using the following code:
var currentNode = null;
$('body').mousemove(function(event) {
if ($(event.target) !== currentNode) {
currentNode = $(event.target);
console.log(currentNode);
}
});
:) think of all the elements, Like:
<div>this is div</div>
<span>this is span</span>
<p>This is p</p>
<a>this a</a>
<ul><li>this is ul li</li></ul>
<ol><li>This is ol li</li></ol>
<img src="" />
<textarea id="text"></textarea>
The textarea is to show you the result only.
jQuery("div,span,p,a,ul,ol,img").hover(function(){
jQuery("#text").append(jQuery(this).html() +
"<br />");
},function(){
}
);

Categories