Detect if cursor is within li on content editable - javascript

I have working code that inserts <br> when you hit enter in a content editable div. (Browsers have various defaults of inserting <div> or <p> instead)
The problem is that it kills the default behavior of hitting enter to add another list item when building ordered or unordered lists. So my question is, can you detect if the text insertion point is within a list item, and if so, disable the javascript that deals with the enter key?
Working code: http://jsfiddle.net/kthornbloom/RCdhS/

You need to do some DOM tree checking on the node containing the selection. Here's a demo that will work in all major browsers:
http://jsfiddle.net/CeMxs/2/
Code:
function isSelectionInsideElement(tagName) {
var sel, containerNode;
tagName = tagName.toUpperCase();
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
containerNode = sel.getRangeAt(0).commonAncestorContainer;
}
} else if ( (sel = document.selection) && sel.type != "Control" ) {
containerNode = sel.createRange().parentElement();
}
while (containerNode) {
if (containerNode.nodeType == 1 && containerNode.tagName == tagName) {
return true;
}
containerNode = containerNode.parentNode;
}
return false;
}

http://jsfiddle.net/RCdhS/2/
.on('keypress', 'document', function (e) {
if (!$('li').focus();) {
...
}
}
});

Related

Javascript - Check highlighted text within Contenteditable has link tags

Im currently building a very simple inline-editor, for content editable areas within a website. I have managed to do the basics (Bold, Italic etc) and now I have hit a pitfall.
I'm allowing the user to create links, by highlighting text and creating the link via text input. My problem is if the highlighted/selected text is already wrapped in tags I wish the text input to display the current link. Thus giving the user the ability to terminate the link or update/edit it.
My code for creating a link by highlighting selected text HTML:
<div contenteditable='TRUE' class="editable">This Contenteditable text</div>
<!-- Add Url to Highlighted Text -->
<div class="text-button" unselectable="on" onmousedown="event.preventDefault();" onclick="displayUrlInserter();">Add Url</div>
<!-- Show URL Input and Submit -->
<div class="text-button-panel" id="text-button-panel">
<input type="text" id="url" placeholder="Paste or Type your link">
<div class="text-panel-done" onmousedown="event.preventDefault();" onclick="doneUrl()">Done</div>
<div class="text-panel-cancel" onmousedown="event.preventDefault();" onclick="cancelUrl()">Cancel</div>
</div>
Javascript :
function saveSelection() {
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
return sel.getRangeAt(0);
}
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
}
return null;
}
function restoreSelection(range) {
if (range) {
if (window.getSelection) {
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (document.selection && range.select) {
range.select();
}
}
}
var selRange;
function displayUrlInserter() {
selRange = saveSelection();
// Display
document.getElementById("text-button-panel").style.display = "block";
// Focus
document.getElementById("url").focus();
}
function doneUrl() {
var url = document.getElementById("url").value;
// No Url
if (url === "") {
return false;
}
// Check for HTTP
if (!url.match("^(http|https)://")) {
url = "http://" + url;
}
restoreSelection(selRange);
**// THIS IS WHERE I NEED TO CHECK FOR EXISTING A TAGS**
document.execCommand("CreateLink", false, url);
// Hide Panel
document.getElementById("text-button-panel").style.display = "none";
// Reset Input
document.getElementById("url").value = "";
}
function cancelUrl() {
document.getElementById("text-button-panel").style.display = "none";
}
The saveSelection and restoreSelection saves the currently selected text and allows me to create the link within doneUrl() via the execCommand.
This all works fine, all i need is to be able check and get the if it is present. Any guidance would be appreciated.
Try : Grande.js
https://github.com/mduvall/grande.js
Look like this when you selected texts
Live : http://mattduvall.com/grande.js/
Here is a function to check if the current selection is a link.
function itemIsLinked(){
if(window.getSelection().toString() != ""){
var selection = window.getSelection().getRangeAt(0);
if(selection){
if (selection.startContainer.parentNode.tagName === 'A' || selection.endContainer.parentNode.tagName === 'A') {
return [true, selection];
} else { return false; }
} else { return false; }
}
}
Then you can run something like
var isLink = itemIsLinked();
If it is linked it will return :
isLink[0] -> true
isLink[1] -> the link object.
To then get the HREF from that selection use:
isLink[1].startContainer.parentNode.href
That's worked really well for me. Good luck.

determine the frame id/name when a user has selected text in that frame- the page has multiple frames

I have a scenario in which there are multiple iframes/frames open in one web page. Now user may select some text in any one of the open frames/iframes. I want to determine the id/name of the iframe in which user has selected text, using the iframe id/name I will then do some operations on the selected text.
How do I do this?
This will get the first iframe in the curent document that has a non-empty selection. If an iframe is from another domain and hence inaccessible to JavaScript running in the current document, the selection cannot be retrieved and the iframe is ignored.
function getSelectedText(win) {
var sel;
if (win.getSelection) {
return "" + win.getSelection();
} else if ( (sel = win.document.selection) ) {
if (sel.type == "Text") {
return sel.createRange().text;
}
}
return "";
}
function getIframeWithSelection(win) {
var iframes = win.document.getElementsByTagName("iframe");
for (var i = 0, len = iframes.length, selectedText; i < len; ++i) {
try {
selectedText = getSelectedText(iframes[i].contentWindow);
if (selectedText != "") {
// alert just there for debugging
alert(selectedText);
return iframes[i];
}
} catch (e) {}
}
return null;
}
// Example
var iframe = getIframeWithSelection(window);

Add keyDown() function to <a> which are new children of a contenteditable div

Jsfiddle: http://jsfiddle.net/qTEmc/1/
I need to associate events with the keypress event on links which are added in the contenteditable.
If you try typing in the contenteditable area in the linked jfiddle, you'll see it creates a link and you can type within it. I fyou press return, you go to a newline. What I want is for pressing return in the new link to trigger a function. For the sake of progress, I'm just trying to get it to return an alert at the moment.
Does anyone know a reliable way to do this?
You won't be able to detect key events within the links themselves because they don't fire key events. Instead, you'll need to adapt your existing keypress handler for the contenteditable element to inspect the selection to see if it lies within a link. Here's a function to do that. I've also updated your demo.
function selectionInsideLink() {
var node = null, sel;
// Get the selection container node
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
node = sel.getRangeAt(0).commonAncestorContainer;
}
} else if (document.selection) {
sel = document.selection;
if (sel.type != "Control") {
node = sel.createRange().parentElement();
}
}
// Check if the node is or is contained inside a link
while (node) {
if (node.nodeType == 1 && node.tagName.toLowerCase() == "a") {
return true;
}
node = node.parentNode;
}
return false;
}

How to have a popup after selecting text?

I can't seem to figure this out. I have a div with some text in it. When the user selects pieces of it (totally at random, whatever they want), I want a small popup to occur with the text inside of it.
To initiative the popup, can I just do this? ...
$('#textdiv').click(function() {
But then how do I get only the selected/highlighted text?
jQuery isn't going to be of much use here, so you'll need pure JS to do the selection grabbing part (credit goes to this page):
function getSelected() {
if(window.getSelection) { return window.getSelection(); }
else if(document.getSelection) { return document.getSelection(); }
else {
var selection = document.selection && document.selection.createRange();
if(selection.text) { return selection.text; }
return false;
}
return false;
}
You were on the right track with the mouseup handler, so here's what I got working:
$('#test').mouseup(function() {
var selection = getSelected();
if (selection) {
alert(selection);
}
});
And a live demo: http://jsfiddle.net/PQbb7/7/.
Just updated first answer.
Try this
function getSelected() {
if(window.getSelection) { return window.getSelection(); }
else if(document.getSelection) { return document.getSelection(); }
else {
var selection = document.selection && document.selection.createRange();
if(selection.text) { return selection.text; }
return false;
}
return false;
}
/* create sniffer */
$(document).ready(function() {
$('#my-textarea').mouseup(function(event) {
var selection = getSelected();
selection = $.trim(selection);
if(selection != ''){
$("span.popup-tag").css("display","block");
$("span.popup-tag").css("top",event.clientY);
$("span.popup-tag").css("left",event.clientX);
$("span.popup-tag").text(selection);
}else{
$("span.popup-tag").css("display","none");
}
});
});
.popup-tag{
position:absolute;
display:none;
background-color:#785448d4;
color:white;
padding:10px;
font-size:20px;
font-weight:bold;
text-decoration:underline;
cursor:pointer;
-webkit-filter: drop-shadow(0 1px 10px rgba(113,158,206,0.8));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Select any text :<br>
<textarea type="text" id="my-textarea" style="width:100%; height:200px;" >
While delivering a lecture at the Indian Institute of Management Shillong, Kalam collapsed and died from an apparent cardiac arrest on 27 July 2015, aged 83. Thousands including national-level dignitaries attended the funeral ceremony held in his hometown of Rameshwaram, where he was buried with full state honours.
</textarea>
<span class="popup-tag"></span>
see: https://jsfiddle.net/arunmaharana123/kxj9pm40/
We've just released an jQuery plugin called highlighter.js that should allow you to do this flexibly. The code is https://github.com/huffpostlabs/highlighter.js, feel free to ask any questions on the github page.
You can get it from the base DOM element likeso:
var start = $('#textdiv')[0].selectionStart;
var end = $('#textdiv')[0].selectionEnd;
var highlight = $('#textdiv').val().substring(start, end);
// Note the [0] part because we want the actual DOM element, not the jQuery object
At this point, you just need to bind it to a click event. I think in this case mouseup is the event you'd want to bind to, since a user clicks and holds the mouse and then releases it after they're done highlighting text.
The problem is this would not trigger users that use only the keyboard to highlight text. For that you'd want to use keyup on the element and filter for the right keystrokes.
You need a event listener that listen to mouseup event.
var bubbleDOM = document.createElement('div');
bubbleDOM.setAttribute('class', 'selection_bubble');
document.body.appendChild(bubbleDOM);
// Lets listen to mouseup DOM events.
document.addEventListener('mouseup', function (e) {
var selection = window.getSelection().toString();
if (selection.length > 0) {
renderBubble(selection);
}
}, false);
// Close the bubble when we click on the screen.
document.addEventListener('mousedown', function (e) {
bubbleDOM.style.visibility = 'hidden';
}, false);
// Move that bubble to the appropriate location.
function renderBubble(selection) {
bubbleDOM.innerHTML = selection;
bubbleDOM.style.visibility = 'visible';
}

jQuery: Trigger keydown only in specific div

I have a page with couple of DIV elements. When user presses the CTRL+ENTER button combo, I need to display (via alert()) the text, that user previously selected. I found the solution and it works like a charm, but there is still one thing left.
I need to make event trigger, only when selected text is inside a DIV with class "main_content". I've tried to assign keyup to $('DIV.main_content'), but it does not work.
Is there a way to make event trigger only if text inside $('DIV.main_content') selected?
Here is a working code that triggers on the whole document:
// Get user selection text on page
function getSelectedText() {
if (window.getSelection) {
return window.getSelection();
}
else if (document.selection) {
return document.selection.createRange().text;
}
return '';
}
$(document).ready(function(){
$(document).keydown(function(e) {
if(e.which == 13 && e.ctrlKey) {
alert(getSelectedText());
return false;
}
});
});
See the code with markup in jsFiddle
You have an error in the getSelectedText() function: window.getSelection() returns a Selection object, not a string. The fact you're passing the result of this to alert() is masking this, because alert() implicitly converts the argument passed to it into a string.
Here's some code to check whether the selection is completely contained within a <div> element with a particular class. It works in all major browsers.
Live example: http://www.jsfiddle.net/cVgsy/1/
// Get user selection text on page
function getSelectedText() {
if (window.getSelection) {
return window.getSelection().toString();
}
else if (document.selection) {
return document.selection.createRange().text;
}
return '';
}
function isSelectionInDivClass(cssClass) {
var selContainerNode = null;
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount) {
selContainerNode = sel.getRangeAt(0).commonAncestorContainer;
}
} else if (document.selection && document.selection.type != "Control") {
selContainerNode = document.selection.createRange().parentElement();
}
if (selContainerNode) {
var node = selContainerNode;
while (node) {
if (node.nodeType == 1 && node.nodeName == "DIV" && $(node).hasClass(cssClass)) {
return true;
}
node = node.parentNode;
}
}
return false;
}
$(document).ready(function(){
$(document).keydown(function(e) {
if(e.which == 13 && e.ctrlKey && isSelectionInDivClass("main_content")) {
alert(getSelectedText());
return false;
}
});
});
It is interesting question. I have the following idea: you need to catch mouseup event on div.
For example:
So, in your case you can do something like this:
var selectedText = "";
$(".yourdiv").mouseup(function(){
if (window.getSelection)
selectedText = window.getSelection();
else if (document.selection)
selectedText = document.selection.createRange().text;
alert(selectedText)
});
And variable selectedText will be store selected text.

Categories

Resources