Say I have this HTML element:
<td>—</td>
When parsed by browsers, — is converted to an actual em-dash, like so:
<td>—</td>
How can I test for — without using other characters in my JavaScript code?
console.log(elem.innerHTML == "—"); // false
console.log(elem.textContent == "—"); // false
console.log(elem.innerHTML == "—"); // true
console.log(elem.textContent == "—"); // true
You could create a new DOM element, and compare the two:
/**
* Test that a DOM element's inner HTML is === —
*/
function mdashTest(el) {
var tempEl = document.createElement('div');
tempEl.innerHTML = '—';
return el.innerHTML === tempEl.innerHTML;
}
// Test it!
elem = document.getElementById('dash');
alert( mdashTest( elem ) );
<div id="dash">—</div>
The unicode equivalent of emdash is \u2014. You can use this unicode to compare with the html.
The default encoding for HTML meta is set to UTF so all the entities are converted to UTF-8. Read More https://developer.mozilla.org/en/docs/Web/HTML/Element/meta#Attributes
var dash = document.getElementById('dash').innerText;
alert(dash === '\u2014');
<div id="dash">—</div>
I suggest that:
through DOMParser()
function parseToText(code) {
return new DOMParser().parseFromString('<em>' + code + '</em>', "text/html").firstChild.textContent;
}
var is = document.getElementById('text').innerHTML == parseToText("—");
document.write("isEquals ", is, parseToText("—"));
<em id="text">—</em>
Or, with jQuery:
function parseToText(code) {
return $("<em>" + code + "</em>").html()
}
var isEquals = document.getElementById('text').innerText == parseToText("—");
document.write("isEquals ", isEquals);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<em id="text">—</em>
Or, with plain JavaScript:
function parseToText(code) {
return document.createRange().createContextualFragment(code).firstChild.textContent;
}
var isEquals = document.getElementById('text').innerText == parseToText("—");
document.write("isEquals ", isEquals);
<em id="text">—</em>
Related
What i have done:
function makeBold(strings) {
var myHTML = document.getElementsByTagName('body')[0].innerHTML;
myHTML = myHTML.replace(strings, '<b>' + strings + '</b>');
document.getElementsByTagName('body')[0].innerHTML = myHTML
}
this code works only for the paces where the texts are free from ant tags
Eg: <p class="ClassName">Some free text without any inner html elements</p>
But for sentences below this the above javascript function is not giving any result
Eg sentence which are not working:
<p class="Aclass"><span class="char-style-override-1">Starting from here, </span><span class="char-style-override-2">text resumes after the span tag</span><span class="char-style-override-1">. again text resumes.</span></p>
What I need
i need a functionality to make the above text bold when i pass that text into my js function. and by text i mean only
Starting from here,text resumes after the span tag. again text resumes.
when i call the above mentioned jas function like this
makeBold('Starting from here,text resumes after the span tag. again text resumes.');
nothing happens, the entire sentence does not gets bold nothing happens, because the js function only looks for the occurrence of that string and makes it bold, in my second example the text is mixed with html tags
so that the above mentioned text will get bold when i call my makebold function.
Please note that i dont have the id for the <p> , what i have is a couple of random strings stored in my db and load a couple of webpages, while doing so i want to bold the sentence/text from the webpage if is matches with my passed string from db
While doing my research i got a code to highlight text given to a js. this js function will select the exact text in the html page which is passed to the js function.
the second eg also works for this code. i.e i can select the exact string from the example by passing it to the function.
function selectText(text) {
if (window.find && window.getSelection) {
document.designMode = "on";
var sel = window.getSelection();
sel.collapse(document.body, 0);
while (window.find(text)) {
document.getElementById("button").blur();
document.execCommand("HiliteColor", false, "yellow");
sel.collapseToEnd();
}
document.designMode = "off";
} else if (document.body.createTextRange) {
var textRange = document.body.createTextRange();
while (textRange.findText(text)) {
textRange.execCommand("BackColor", false, "yellow");
textRange.collapse(false);
}
}
}
I tried to customize it so that instead of selecting the passed text, i tried to make it bold. but coudnt succed.
Please help me in getting this done. I am new to js.
I finally got a solution to your problem that works as you want it to (i. e. the function takes an arbitrary substring and marks anything that fits the substring bold while leaving the rest of the string untouched). If the string passed doesn't match any part of the string that you want to modify, the latter remains untouched.
Here goes (Beware: That JS section got really BIG!):
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test case for making arbitrary text bold</title>
<meta charset="UTF-8">
<script type="application/javascript">
// Takes two strings and attempts to intersect them (i. e. the end of p_str1
// must match the beginning of p_str2). The index into p_str1 is returned.
// If no intersection can be found, -1 is returned.
function intersectStrings(p_str1, p_str2)
{
var l_pos = -1;
do
{
l_pos = p_str1.indexOf(p_str2[0], l_pos + 1);
if(p_str1.substr(l_pos) == p_str2.substr(0, p_str1.length - l_pos))
// If the two substrings match, we found something. Return with the position.
break;
}
while(l_pos != -1);
return l_pos;
}
function makeBold(p_string)
{
var l_elem = document.getElementById('modify');
var l_html = l_elem.innerHTML;
var l_text = l_elem.innerText;
var l_aux = l_html.match(/<.+?>/g);
var l_here = l_text.indexOf(p_string);
var l_before;
var l_middle;
var l_behind;
if(typeof(p_string) != 'string')
throw "invalid argument";
// First of all, see whether or not we have a match at all. If no, we don't
// need to continue with this.
if(l_here == -1)
{
console.error('makeBold: Could not find desired substring ' + p_string + '! Stop...');
return;
}
// Take the plain text and split it into three distinct parts (l_middle is of
// interest for us here).
l_before = l_html.slice(0, l_here);
l_behind = l_html.slice(l_here + l_html.length);
l_middle = l_html.slice(l_here, l_here + l_html.length);
if(l_aux)
{
// If we have a set of markup tags, we need to do some additional checks to
// avoid generating tag soup.
let l_target = new Array();
let l_tag;
let l_nexttag;
let l_this;
let l_endpos = 0;
let l_in_str = false;
let l_start;
while(l_aux.length - 1)
{
l_tag = l_aux.shift();
l_target.push(l_tag);
l_nexttag = l_aux[0];
l_endpos = l_html.indexOf(l_nexttag, 1);
l_this = l_html.slice(l_tag.length, l_endpos);
l_html = l_html.slice(l_endpos);
// Skip the entire rigmarole if there are two adjacent tags!
if(l_tag.length == l_endpos)
continue;
if(!l_in_str)
{
if((l_start = l_this.indexOf(p_string)) != -1)
{
// If we find the entire passed string in a fragment of plain text, we can
// modify that, reassemble everything and exit the loop.
l_before = l_this.slice(0, l_start);
l_behind = l_this.slice(l_start + p_string.length);
l_middle = l_this.slice(l_start, l_start + p_string.length);
l_this = l_before + '<strong>' + l_middle + '</strong>' + l_behind;
l_target.push(l_this);
l_target.push(l_html);
l_html = l_target.join('');
console.info('makeBold: The passed string fit between two tags: Done!');
break;
}
// Take the possibility of having to scan across fragments into account. If
// that is the case, we need to piece things together.
if((l_start = intersectStrings(l_this, p_string)) != -1)
{
// Once we wind up here we have a partial match. Now the piecework starts...
l_before = l_this.slice(0, l_start);
l_middle = l_this.slice(l_start);
l_this = l_before + '<strong>' + l_middle + '</strong>';
l_target.push(l_this);
console.info('makeBold: Found starting point of bold string!');
l_in_str = true;
}
else
{
// Nothing to do: Push the unmodified string.
l_target.push(l_this);
}
}
else
if((l_endpos = intersectStrings(p_string, l_this)) == -1)
{
// We haven't arrived at the end position yet: Push the entire segment with
// bold markers onto the stack.
l_this = '<strong>' + l_this + '</strong>';
l_target.push(l_this);
}
else
{
// We have an end position: Treat this fragment accordingly, wrap everything up
// and exit the loop.
l_behind = l_this.slice(l_endpos + 1);
l_middle = l_this.slice(0, l_endpos + 1);
l_this = '<strong>' + l_middle + '</strong>' + l_behind;
l_target.push(l_this);
l_target.push(l_html);
l_html = l_target.join('');
console.info('makeBold: Found the end part: Done!');
break;
}
}
}
else
l_html = l_before + '<strong>' + l_middle + '</strong>' + l_behind;
l_elem.innerHTML = l_html;
}
</script>
</head>
<body>
<header><h1>Test case for making arbitrary text bold by using JavaScript</h1></header>
<main>
<p id="modify"><span class="char-style-override-1">Starting from here, </span><span class="char-style-override-2">text resumes after the span tag</span><span class="char-style-override-1">. again text resumes.</span></p>
</main>
<script type="application/javascript">
// makeBold('Starting from here, text resumes after the span tag. again text resumes.');
// makeBold('from here, text resumes');
// makeBold('resumes after the span');
makeBold('text resumes after the span tag');
</script>
</body>
</html>
Unfortunately this job couldn't be done with a short section, because you need to take various cases into account that need to be handled individually. The control logic that I have come up with addresses all these concerns.
See the annotations in the JS that I have made for details.
Jquery when tag string contains dot. When hard coded, query get expected value, but if tag is obtained with a function and concatenated, query fails.
var tagWithDot = getTag(...) // tagWithDot === 'tag.withdot'
console.log(tagWithDot === 'tag.withdot') // true
console.log('#' + tagWithDot === '#tag.withdot') // true
console.log('#' + tagWithDot.replace('.', '\\.') === '#tag\\.withdot') // true
console.log($('#' + tagWithDot.replace('.', '\\.')) === $('#tag\\.withdot')) // false
console.log($(('#' + tagWithDot.replace('.', '\\.'))) === $('#tag\\.withdot')) // false
Instead of replacing manually . with \\. stuff you could use jQuery's escapeSelector
var tagWithDot = "#tag.withdot";
console.log( $.escapeSelector(tagWithDot) );
<script src="//code.jquery.com/jquery-3.1.0.js"></script>
Using the replace('.','\\.') seems to work here.
Be aware though if you use $.escapeSelector you don't include the # or the # gets escaped too, and is likely not what you wanted.
var tagWithDot = "#tagwith.dot";
setTimeout(function () {
$(tagWithDot.replace('.','\\.')).text('Replaced');
}, 2000);
<script src="//code.jquery.com/jquery-3.1.0.js"></script>
<div>Wait 2 seconds and replace text in div with id #tagwith.dot<div>
<br>
<div id="tagwith.dot">This should get replaced</div>
In my project I have some html with comments surrounding text so I can find the text between particular comments and replace that text whilst leaving the comments so I can do it again.
I am having trouble getting the regex to work.
Here is an html line I am working on:
<td class="spaced" style="font-family: Garamond,Palatino,sans-serif;font-size: medium;padding-top: 10px;"><!--firstname-->Harrison<!--firstname--> <!--lastname-->Ford<!--lastname--> <span class="spacer"></span></td>
Now, here is the javascript/jquery that I have at the moment:
var thisval = $(this).val(); //gets replacement text from a text box
var thistoken = "firstname";
currentTemplate = $("#gentextCodeArea").text(); //fetch the text
var tokenstring = "<!--" + thistoken + "-->"
var pattern = new RegExp(tokenstring + '\\w+' + tokenstring,'i');
currentTemplate.replace(pattern, tokenstring + thisval + tokenstring);
$("#gentextCodeArea").text(currentTemplate); //put the new text back
I think I'm pretty close, but I don't have the regex right yet.
The regex ought to replace the firstname with whatever is entered in the textbox for $thisval (method is attached to keyup procedure on textbox).
Using plain span tags instead of comments would make things easier, but either way, I would suggest not using regular expressions for this. There can be border cases that may lead to undesired results.
If you stick with comment tags, I would iterate over the child nodes and then make the replacement, like so:
$("#fname").on("input", function () {
var thisval = $(this).val(); //gets replacement text from a text box
var thistoken = "firstname";
var between = false;
$("#gentextCodeArea").contents().each(function () {
if (this.nodeType === 8 && this.nodeValue.trim() === thistoken) {
if (between) return false;
between = true;
} else if (between) {
this.nodeValue = thisval;
thisval = '';
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
New first name: <input id="fname">
<div id="gentextCodeArea">
<!--firstname-->Harrison<!--firstname-->
<!--lastname-->Ford<!--lastname-->
<span class="spacer"></span></div>
What went wrong in your code
By using text() you don't get the comment tags. To get those, you need to use html() instead
replace() does not mutate the variable given in the first argument, but returns the modified string. So you need to assign that back to currentTemplate
It would be better to use [^<]* instead of \w+ for matching the first name, as some first names have non-letters in them (hyphen, space, ...), and it may even be empty.
Here is the corrected version, but I insist that regular expressions are not the best solution for such a task:
$("#fname").on("input", function () {
var thisval = $(this).val(); //gets replacement text from a text box
var thistoken = "firstname";
currentTemplate = $("#gentextCodeArea").html(); //fetch the html
var tokenstring = "<!--" + thistoken + "-->"
var pattern = new RegExp(tokenstring + '[^<]*' + tokenstring,'i');
currentTemplate = currentTemplate.replace(pattern, tokenstring + thisval + tokenstring);
$("#gentextCodeArea").html(currentTemplate); //put the new text back
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
New first name: <input id="fname">
<div id="gentextCodeArea">
<!--firstname-->Harrison<!--firstname-->
<!--lastname-->Ford<!--lastname-->
<span class="spacer"></span></div>
here is a function which will generate an appropriate Regular expression:
function templatePattern(key) {
return new RegExp(`<!--${key}-->(.*?)<!--${key}-->`);
}
the (.*?) means "match as little as possible," so it will stop at the first instance of the closing tag.
Example:
'<!--firstname-->Harrison<!--firstname--> <!--lastname-->Ford<!--lastname-->'
.replace(templatePattern('firstname'), 'Bob')
.replace(templatePattern('lastname'), 'Johnson') // "Bob Johnson"
$(function(){
function onKeyUp(event)
{
if(event.which === 38) // if key press was the up key
{
$('.firstname_placeholder').text($(this).val());
}
}
$('#firstname_input').keyup(onKeyUp);
});
input[type=text]{width:200px}
<input id='firstname_input' type='text' placeholder='type in a name then press the up key'/>
<table>
<tr>
<td ><span class='firstname_placeholder'>Harrison</span> <span class='lastname_placeholder'>Ford</span> <span class="spacer"></span></td>
</tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
// Function for setting text of an element:
function setText(elementId, message)
{
'use strict';
if ( (typeof elementId == 'string')&& (typeof message == 'string') )
{
var output = $(elementId);
if (output.textContent !== undefined)
{
output.textContent = $(elementId).string;
}
else
{
output.innerText =$(elementId).string ;
}
} // End of main if.
} // End of setText() function.
I need help with this code, I need to define a function name the setText() function as shown below, when I run this code in JS Bin the page shows the code won't run, I couldn't find where the error is. Can anyone give me a hint?
Your type checking for message is unnecessary, but in case you want to keep it:
function setText(elementId, message){
if((typeof elementId == 'string') && (typeof message == 'string')){
document.getElementById(elementId).innerHTML = message;
}
}
setText("foo", "1")
setText("foobar", "2")
setText("bar", "3")
setText("barfoo", "4")
<p id="foo"></p>
<p id="foobar"></p>
<p id="bar"></p>
<p id="barfoo"></p>
You can do it using JavaScript prototypical way. This is little advanced.
HTML:
<span id="spanText"> Your sample Text </span>
First of all augment the type by this code:
/*
Augmenting type
*/
Function.prototype.addMethod = function(funcName, funcBody){
if(!this.prototype[funcName]){
this.prototype[funcName] = funcBody;
return this;
}};
String.addMethod("setText", function(text){
document.getElementById(this).textContent = text;
});
var elementId = "spanText";
elementId.setText("kkkkkkkkkkk");
Load this JS below your HTML file.
You are able to add any of your custom string, number, array method by this way.
See the complete example here:
https://jsfiddle.net/dmsbilas/wu3cd88w/
I wanted an if statement to show an image or html code depending on the webpage. I got this far and the html table doesn't appear at all (appears blank):
<script type="text/javascript">
<!--
var url = document.location.pathname;
if( document.location.pathname == '/tagged/photos' ){
document.innerHTML('<table><tr> hello </tr> </table>');
}
if( document.location.pathname == '/tagged/news' ){
document.write("<b>This is my news page</b>");
}
//-->
</script>
I'd do it slightly differently
Add both markup to the page, and show/hide as approproate:
<table id="table"><tr> hello </tr></table>
<span id="title"><b>This is my news page</b></span>
<script type="text/javascript">
$(function(){
var url = document.location.pathname;
if( url == '/tagged/photos' ){
$('#title').hide();
$('#table').show();
}
if( url == '/tagged/news' )
{
$('#title').show();
$('#table').hide();
}
})
</script>
I have assumed you have JQuery since it is tagged
You're using document.innerHTML, which doesn't exist. At the very least, you need to get a proper element:
document.documentElement.innerHTML = 'some HTML';
Setting aside everything else that's wrong with this approach, I'm not sure, why would you use document.write() in one branch and someElement.innerHTML in the other.
I'd suggest the following approach:
function pagePopulate() {
// you're looking at the pathname, use a sensible (meaningful) variable-name:
var pagePath = document.location.pathname,
// this is a map, of the relationship between page and content:
pathToContent = {
// pagename : html
'photos': '<table><tbody><tr><td>photos page</td></tr></tbody></table>',
'news': '<b>This is the news page</b>'
},
// getting a reference to the <body> element:
body = document.querySelector('body');
// setting the innerHTML of the <body>,
// if pagePath = 'tagged/photos', splitting with '/' would return:
// ['tagged','photos'], calling 'pop()' returns the last element of the array
// 'photos', which returns that string to the square brackets, resulting in:
// pathToContent['photos'], which would yield the '<table>...</table>' HTML.
// if that call resulted in an undefined, or falsey, value, then the default
// (the string *after* the '||' would be used instead:
body.innerHTML = pathToContent[pagePath.split('/').pop()] || '<h2>Something went wrong</h2><img src="http://blog.stackoverflow.com/wp-content/uploads/error-lolcat-problemz.jpg" />';
}
// calling the function:
pagePopulate();
References:
|| (logical 'or' operator).
Array.prototype.pop().
document.querySelector().
String.prototype.split().