I can used window.getSelection to get selected words.
<div id="content">
<p class="todo">If you don't know, you can google</p>
</div>
<script>
let selectionObj = null;
let selectedText = "";
function getCurrentSelect() {
if (window.getSelection) {
selectionObj = window.getSelection();
selectedText = selectionObj.toString();
return {
selectText: selectedText
}
}
}
window.onload = function (){
document.body.addEventListener('mouseup', function(){
// if (selectOb) console.log(getCurrentSelect()===selectOb);
// selectOb = getCurrentSelect();
console.log('onmouseup');
console.log(getCurrentSelect());
})
}
</script>
if have two or more identical elements.
<div id="content">
<p class="todo">If you don't know, you can google</p>
<p class="todo">If you don't know, you can google</p>
<p class="todo">If you don't know, you can google</p>
</div>
how to know which element selected?
I want to be able to return an element object when selecting text.But I don't know what to do.
window.getSelection() will return a selection object which contains some of the properties that you might be interested in. For example, you can access the parent element of the text you select via window.getSelection().baseNode.parentElement. This will return a parent element which you could manipulate with your code furthermore.
In the code below, I will get the parent node of the selected text, and change the color of it (style property) to red. Please find it here:
let selectionObj = null;
let selectedText = '';
function getCurrentSelect() {
if (window.getSelection) {
selectionObj = window.getSelection();
selectedText = selectionObj.toString();
return {
selectText: selectedText,
parentElement: selectionObj.baseNode.parentElement,
};
}
}
window.onload = function () {
document.body.addEventListener('mouseup', function () {
console.log('onmouseup');
const { parentElement } = getCurrentSelect(); // this one will give the parent element of the selected text
parentElement.style.color = 'red'; // we change one of the properties of the parent element
console.log(getCurrentSelect());
});
};
let selectionObj = null;
let selectedText = "";
window.onload = function (){
document.body.addEventListener('mouseup', function(e){
// if (selectOb) console.log(getCurrentSelect()===selectOb);
// selectOb = getCurrentSelect();
console.log('onmouseup');
console.log(e.target.innerText);
})
}
<div id="content">
<p class="todo">If you don't know, you can google</p>
</div>
Related
We are able to get a selection range via window.getSelection().
I'm wondering whether there is a way to subscribe to window.getSelection changes.
The only way which came to me is to use timeouts (which is obviously bad) or subscribe to each user's key \ mouse press event and track changes manually.
ANSWER UPD: You are able to use this library, I've published it, as there are no more suitable ones: https://github.com/xnimorz/selection-range-enhancer
Use the onselect event.
function logSelection(event) {
const log = document.getElementById('log');
const selection = event.target.value.substring(event.target.selectionStart, event.target.selectionEnd);
log.textContent = `You selected: ${selection}`;
}
const textarea = document.querySelector('textarea');
textarea.onselect = logSelection;
<textarea>Try selecting some text in this element.</textarea>
<p id="log"></p>
For specific cases such as span contenteditable, you can make a polyfill:
function logSelection() {
const log = document.getElementById('log');
const selection = window.getSelection();
log.textContent = `You selected: ${selection}`;
}
const span = document.querySelector('span');
var down = false;
span.onmousedown = () => { down = true };
span.onmouseup = () => { down = false };
span.onmousemove = () => {
if (down == true) {
logSelection();
}
};
<span contenteditable="true">Try selecting some text in this element.</span>
<p id="log"></p>
if Im undesrting in right way you want to know when user start selection on page you can use DOM onselectstart.
document.onselectstart = function() {
console.log("Selection started!");
};
more info MDN
I'm trying to use one function and a lot of IF functions to run this code.
I'm going to make this as a note app.
I want to add an IF function that has an class called stop-note.
I want to add it in the notes list for it's IF function then I want to add it to the "renderNotes" for it's link like style.
notesList.on('click', function (e) {
e.preventDefault();
var target = $(e.target);
var abort = false;
// Listen to the selected note.
if (target.hasClass('listen-note')) {
if (abort) {
return;
}
var content = target.closest('.note').find('.content').text();
readOutLoud(content);
}
//Edit Note
if (target.hasClass('edit-note')) {
editText(content);
var dateTime = target.siblings('.date').text();
deleteNote(dateTime);
target.closest('.note').remove();
var content = target.closest('.note').find('.content').text();
}
// Delete note.
if (target.hasClass('delete-note')) {
var dateTime = target.siblings('.date').text();
deleteNote(dateTime);
target.closest('.note').remove();
}
});
This is my function that runs my function above.
function renderNotes(notes) {
var html = '';
if (notes.length) {
notes.forEach(function (note) {
html += `<li class="note">
<p class="header">
<span class="date">${note.date}</span>
Listen
Edit
html = <button class="stop-note" onclick="abort = true">Stop</button>
Delete
</p>
<p class="content">${note.content}</p>
</li>`;
});
} else {
html = '<li><p class="content">You don\'t have any notes yet.</p></li>';
}
notesList.html(html);
}
abort is a local variable, and you set it to false whenever they click on a note list. So onclick="abort = true" has no effect on the variable that's being tested in the function.
You need to make it a global variable.
window.abort = false;
notesList.on('click', function (e) {
e.preventDefault();
var target = $(e.target);
// Listen to the selected note.
if (target.hasClass('listen-note')) {
if (abort) {
return;
}
var content = target.closest('.note').find('.content').text();
readOutLoud(content);
}
//Edit Note
if (target.hasClass('edit-note')) {
editText(content);
var dateTime = target.siblings('.date').text();
deleteNote(dateTime);
target.closest('.note').remove();
var content = target.closest('.note').find('.content').text();
}
// Delete note.
if (target.hasClass('delete-note')) {
var dateTime = target.siblings('.date').text();
deleteNote(dateTime);
target.closest('.note').remove();
}
});
I have made a plugin for CKEditor, but it relies on the currently selected text.
In FF and Chrome I can use:
var selectedText = editor.getSelection().getNative();
but this doesn't work in IE and I only get [object Object]
Any suggestions?
This is what I use:
var mySelection = editor.getSelection();
if (CKEDITOR.env.ie) {
mySelection.unlock(true);
selectedText = mySelection.getNative().createRange().text;
} else {
selectedText = mySelection.getNative();
}
Use:
editor.getSelection().getSelectedText();
Or:
CKEDITOR.instances["txtTexto"].getSelection().getSelectedText()
"txtTexto" = ID of textarea tag
To those who want to prefill fields with a selection, just do it like that and safe yourself a long journey.
onShow: function() {
this.setValueOf( 'tab-id', 'field-id', editor.getSelection().getSelectedText().toString() );
},
Have a nice day!
In the newer versions of CKEDITOR, there seems to be a way easier method:
var selectedHTML = editor
.getSelectedHtml()
.getHtml(); //result: <p>test</p>
#TheApprentice
You put it like this:
( function(){
var getSelectedText = function(editor) {
var selectedText = '';
var selection = editor.getSelection();
if (selection.getType() == CKEDITOR.SELECTION_TEXT) {
if (CKEDITOR.env.ie) {
selection.unlock(true);
selectedText = selection.getNative().createRange().text;
} else {
selectedText = selection.getNative();
}
}
return(selectedText);
}
...
with a call like this:
onShow: function() {
// Get the element currently selected by the user
var editor = this.getParentEditor();
var selectedContent = getSelectedText(editor);
I've tried to simplify the code as much as possible. What I'm trying to do is implement a way to resize some elements. To do so, I create a <div class="resize-on"> (it's the orange colored one) and then if you click and hold your mouse down and move then some action should happen like so
var Ui = {};
Ui.Resizer = function (element) {
this.isResizing = false;
this.element = element;
this.resizer = document.createElement("div");
this.resizer.classList.add('resize-on');
var toWrap = this.element;
var parent = toWrap.parentNode;
var next = toWrap.nextSibling;
this.resizer.appendChild(toWrap);
parent.insertBefore(this.resizer, next);
this.resizer.onmousedown = function(event) {
this.isResizing = true;
console.log('onmousedown', this.isResizing);
}.bind(this);
document.querySelector("body").onmousemove = function(event) {
if(this.isResizing) {
console.log('onmousemove', this.isResizing);
}
}.bind(this);
document.querySelector("body").onmouseup = function(event) {
this.isResizing = false;
console.log('mouse up');
}.bind(this);
};
(function() {
Array.prototype.forEach.call(
document.querySelectorAll('.resizable'),
function (element) {
new Ui.Resizer(
element
);
}
);
})();
.resize-on {
background-color: orange;
}
<div class="wrap">
<div class="one">One</div>
<div class="two resizable">two</div>
<div class="three">three</div>
<div class="four">four</div>
<div class="five">five</div>
</div>
So this works fine.
Now the problem is if I have multiple resizable elements it does not work. It then only works on the "last" one (in this case <div class="four resizable">four</div>) Why is that?
The element <div class="two resizable">two</div> get's the mousedown but does not show the onmousemove anymore.
It's the exact same code as above. Just added the resizable class to another HTML element. I can't understand why this doesn't work. Can anyone shed some light on this? Also what do I have to change to get it to work?
var Ui = {};
Ui.Resizer = function (element) {
this.isResizing = false;
this.element = element;
this.resizer = document.createElement("div");
this.resizer.classList.add('resize-on');
var toWrap = this.element;
var parent = toWrap.parentNode;
var next = toWrap.nextSibling;
this.resizer.appendChild(toWrap);
parent.insertBefore(this.resizer, next);
this.resizer.onmousedown = function(event) {
this.isResizing = true;
console.log('onmousedown', this.isResizing);
}.bind(this);
document.querySelector("body").onmousemove = function(event) {
if(this.isResizing) {
console.log('onmousemove', this.isResizing);
}
}.bind(this);
document.querySelector("body").onmouseup = function(event) {
this.isResizing = false;
console.log('mouse up');
}.bind(this);
};
(function() {
Array.prototype.forEach.call(
document.querySelectorAll('.resizable'),
function (element) {
new Ui.Resizer(
element
);
}
);
})();
.resize-on {
background-color: orange;
}
<div class="wrap">
<div class="one">One</div>
<div class="two resizable">two</div>
<div class="three">three</div>
<div class="four resizable">four</div>
<div class="five">five</div>
</div>
Use addEventListener for the events. Using the property onmousemove and others on the body element is only going to allow you to add a single event listener, as the previous one is going to be overwritten, hence why only the last one done, in this case the one for "four", works.
document.querySelector("body").addEventListener("mousemove", function(event) {
this.isResizing = false;
console.log('mouse up');
}.bind(this);
Though you can make it so you only need to set a single listener with only a little modification.
Ui.Resizer = function(element){
//...other code
this.resizer.onmousedown = function(event) {
//Set a property on Ui for use to know which Resizer is active and
//access it in the body events.
Ui.active = this;
}.bind(this);
//...rest of code excluding body events (mousemove, mouseup)
};
document.body.addEventListener("mousemove",function(event){
if(Ui.active){
//if Ui.active is set, active will be the Resizer instance
//and therefore can access the element it was created for
//by using active.element
console.log("mousemove",Ui.active.element);
}
});
document.body.addEventListener("mouseup",function(event){
if(Ui.active){
console.log("mouseup",Ui.active.element);
//clear active
Ui.active = null;
}
});
Demo
var Ui = {};
Ui.Resizer = function(element) {
this.isResizing = false;
this.element = element;
this.resizer = document.createElement("div");
this.resizer.classList.add('resize-on');
var toWrap = this.element;
var parent = toWrap.parentNode;
var next = toWrap.nextSibling;
this.resizer.appendChild(toWrap);
parent.insertBefore(this.resizer, next);
this.resizer.onmousedown = function(event) {
//Set a property on Ui for use to know which Resizer is active and
//access it in the body events.
Ui.active = this;
}.bind(this);
};
document.body.addEventListener("mousemove", function(event) {
if (Ui.active) {
//if Ui.active is set, active will be the Resizer instance
//and therefore can access the element it was created for
//by using active.element
console.log("mousemove", Ui.active.element);
}
});
document.body.addEventListener("mouseup", function(event) {
if (Ui.active) {
console.log("mouseup", Ui.active.element);
//clear active
Ui.active = null;
}
});
(function() {
Array.prototype.forEach.call(
document.querySelectorAll('.resizable'),
function (element) {
new Ui.Resizer(
element
);
}
);
})();
.resize-on {
background-color: orange;
}
<div class="wrap">
<div class="one">One</div>
<div class="two resizable">two</div>
<div class="three">three</div>
<div class="four resizable">four</div>
<div class="five">five</div>
</div>
I am creating a Google chrome extension which can read the contents of clipboard.
But I am unable to get the documentation for this. I want to get the clipboard content as in IE's clipboard API.
In the manifest file i gave permissions to
clipboardRead and clipboardWrite.
I have created a function in Background page as below
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == "getClipData")
sendResponse({data: document.execCommand('paste')});
else
sendResponse({}); // snub them.
});
And in Content Script I am calling the function like this
chrome.extension.sendRequest({method: "getClipData"}, function(response) {
alert(response.data);
});
But this returns me undefined...
document.execCommand('paste') returns success or failure, not the contents of the clipboard.
The command triggers a paste action into the focused element in the background page. You have to create a TEXTAREA or DIV contentEditable=true in the background page and focus it to receive the paste content.
You can see an example of how to make this work in my BBCodePaste extension:
https://github.com/jeske/BBCodePaste
Here is one example of how to read the clipboard text in the background page:
bg = chrome.extension.getBackgroundPage(); // get the background page
bg.document.body.innerHTML= ""; // clear the background page
// add a DIV, contentEditable=true, to accept the paste action
var helperdiv = bg.document.createElement("div");
document.body.appendChild(helperdiv);
helperdiv.contentEditable = true;
// focus the helper div's content
var range = document.createRange();
range.selectNode(helperdiv);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
helperdiv.focus();
// trigger the paste action
bg.document.execCommand("Paste");
// read the clipboard contents from the helperdiv
var clipboardContents = helperdiv.innerHTML;
If you want plain-text instead of HTML, you can either use helperdiv.innerText, or you can switch to using a textarea. If you want to parse the HTML in some way, you can walk the HTML dom inside the DIV (again, see my BBCodePaste extension)
var str = document.execCommand('paste');
You will need to add the clipboardRead permission too.
We cant access clipboard from javascript instead IE for chrome and other browsers.
The hack for this is very simple: create own custom clipboard which store text on cut and from where we paste it directly
function copy(){
if (!window.x) {
x = {};
}
x.Selector = {};
x.Selector.getSelected = function() {
var t = '';
if (window.getSelection) {
t = window.getSelection();
} else if (document.getSelection) {
t = document.getSelection();
} else if (document.selection) {
t = document.selection.createRange().text;
}
return t;
}
var mytext = x.Selector.getSelected();
document.getElementById("book").innerHTML =mytext;
}
function cut(){
if (!window.x) {
x = {};
}
x.Selector = {};
x.Selector.getSelected = function() {
var t = '';
if (window.getSelection) {
t = window.getSelection();
} else if (document.getSelection) {
t = document.getSelection();
} else if (document.selection) {
t = document.selection.createRange().text;
}
return t;
}
var mytext = x.Selector.getSelected();
document.getElementById("book").innerHTML =mytext;
x.Selector.setSelected()="";
}
function paste()
{
var firstDivContent = document.getElementById('book');
var secondDivContent = document.getElementById('rte');
secondDivContent.innerHTML += firstDivContent.innerHTML;
rte.focus();
}
function clear()
{
document.getElementById('rte').innerHTML="";
rte.focus();
}
<button id="cut"onclick="cut();">Cut</button>
<button id="copy"onclick="copy();">Copy</button>
<button id="paste"onclick="paste();">Paste</button>
Working Div
<div id="rte" contenteditable="true" style="overflow:auto;padding:10px;height:80vh;border:2px solid black;" unselectable="off" ></div>
Own Clipboard(hack)
<div id="book" contenteditable="true"style="background-color:#555;color:white;"> </div>