I know that document.createTextNode(text) in JS is for creating text only, but is there a way to insert into it two span elements?
I have two spans created like this:
/*
* span with wrong (old) medical word
*/
// Replacement node
var span_old = $('<span />', {
'class': pluginName + '-autoword-highlight wrong wrong-medical-word-'+i
});
// If we have a new match
if (i !== c) {
c = i;
replaceElement = span_old;
}
span_old
.text(fill)
.data({
'firstElement': replaceElement,
'word': oldWord
});
/*
* span with new - corrected medical word
*
*/
// Replacement node
var span_new = $('<span />', {
'class': pluginName + '-autoword-highlight corrected-medical-word-'+i
});
// If we have a new match
if (i !== c) {
c = i;
replaceElement = span_new;
}
span_new
.text(replaceFill)
.data({
'firstElement': replaceElement,
'word': replaceFill
});
var wrong_and_corrected_medical_text = span_old[0] + span_new[0];
return document.createTextNode(wrong_and_corrected_medical_text);
Expected result is
old text - new text
and I need to return Text Node as always. Is there a hack to stringify the span elements or other way? Thanks!
Is this what you need?
var wrong_and_corrected_medical_text = span_old.text() + span_new[0].text();
Edit:
So you need the html to be returned as text, Please try this.
var wrong_and_corrected_medical_text = span_old.prop('outerHTML') + span_new.prop('outerHTML');
Reference:
https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
Related
I have the following java userscript:
function highlightWord(word) {
var xpath = "//text()[contains(., '" + word + "')]";
var texts = document.evaluate(xpath, document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (n = 0; n < texts.snapshotLength; n++) {
var textNode = texts.snapshotItem(n);
var p = textNode.parentNode;
var a = [];
var frag = document.createDocumentFragment();
textNode.nodeValue.split(word).forEach(function(text, i) {
var node;
if (i) {
node = document.createElement('span');
node.style.backgroundColor = 'lightgreen';
node.appendChild(document.createTextNode(word));
frag.appendChild(node);
}
if (text.length) {
frag.appendChild(document.createTextNode(text));
}
return a;
});
p.replaceChild(frag, textNode);
}
}
highlightWord('office');
Would anyone be able to help me with finding a solution to only match the exact text of the highlightWord's that I add? For example, I want it to only match "office" and not "officer".
Thanks!
This answer
https://stackoverflow.com/a/2994336/2707021
should help. Essentially you need to apply word boundaries to the pattern match string on this line
var xpath = "//text()[contains(., '" + word + "')]";
You need to change the following line of your code
textNode.nodeValue.split(word).forEach(function(text, i) {
into the one shown below. This will highlight, only the word that you mention.
textNode.nodeValue.split(RegExp("\\b" + word + "\\b")).forEach(function (text, i) {
The XPath just extracts the entire text, the actual string search in your code happens in the above statement.
I simply try to replace the selected text from an input field e.g from a textarea, with another text.
E.g. if i select a part of the text inside the input field and click the Button CENTER, then the selected text should be wrapped in <center></center>.
I found this "solution" from 2009 which seems to be outdated, I tried it with Chrome and Firefox and I get the info that my browser is not supported.
Is there another way to achieve this? It should work at least with Firefox and Chrome.
Try this:
function getSel() // javascript
{
console.log("test");
// obtain the object reference for the textarea>
var txtarea = document.getElementById("mytextarea");
// obtain the index of the first selected character
var start = txtarea.selectionStart;
// obtain the index of the last selected character
var finish = txtarea.selectionEnd;
//obtain all Text
var allText = txtarea.value;
// obtain the selected text
var sel = allText.substring(start, finish);
//append te text;
var newText=allText.substring(0, start)+"<center>"+sel+"</center>"+allText.substring(finish, allText.length);
console.log(newText);
txtarea.value=newText;
}
https://jsfiddle.net/qpw1eemr/1/
Here is one simple example
$(function() {
$('textarea').select(function(event) {
var elem = $(this);
var start = elem.prop("selectionStart");
var end = elem.prop("selectionEnd");
var prefixStr = elem.text().substring(0, start);
var sufixStr = elem.text().substring(end, elem.text().length);
var selectedStr = elem.text().substring(start, end);
function transform(str) {
return '<center>' + str + '</center>'
}
elem.text(prefixStr + transform(selectedStr) + sufixStr);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea>iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii</textarea>
// hope this would be usefull
// i used these codes for auto completing the texts in textarea.
// other methods change all matching items before the selected text
// but this affects only the text where caret on.
// at first, i divided textarea.value into 3 pieces. these are ;
// p1; until the 'searched' item, p2 after 'searched' item
// and pa = new item that will replaced with 'searched' item
// then, i combined them together again.
var tea = document.getElementById(targetTextArea);
caretPosition = tea.selectionStart - ara.length; //ara=searched item
p1 = tea.value.substring(0,caretPosition);
console.log('p1 text : ' + p1);
p2 = tea.value.substring(caretPosition+ara.length,tea.value.length);
console.log('p2 text : ' + p2);
pa = yeni; //new item
console.log('pa text : ' + pa);
tea.value = p1 + pa + p2;
tea.selectionStart = caretPosition + yeni.length;
tea.selectionEnd = caretPosition + yeni.length;
tea.focus();
i install ckeditor and after i install that code (bbcode plugin):
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/bbcode/plugin.js
and i install that code (justify plugin):
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/justify/plugin.js
and after i install that plugins all work but when i click center or right or left in the justify plugin - the bbcode plugin not support the justify mod.
anybody can help me build a simple code in the bbcode plugin support the justify mod?
its for forum and i need only bbcode.
i need code like :
if <span style=\"text-align: center;\">texthere</span>
its replace to [center]texthere[/center]
or something like that.
thx for the help.
i try this code:
(function() {
CKEDITOR.plugins.add('bbcode',
{
requires: ['htmlwriter'],
init: function(editor) {
editor.dataProcessor = new CKEDITOR.htmlDataProcessor(editor);
editor.dataProcessor.toHtml = toHtml;
editor.dataProcessor.toDataFormat = toDataFormat;
}
});
var toHtml = function(data, fixForBody) {
// Convert < and > to their HTML entities.
data = data.replace(/</g, '<');
data = data.replace(/>/g, '>');
// Convert line breaks to <br>.
data = data.replace(/(?:\r\n|\n|\r)/g, '<br>');
// [url]
data = data.replace(/\[url\](.+?)\[\/url]/gi, '$1');
data = data.replace(/\[url\=([^\]]+)](.+?)\[\/url]/gi, '$2');
// [b]
data = data.replace(/\[b\](.*?)\[\/b]/gi, '<b>$1</b>');
// [i]
data = data.replace(/\[i\](.*?)\[\/i]/gi, '<i>$1</i>');
// [u]
data = data.replace(/\[u\](.*?)\[\/u]/gi, '<u>$1</u>');
// [h3]
data = data.replace(/\[h3\](.*?)\[\/h3](?:<br ?\/?>|\n)?/gi, '<h3>$1</h3>');
// [img]
data = data.replace(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />');
data = data.replace(/\[img class=([\w-]+)\](.*?)\[\/img\]/gi,'<img class="$1" src="$2" />');
// [quote]
data = data.replace(/\[quote\]/gi, '<blockquote>');
data = data.replace(/\[\/quote]/gi, '</blockquote>');
// [poster]
data = data.replace(/\[poster\](.+?)\[\/poster]/gi, '<div class="text-poster">$1</div>');
// [code]
data = data.replace(/\[code\]/gi,'<code>');
data = data.replace(/\[\/code\]/gi,'</code>');
// [size]
data = data.replace(/\[size=(\d+)\](.*?)\[\/size\]/gi,'<span style="font-size: $1px">$2</span>');
// [color]
data = data.replace(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<span style="color: $1">$2</span>');
// [center]
data = data.replace(/\[align=(.*?)\](.*?)\[\/align\]/gi,'<span style="align: center">$2</span>');
// [right]
data = data.replace(/\[align=(.*?)\](.*?)\[\/align\]/gi,'<span style="align: right">$2</span>');
// [left]
data = data.replace(/\[align=(.*?)\](.*?)\[\/align\]/gi,'<span style="align: left">$2</span>');
// smileys
for (var i = 0; i < this.editor.config.smiley_images.length; i++) {
var smiley = this.editor.config.smiley_images[i].replace('.gif', '');
if (data.indexOf(smiley) != -1) {
data = data.split(smiley).join('<img src="'+ this.editor.config.smiley_path + this.editor.config.smiley_images[i] + '" class="smiley" />');
}
}
return data;
};
var toDataFormat = function(html, fixForBody ) {
if (html == '<br>' || html == '<p><br></p>') {
return "";
}
// Convert <br> to line breaks.
html = html.replace(/<br><\/p>/gi,"\n");
html = html.replace(/<br(?=[ \/>]).*?>/gi, '\r\n');
html = html.replace(/<p>/gi,"");
html = html.replace(/<\/p>/gi,"\n");
html = html.replace(/ /gi," ");
// [url]
html = html.replace(/<a .*?href=(["'])(.+?)\1.*?>(.+?)<\/a>/gi, '[url=$2]$3[/url]');
// [b]
html = html.replace(/<(?:b|strong)>/gi, '[b]');
html = html.replace(/<\/(?:b|strong)>/gi, '[/b]');
// [i]
html = html.replace(/<(?:i|em)>/gi, '[i]');
html = html.replace(/<\/(?:i|em)>/gi, '[/i]');
// [u]
html = html.replace(/<u>/gi, '[u]');
html = html.replace(/<\/u>/gi, '[/u]');
// [h3]
html = html.replace(/<h3>/gi, '[h3]');
html = html.replace(/<\/h3>/gi, '[/h3]\n');
// smileys
html = html.replace(/<img .*?src=(["']).+?(:.+?:?|(\W)_\3).gif\1.*?>/gi, '$2');
// [img]
html = html.replace(/<img .*?class=(["'])([\w-]+)\1.*?src=(["'])(.+?)\3.*?>/gi, '[img class=$2]$4[/img]');
html = html.replace(/<img .*?src=(["'])(.+?)\1.*?class=(["'])([\w-]+)\3.*?>/gi, '[img class=$4]$2[/img]');
html = html.replace(/<img .*?src=(["'])(.+?)\1.*?>/gi, '[img]$2[/img]');
// [quote]
html = html.replace(/<blockquote>/gi, '[quote]');
html = html.replace(/\n*<\/blockquote>/gi, '[/quote]');
// [poster]
html = html.replace(/<div class="text-poster">([\s\S]+?)<\/div>/gi, '[poster]$1[/poster]');
// [code]
html = html.replace(/<code>/gi, '[code]');
html = html.replace(/<\/code>/gi, '[/code]');
// [color]
html = html.replace(/<span style="color: ?(.*?);?">(.*?)<\/span>/gi,"[color=$1]$2[/color]");
// [size]
html = html.replace(/<span style="font-size: ?(\d+)px;?">(.*?)<\/span>/gi,"[size=$1]$2[/size]");
// Remove remaining tags.
html = html.replace(/<[^>]+>/g, '');
// Restore < and >
html = html.replace(/</g, '<');
html = html.replace(/>/g, '>');
// Restore (and )
html = html.replace(/%28/g, '(');
html = html.replace(/%29/g, ')');
// Restore %20
html = html.replace(/%20/g, ' ');
return html;
}
})();
but this code not work.
i think this code for ckeditor 3 or something ..
I meet the same problem today and I managed to make it work by modifying the plugin.js in the bbcode plugin folder
Line 29:
var bbcodeMap = { b: 'strong', u: 'u', i: 'em', color: 'span', size: 'span', quote: 'blockquote', code: 'code', url: 'a', email: 'span', img: 'span', '*': 'li', list: 'ol',center:'div',left:'div',right:'div'},
and Line around 151-160:
// as "span" with an attribute marker.
if ( part == 'email' || part == 'img' )
attribs[ 'bbcode' ] = part;
//adding this to deal with the align issues
if (part == 'center' || part == 'left' || part == 'right'){
styles ['text-align'] = part;
attribs.style = serializeStyleText( styles );
}
this.onTagOpen( tagName, attribs, CKEDITOR.dtd.$empty[ tagName ] );
And finally line start from 658:
if ( tagName in convertMap )
tagName = convertMap[ tagName ];
//adding div element
else if (tagName == 'div'){
if ( ( value = style['text-align'] ) ) {
tagName = value;
value = '';
}
}
else if ( tagName == 'span' ) {
if ( ( value = style.color ) ) {
tagName = 'color';
value = CKEDITOR.tools.convertRgbToHex( value );
....
At least this works for me.
This is kind of weired because the Justify Plugin is adding 'div' elements instead of 'span'. Maybe you can also modify it to satisfy your 'span' requirement.
can we get the word on which a right click was made and x,y coordinates of that word ?
i tried:
document.onclick=getTextOnClick;
function getTextOnClick(e)
{
console.log(e);
if (window.getSelection) {
txt = window.getSelection();
console.log(">>>"+txt);
} else if (document.getSelection) {
// FireFox
txt = document.getSelection();
console.log(txt);
} else if (document.selection) {
// IE 6/7
txt = document.selection.createRange().text;
console.log(txt);
}
}
Now this code works if i select some text, but can i get the same when i just eight click or click on certain word ? And event object is giving me coordinates of click. can i get coordinates of the word on which the click was made ? Plz help
This can be done with pure JavaScript, assuming your container contain "simple" words only:
window.onload = function() {
var oDiv = document.getElementById("Container");
var rawHTML = oDiv.innerHTML;
var arrWords = rawHTML.split(" ");
oDiv.innerHTML = "";
for (var i = 0; i < arrWords.length; i++) {
var curWord = arrWords[i];
var curSpan = document.createElement("span");
curSpan.innerHTML = curWord;
if (i < (arrWords.length - 1))
curSpan.innerHTML += " ";
curSpan.onclick = WordClicked;
curSpan.oncontextmenu = WordClicked;
oDiv.appendChild(curSpan);
}
};
function WordClicked() {
var word = this.innerHTML;
alert("You clicked: " + word);
return false;
}
Live test case - handles both left and right click.
One way that comes to mind is putting each word in a span of its own. Apart from that, I think it will be difficult to find a solution that runs consistently on all browsers.
Thy this ?
Text ->
<div id="foo">Hello I am a text. I have no clue why I am here or
what I am good for, but I have QUOTES and other things I can offer.</div>
jQuery ->
$('#foo').contents().each(function(_, node) {
var nodelist = node.textContent.split(/\s/).map(function( word ) {
return $('<span>', {
text: word + ' ',
click: function() {
alert( $(this).text() );
}
}).get(0);
});
$('#foo').empty().append(nodelist);
});
Demo -> http://jsfiddle.net/qLuEF/
I have a regular expression task at hand and can really use some help.
Say I have a text like below:
To Sherlock Holmes she is always <i>THE</i> woman.
I need to enclose each character in a span tag, with exception of HTML tags. For example, the text above would be:
<span>T</span><span>o</span><span> </span><span>S</span><span>h</span>
<span>e</span><span>r</span><span>l</span><span>o</span><span>c</span>
<span>k</span><span> </span><span>H</span><span>o</span><span>l</span>
<span>m</span><span>e</span><span>s</span><span> </span><span>s</span>
<span>h</span><span>e</span><span> </span><span>i</span><span>s</span>
<span> </span><span>a</span><span>l</span><span>w</span><span>a</span>
<span>y</span><span>s</span><span> </span><i><span>T</span><span>H</span>
<span>E</span></i><span> </span><span>w</span><span>o</span><span>m</span>
<span>a</span><span>n</span><span>.</span>
Note that:
each character is enclosed in a span
tag, even a space
HTML tag, <i></i> is not
Any suggestion is welcome.
Thanks!
This job is better handled by DOM interactions. The following two utility functions will work help wrapping each character in the given text with a span tag.
/**
* recursively get all text nodes as an array for a given element
*/
function getTextNodes(node) {
var childTextNodes = [];
if (!node.hasChildNodes()) {
return;
}
var childNodes = node.childNodes;
for (var i = 0; i < childNodes.length; i++) {
if (childNodes[i].nodeType == Node.TEXT_NODE) {
childTextNodes.push(childNodes[i]);
}
else if (childNodes[i].nodeType == Node.ELEMENT_NODE) {
Array.prototype.push.apply(childTextNodes, getTextNodes(childNodes[i]));
}
}
return childTextNodes;
}
/**
* given a text node, wrap each character in the
* given tag.
*/
function wrapEachCharacter(textNode, tag) {
var text = textNode.nodeValue;
var parent = textNode.parentNode;
var characters = text.split('');
characters.forEach(function(character) {
var element = document.createElement(tag);
var characterNode = document.createTextNode(character);
element.appendChild(characterNode);
parent.insertBefore(element, textNode);
});
parent.removeChild(textNode);
}
Now given some piece of HTML, we will create a DOM representation of it, and then retrieve all text nodes from it using the first function - getTextNodes. Once we have all the text nodes, we can pass each one of them to the second function - wrapEachCharacter.
// create a wrapper element that will hold our HTML.
var container = document.createElement('div');
container.innerHTML = "To Sherlock Holmes she is always <i>THE</i> woman.";
// get all text nodes recursively.
var allTextNodes = getTextNodes(container);
// wrap each character in each text node thus gathered.
allTextNodes.forEach(function(textNode) {
wrapEachCharacter(textNode, 'span');
});
An example is posted here.
Something along this line should do the trick
txt = txt.replace (/(<.*?>)|(.)/g, function (m0, tag, ch) {
return tag || ('<span>' + ch + '</span>');
});
Don't use a regex, just loop over the string using a for loop:
var s = 'To Sherlock Holmes she is always <i>THE</i> woman.';
var out = '';
for (var z = 0; z < s.length; ++z) {
var ch = s.charAt(z);
if (ch == '<') {
while (ch != '>') {
out += ch;
ch = s.charAt(++z);
}
out += ch;
continue;
}
out += '<span>' + ch + '</span>';
}
alert(out);