I have the following solution that adds clicked words to a <input> field string.
However, I would like to change the javascript to allow me to:
Keep text that I manually add to the <input> field. At the moment it is overwritten.
Exclude full stops from text transferred from <p> to <input>
HTML
<p id="target_para">
Here's an example of the thing you wanted to be made clickable.
</p>
<input type="text" id="display" />
JS
(function () {
"use strict";
var para, targets, display, words, clickHandler, updateList, i, j, cur;
display = document.getElementById("display");
para = document.getElementById("target_para");
// Wrap every word in a span element
para.innerHTML = '<span>' + para.innerText.replace(/ /g,'</span><span> ') + '</span>';
// Updated target
targets = para.getElementsByTagName("span");
words = [];
// Handler for clicking a clickable element
clickHandler = function () {
var text = this.innerText || this.textContent,
idx = words.indexOf(text);
if (words.indexOf(text) < 0) {
// If not already in list, add it
words.push(text);
} else {
// Otherwise remove it
words.splice(idx, 1);
}
updateList();
};
// Update display of word list
updateList = function () {
while (display.firstChild) {
display.removeChild(display.firstChild);
}
// Set the input box value
display.value = words.join(",");
};
// Bind event handlers to clickable elements
for (i = 0, j = targets.length; i < j; i++) {
cur = targets[i];
cur.addEventListener("click", clickHandler, false);
}
}());
I would do it this way
(function() {
"use strict";
var input = document.getElementById('display');
var paragraph = document.getElementById('target_para');
paragraph.innerHTML = paragraph.innerHTML.replace(/([^\ ]+)/g, "<span>$1</span>");
paragraph.addEventListener('click', function(e) {
if ('span' !== e.target.nodeName.toLowerCase()) {
return false;
}
input.value += ' ' + e.target.innerHTML;
}, false);
})();
Here's a fiddle: http://jsfiddle.net/HAxCw/
As a word separator for the input I used a space but you can change it to whatever you want. It's this line of code
input.value += ' ' + e.target.innerHTML;
Related
I am trying to set the cursor inside a empty span that I append, but it's not working. I did check out this question How to set the cursor inside a newly added empty span with Javascript (in a contenteditable div)?, But it didn't help me out
This is my code:
<script>
var app = angular.module('myApp',[]);
app.controller('editor',function($scope){
$scope.FontSize = function(start, end)
{
var size = [];
for (var i = start; i <= end; i++) {
size.push(i);
}
return size;
};
$scope.changeFont = function()
{
$("#content").append("<span id='one' style='font-size:"+$scope.kys_selected_font +"px' > </span>");
$("#one").focus();
};
});
</script>
I am able to set focus when i have text inside span, but not when it's empty.
Maybe you change code like this:
$scope.changeFont = function() {
var spanNode = $("<span id='one' style='font-size:" + $scope.kys_selected_font + "px' > </span>");
$("#content").append(spanNode);
spanNode.focus();
};
I am creating a keyboard on my screen. Right now I am getting back the value of each letter when clicked through the function getLetter, but I need to grab that value and use it instead of prompt()[0]. So I want my input to be the actual letter ("A" or "B" or...). The problem is that I am not being able to put that value in the input variable. How do I do this?
abc = ['A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
$('#letters').text('');
for (i = 0; i < 26; i++) {
var div = $('<div>').css( 'cursor', 'pointer' );
div.html(abc[i]);
div.on('click', getLetter);
var newDiv = $('#letters').append(div);
}
$('body').append(newDiv);
function getLetter() {
$(this).text();
this.innerHTML = ' ';
this.style.cursor = 'default';
this.onclick = null;
}
while(!game.isOver()) {
var input = prompt()[0];
game.guess(input);
$('p').text(game.render());
}
You can move the contents of the while loop into the getLetter() function, and remove the while loop because it is useless now: you don't want to do anything until the user clicks a button.
function getLetter() {
var input=$(this).text();
this.innerHTML = ' ';
this.style.cursor = 'default';
this.onclick = null;
game.guess(input);
$('p').text(game.render());
}
Ok I am making a text editor and have to try and make the last word typed change font color based on if it's a keyword or not... I have tried multiple solutions to this but nothing has prevailed... Here is what I have tried so far
function getLastWord() {
var input = document.getElementById("my_text").value;
//var input = document.getElementById(textArea.value);
var inputValue = input.value;
var lastWordTyped
var changeColorOfWord;
var ele = document.querySelector("#my_text");
//ele.style.color = "blue"
if (input == null) {
input == " ";
}
lastWordTyped = input.substr(input.trim().lastIndexOf(" ") + 1);
//lastWordTyped = inputValue.substr(inputValue.trim().lastIndexOf(" ") + 1);
if (input != null) {
for (var i = 0; i < reservedKeyWords.length; i++) {
if ( lastWordTyped == reservedKeyWords[i] ) {
//changeColor(lastWordTyped);
//my_text.replace(inputValue, lastWordTyped);
//ele.fieldNameElement.innerHTML = lastWordTyped;
//ele.innerHTML = lastWordTyped;
ele.innerHTML.fontcolor = 'Blue';
return;
} else if (lastWordTyped !== reservedKeyWords[i]) {
//ele.innerHTML = ele.innerHTML.replace(lastWordTyped, '<span style="color:black"></span>');
//resetFontColor();
}
}
}
}
I have tried this function (found from SO)
function changeColor(word) {
var ele = document.querySelector("my_text");
ele.onkeypress = function () {
setTimeout(function () {
//the setTimeout is so the content is inserted before execution
document.getElementById('view_text').value = ele.textContent;
if (ele.innerHTML.indexOf(word) !== -1) {
ele.innerHTML = ele.innerHTML.replace(word, '<span style="color:blue">' + word + '</span>');
}
}, 50);
}
}
Also I have tried this one:
function colorMyKeyword(keywordColor, text) {
return '<span style="color:' + keywordColor + '>' + text + '</span>';
}
None of these functions have gotten the job done though. I have it now so that it will change the text color to blue but then the problem is that it changes ALL of the text to blue after that word...
I would prefer this to be in javascript as I do not know how to use JQuery, or really CSS for that matter or even know how to write it..
Thank you for any responses.
Updated code based on comment(s) below (changed to div from input)
Not the best code in the world but it should work. The CSS should probably be done by adding a class instead of changing the style attribute.
<div id="my_text">This is some text</div>
var isKeyword = false;
var el = document.getElementById('my_text');
var arr = el.innerHTML.split(' ');
var lastWordTyped = arr.pop();
/* replace with yours*/
var reservedKeyWords = ['text','another','word', 'here'];
for (var i = 0, len = reservedKeyWords.length ; i < len ; i++) {
if ( lastWordTyped == reservedKeyWords[i] ) {
lastWordTyped = '<span style="color:blue">'+lastWordTyped +'</span>'; //update color
arr.push(lastWordTyped);
isKeyword = true;
}
}
if (!isKeyword) { arr.push(lastWordTyped); } //put original back
el.innerHTML = arr.join(' ');
UPDATED: Do the whole thing on keyup
here's a simple example that you can use: DEMO
$('#text').keyup(function(){
$('#result').html($('#text').val());
var splittedText=$('#result').html().split(/\s/);
var lastWord=splittedText[splittedText.length-1];
$('#result').html($('#result').html().replace(lastWord,'<span>'+lastWord+'</span>'));
$('#result').children('span').css('color',$('#color').val());
});
you need to write a sentence in the first input and a hexa-deciaml color in the second one.(including the # at the beginning)
Here is an attempt to answer your questions :
I am using #GaryStorey's answer as it was a better starting point than what I add (I do like pop&push).
The problem with his answer were that it only showed how to change the color but it wasn't relevant on how to do it in an input nor in a contenteditable element.
So here are my adjustements, with a setCaret function to deal with the fact that caret always returns to start if we do change the innerHTML of edited element.
Be carefull, it is still very buggy and you should not use it in any production,
however it can give you a good starting point.
var reservedKeyWords = ['text', 'another', 'word', 'here'];
var el = document.getElementById('my_text');
el.addEventListener('keyup', function (evt) {
if (evt.keyCode == 32 || evt.keyCode == 13) {
var isKeyword = false;
var arr = el.innerHTML.split(/\s/);
var lastWordTyped = arr.pop();
lastWordTyped = lastWordTyped.replace(' ', '');
for (var i = 0, len = reservedKeyWords.length; i < len; i++) {
if (lastWordTyped == reservedKeyWords[i]) {
lastWordTyped = '<span style="color:blue">' + lastWordTyped + '</span>'; //update color
arr.push(lastWordTyped);
isKeyword = true;
}
}
if (!isKeyword) {
arr.push(lastWordTyped);
} //put original back
el.innerHTML = arr.join(' ') + ' ';
setCaret(el);
}
});
function setCaret(el) {
var range = document.createRange();
var endNode = el.lastChild;
range.selectNodeContents(endNode);
range.setStart(endNode, range.endOffset);
range.setEnd(endNode, range.endOffset);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
#my_text {
min-width: 100%;
min-height: 2em;
padding: 0.5em;
display: block;
border : dashed 0.5px grey;
}
<p> list of KeyWords : 'text', 'another', 'word', 'here';</p>
<span id="my_text" contenteditable="true">Edit me using "reservedKeyWords" defined in JS</span>
Oh and note that I am using a span instead of a div, because div tag adds some <br> from nowhere after the textNode.
I'm trying to replace the <li> with 1. 2. 3. respectively. I managed to change the <li> to a number, but that number is 0. The loop doesn't want to work. To be honest, this method may be impossible.
Take a look at the Fiddle if you'd like.
This is my function(){...} :
function doIt(){
var input = document.getElementById("input");
var li = /<li>/; // match opening li
var liB = /<\/li>/; // match closing li
var numberOfItems = input.value.match(li).length; // number of lis that occur
for(var i = 0; i < numberOfItems; i++) {
insertNumber(i); // execute insertNumber function w/ parameter of incremented i
}
function insertNumber(number){
input.value = input.value.replace(li, number + "." + " ").replace(liB, "");
}
}
I understand the insertNumber(){...} function is not necessary.
Here's an alternative method, turning your HTML textarea contents into DOM elements that jQuery can manipulate and managing them that way:
function doIt() {
var $domElements = $.parseHTML( $('#input').val().trim() ),
output = [],
i = 1;
$.each($domElements, function(index, element) {
if($(this).text().trim() != '') {
output.push( i + '. ' + $(this).text().trim() );
i++;
}
});
$('#input').val(output.join('\n'));
}
I have seen many posts pertaining to highlighting text in a DIV using javascript, but none do quite what I'm looking for.
What I need to do is highlight the text within a specific DIV, character by character as the user enters the search term. Conversely, as the user backspaces or deletes characters, I need to "de-highlight" the text of the same DIV.
I imagine this has already been done somewhere by someone, but I have not yet found a post here or from Google that behaves exactly as I need.
Any feedback is appreciated.
this code executes as user types characters into an input field. The problem with it is that in some instances, it inserts the string " " into the table as I type and I don't know why, so I'm searching for a different solution.
Thanks for your feedback!
function filterTable(Stxt, table) {
dehighlight(document.getElementById(table));
if (Stxt.value.length > 0)
highlight(Stxt.value.toLowerCase(), document.getElementById(table));
}
function dehighlight(container) {
for (var i = 0; i < container.childNodes.length; i++) {
var node = container.childNodes[i];
if (node.attributes && node.attributes['class'] && node.attributes['class'].value == 'highlighted') {
node.parentNode.parentNode.replaceChild(
document.createTextNode(node.parentNode.innerHTML.replace(/<[^>]+>/g, "")),node.parentNode);
return;
} else if (node.nodeType != 3) {
dehighlight(node);
}
}
}
function highlight(Stxt, container) {
for (var i = 0; i < container.childNodes.length; i++) {
var node = container.childNodes[i];
if (node.nodeType == 3) {
var data = node.data;
var data_low = data.toLowerCase();
if (data_low.indexOf(Stxt) >= 0) {
var new_node = document.createElement('span');
node.parentNode.replaceChild(new_node, node);
var result;
while ((result = data_low.indexOf(Stxt)) != -1) {
new_node.appendChild(document.createTextNode(data.substr(0, result)));
new_node.appendChild(create_node(
document.createTextNode(data.substr(result, Stxt.length))));
data = data.substr(result + Stxt.length);
data_low = data_low.substr(result + Stxt.length);
}
new_node.appendChild(document.createTextNode(data));
}
} else {
highlight(Stxt, node);
}
}
}
function create_node(child) {
var node = document.createElement('span');
node.setAttribute('class', 'highlighted');
node.attributes['class'].value = 'highlighted';
node.appendChild(child);
return node;
}
This can be easily done with a regular expression to change the div's content. Here's a simple implementation :
var s = document.getElementById('s'); // your input
var div = document.getElementById('a'); // the div to change
var t = a.textContent || a.innerText;
s.onkeyup = function(){
div.innerHTML = this.value
? t.replace(new RegExp('('+this.value+')','ig'), '<span class=highlight>$1</span>')
: t;
};
Demonstration (click "Run with JS")
EDIT :
This more sophisticated version works even if you have tables and stuff :
var s = document.getElementById('s');
var div = document.getElementById('a');
function changeNode(n, r, f) {
f=n.childNodes; for(c in f) changeNode(f[c], r);
if (n.data) {
f = document.createElement('span');
f.innerHTML = n.data.replace(r, '<span class=found>$1</span>');
n.parentNode.insertBefore(f, n);
n.parentNode.removeChild(n);
}
}
s.onkeyup = function(){
var spans = document.getElementsByClassName('found');
while (spans.length) {
var p = spans[0].parentNode;
p.innerHTML = p.textContent || p.innerText;
}
if (this.value) changeNode(
div, new RegExp('('+this.value+')','gi')
);
};
Demonstration (click "Run with JS")
My Rangy library has support for this, although I admit it's quite a large script for just this one use.
Demo: http://rangy.googlecode.com/svn/trunk/demos/textrange.html
I made a demo that uses regex.
// Input element
var input = document.getElementById("highlighter"),
// Text container element
divText = document.getElementById("text"),
// using textContent property if it exists
textProp = ("textContent" in divText) ? "textContent" : "innerText",
// Getting text to discard html tags (delete line 6 and use divText.innerHTML if you want to keep the HTML tags)
originalText = divText[textProp];
function handler(){
// if Input.value is empty clear the highlights
if(!this.value){
divText.innerHTML = originalText;
return true;
}
// Regex to group the matches, with tags 'global' and 'case insensitive'
var regex = new RegExp("("+this.value+")", "ig");
// replace text with the new one ($1 refers to first group matched by regex)
divText.innerHTML = originalText.replace(regex, "<span class='highlight'>$1</span>");
};
// adding listener to input.. IE uses attachEvent method
input.addEventListener("keyup", handler, false);
JSFiddle DEMO
let keywords = $("#highlight").html(); //get replace text
let textBody = $("#textBody"); //replace body
//create regular expression //text without case change
let custfilter = new RegExp("(" + keywords + ")", "ig");
//replace with highlight
textBody.html(textBody.html().replace(custfilter, "<b>$1</b>"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<p id="textBody">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
<span id="highlight">IPSUM</span>