Get full (and original) text of an HTML element - javascript

Edit: It looks like we identified the solution to this problem via the comments -- which is achieved by getting value of the .outerHTML property. However, it still appears that at least Firefox and Chrome "normalize" original source code when outerHTML is used. For example, outerHTML of
<div id = "a"> <!-- string is 14 characters long //-->
still returns
<div id="a"> <!-- string is 12 characters long //-->
Apparently, the problem would be considered solved if the formatting of the resulting string would match that of the original HTML source code. Ah! Why must outerHTML adjust the original value?
--- Having said this: ---
I'm looking for a solution to get full text of a clicked HTML tag.
Starting point examples (note intentional, legal but mangled formatting):
<div id = "a" style ="color: blue ;">text</div>
// Returns: div
var doc = document.getElementById("id").tagName;
// Returns: array of attribute name/value pair (without = or ")
var attrs = document.getElementById("id").attributes;
How would we go about generating the following text string, when element #a is clicked:
<div id = "a" style= "color: blue ;">
I seem to have not found a solution for this as of yet.
What's this for?
Ultimately, the goal is to determine the length in characters of the arbitrary contents of a tag. Assuming it can be edited in any way that produces acceptable HTML output. For example, the two cases below should return:
<div id=a style="color:blue"> // 28
<div id = "a" style= "color: blue ;"> // 36
Counting is the easy part. It's getting the actual string of that tag, just as it appears in the source code, that is the problem.

Have you tried this?
document.getElementById('a').outerHTML
But this doesn't work in every browser i guess

Use outerHTML to get the full tag and then strip out everything after the open tag.
var openTag = document.getElementById("a").outerHTML.split(">")[0] + ">";

This seems to do what you want:
http://jsfiddle.net/abalter/c3eqnLrc/
html:
<div id="a" class="find-my-length" style="color:blue">First One</div>
<div id="a " class="find-my-length" style= "color: blue ; " > Second One </div >
JavaScript:
$('.find-my-length').on('click', function () {
var htmlString = $(this).prop('outerHTML');
alert(htmlString + " has " + htmlString.length + " characters.");
});
Note: The one thing that doesn't get counted is spaces between attributes. Spaces within attributes are counted.
From: Get selected element's outer HTML
What about: prop('outerHTML')?
var outerHTML_text = $('#item-to-be-selected').prop('outerHTML');
And to set:
$('#item-to-be-selected').prop('outerHTML', outerHTML_text);

Related

Recognize character inside div and add class javascript

I am trying to recognize character inside div and add to all the matches class.
Example :
> Kapetown > China Town >London > Washington
I want to recognize the character > and give all of them class
I tried to do this
if (sign.indexOf("$") >= 0) {
//remove the sign
}
Here is a trick you can use:
var a = '> Kapetown > China Town >London > Washington' //get the text from document here
a = a.split('>');
a = a.join('<span class="myClass">></span>');
Now you can replace "a" in your document.
This is just a trick you can use in your case. Maybe this will help you.
I assume that there is only text inside the targeted div
$(document).ready(function() {
// get the target element
var breadcrumbs = $('#breadcrumbs')
// get all text of that element. Note: this will remove all
// HTML tag and get only the text
var str = breadcrumbs.text()
// a regEx to find all occurrences of ">" sign
// and wrap them with span.myClass
var strHtml = str.replace(/\>/g, "<span class='myClass'>></span>");
// push the replaced string back to the targeted element
breadcrumbs.html(strHtml)
})
.myClass {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.2/jquery.min.js"></script>
<div id="breadcrumbs">> Kapetown > China Town >London > Washington</div>
If I understand your problem correctly, then you have a particular HTML like so:
<div id="abc">
> Capetown > China > London > Washington
</div>
and you want it to be lets say something like this:
<div id="abc">
<span class="some-class">></span> Capetown <span class="some-class">></span> China <span class="some-class">></span> London <span class="some-class">></span> Washington
</div>
Then by vanilla javascript you could achieve this via Regex. Here is how I would do it if the HTML was like the example I proposed:
let content = document.getElementById('abc').textContent.replace(/>/g, '<span class="some-class">></span>');
document.getElementById('abc').innerHTML = content;
What I am doing here is that with document.getElementById('abc').textContent, I am getting the text content that is inside <div id="abc">...</div> and I am storing this text content in a mutable variable content.
Then I used the String.prototype.replace method of JavaScript to replace the required character (in our case it is the ">" character). The String.prototype.replace method accepts two parameters: a pattern and the replacement string. read about the replace method here
The character I want to select is ">". So using Regex the pattern I want to match is />/. Now just using this expression will only match the first instance of ">". So I give it a global parameter to match all occurrences of ">" by />/g.
Now we want to give it a class. So I decide to use the inline HTML element <span> to avoid any changes in the DOM layout. Now for the replacement substring, I use <span class="some-class">></span>. The > is the HTML code for the ">" sign. Lets include these two parameters in our String.prototype.replace method as content.replace(/>/g, '<span class="some-class">></span>');
When executed, the variable content now contains our required character with a class. Next, I replaced the content of <div id="abc">...</div> by the content variable with document.getElementById('abc').innerHTML = content;. I used the .innerHTML property because we have included some HTML in our replacement string.
If this is what you wanted then hope this helps.
use can use {'>'} for react
example:
<div className='row'>
{route[0]} {'>'} {route[1]} {'>'} {route[2]}
</div>
where route = ["home","products","productID"];

Spacing different in original html rendering vs dynamic JS rendering

Here is a small part of my page:
<a href="#" onclick="PolicyViolation(<%: ViewBag.DeviceData[i].DeviceID%>); return false;">
<span class="policyViolationsNumber"><%= ViewBag.DeviceData[i].ViolationCount%></span>
<span>Policy Violations</span>
</a>
This renders out to have some space between the two spans.
In code, we update this in JS:
var spanViolationNumber = $('<span>')
.html(statusModel.Violations)
.addClass('policyViolationsNumber');
var spanViolationString = $('<span>')
.html('<%=ServiceSite.Resources.Resources.DEVICES_POLICY_VIOLATIONS%>');
var imageTag = $('<img>')
.attr('src', '/Content/images/error_error.png')
.attr('align', 'absmiddle');
var anchorTag = $('<a href="#">')
.append(spanViolationNumber)
.append(spanViolationString);
cell.empty();
cell.append(imageTag)
.append(anchorTag);
However, this renders out with no space between the spans. I've seen small issues like this before but never figured out what it is. You can ignore the image tag stuff, it is irrelevant.
EDIT:
Didn't know about this, I guess it's expected behaivor: http://jsfiddle.net/2MMuA/
The extra space is happening because of the way you are formatting your HTML.
The "span" tag is an inline HTML element. This basically means you need to treat it just as you would treat text on the page.
<span>Hello</span> <span>World</span>
<!-- Prints Hello World -->
<span>Hello</span>
<span>World</span>
<!-- Prints Hello World
The line break is where your extra space is coming from. -->
<span>Hello</span><span>World</span>
<!-- prints HelloWorld
This is how the ".append()" function is formatting the HTML.
It adds it literally right after the last character in the HTML. -->
In order to normalize this across the two different techniques, you either have to butt your "span" tags right up next to each other so the HTML doesn't add an extra space...
<span></span><span></span>
..or you need to manually add the space in your ".append()" function.
obj.append(' ' + spanTag);
I hope that helps!
Perhaps you could clarify .. are you talking about there being space between these spans?
<span class="policyViolationsNumber">12</span>
<span>Policy Violations</span>
Either way I would look at adding some padding or margin to your css to insure you get the space that you want OR at minimum (though not recommended) use an HTML encoded space like so
There is most likely spaces between your spans. If you put the spans exactly next to each other then there should be no spaces.
<span></span><span></span>

HTML textarea ignores 1st new line character, why?

Could you explain why this:
<script type="text/javascript">
document.write("<textarea cols='10' rows='10'>" + "\nhello\nbabe\n" + "</textarea>");
</script>
renders a textarea with one new line at the bottom, but NO new line at the top?
Tested IE8, FF11, Safari 5.1, Chrome 24
And it's not a JS issue, even when you write HTML in page you get the same result, i.e.
<textarea cols='10' rows='10'>
hello
babe
</textarea>
The 1st new line is still missing!!!
I need to add another new line at the top in order to show one:
document.write("<textarea cols='10' rows='10'>" + "\n\nhello\nbabe\n" + "</textarea>");
When writing inside of XHTML use proper entities.
<textarea>
hello</textarea>
If a text node begins with white space (space, new line) it will be ignored by HTML parsers. Encoding the new line into a proper HTML entity forces the parser to acknowledge it.
== carriage return
Answering the question "Why". This is specified in HTML 5 specification in the chapter that describes how DOM tree is created from tags found in a HTML document.
In the current HTML 5 living standard it is "12.2 Parsing HTML documents" > "12.2.6 Tree construction" > "12.2.6.4 The rules for parsing tokens in HTML content" > "12.2.6.4.7 The "in body" insertion mode".
(In HTML 5.2 the same section is numbered 8.2.5.4.7).
Scroll down for item "A start tag whose tag name is "textarea""
A start tag whose tag name is "textarea"
Run these steps:
1. Insert an HTML element for the token.
2. If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move on to the next one. (Newlines at the start of textarea elements are ignored as an authoring convenience.)
3. Switch the tokenizer to the RCDATA state.
...
The algorithm deals with LF characters only, because CR characters are handled earlier.
(Historically, looking into obsolete HTML 4.01 specification:
Its Chapter 17.7 "The TEXTAREA element" has an example that shows that text content for a textarea starts from a new line.
Appendix B.3.1 Line breaks (informative) explains that such behaviour originates from SGML.)
A line break character before </textarea> end tag is not ignored nowadays, in HTML 5.
If possible, change your code to have the textarea pre-defined as html, then write the string like this instead:
HTML:
<textarea cols='10' rows='10' id='test'></textarea>
Script:
document.getElementById('test').innerHTML = '\nhello\nbabe\n';
That should preserve white-space. Optionally you can add a css rule:
textarea {
white-space:pre;
}
A fiddle to play with:
http://jsfiddle.net/RFLwH/1/
Update:
OP tested in IE8 which this does not work - it appear to be a limitation/bug with this browser. IE8 do actually use CR+LF if you manually insert a line-feed at the top, but when set programmatic this is completely ignored by the browser.
Add this to the html to do a test:
<span onclick="this.innerHTML = escape(document.getElementById('test').innerHTML);">
Get textarea content
</span>
You can see the string returned is:
%0D%0Ahello%20babe%20
meaning the CR+LF is there (the other line-feeds are converted to spaces - but inserting a space at the beginning does not help either). I guess there is nothing you can do about this behavior; the browser is obsolete (but unfortunately still widely used so this can be a problem for those users if this is essential).
Add a whitespace before the first "\n" like this :
<script type="text/javascript">
document.write("<textarea cols='10' rows='10'>" + " \nhello\nbabe\n" + "</textarea>");
</script>
or
<textarea cols='10' rows='10'> <!-- whitespace here -->
hello
babe
</textarea>
otherwise it won't work.
Update:
Later in your server side, you can remove the first whitespace by doing
$str = ltrim ($str,' ');
or
$str2 = substr($str, 4);
if it is PHP.
It should be a \n\r at the top:
document.write("<textarea cols='10' rows='10'>" + "\n\rhello\nbabe\n" + "</textarea>");
jsbin
Finally i finished with this server-side solution:
to double leading(only first!) nl symbol before output it in textarea:
if(str_startswith("\r\n",$value))
{
$value = "\r\n".$value;
}elseif(str_startswith("\n",$value))
{
$value = "\n".$value;
}elseif(str_startswith("\r",$value))
{
$value = "\r".$value;
}
function str_startswith($start, $string)
{
if(mb_strlen($start)>mb_strlen($string))
return FALSE;
return (mb_substr($string, 0,mb_strlen($start))==$start);
}

How to use insertBefore to add a new element?

I'm trying to add text to a tag but I keep getting an error
NOT_FOUND_ERR: DOM Exception 8
Error: An attempt was made to reference a Node in a context where it does not exist.
Here's the javascript:
var getexp = document.getElementsByTagName("td")[219];
few lines of code here...
var fsptag = document.createElement('text');
fsptag.innerHTML = append1 +fspRound +append2 +ratioRound;
var fsptext = fsptag.innerHTML;
fsptag.appendChild(fsptext);
getexp.insertBefore(fsptag,getexp.childNodes[10]);
I'm new to this (only a few days). From what I understand getexp.childNodes[10] should be a child node of getexp. And it is a child node.
Any help here would be appreciated. Thanks.
EDIT: HTML
<td colspan=2> »
<b>Combat level: 20</b> (311855484) <font style='font-size:8px;color:#696156'>+13144516</font>
<BR><BR> »
<b>Troops ready:</b> 100%
<BR> »
<b>Mana:</b> 40 / 40<BR> »
<b>Location:</b> <a href=map.php?cx=50&cy=50>Empire Capital</a>
<BR><BR><BR><BR><BR>
<center><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="460" height="54" id="showarmy" align="middle">
The HTML looks something like this. It's from here (http://www.lordswm.com/pl_info.php?id=2255) in the source about line 204.
Edit:
var append1 = "<br><br> » <b>Total FSP: </b>";
var append2 = "<br> » <b>Ratio: </b>";
var fsptag = document.createElement('text');
fsptag.innerHTML = append1 +fspRound +append2 +ratioRound; //fspRound & ratioRound are numbers
Then when I use this: getexp.appendChild(fsptag); the appended text(html?) is created at the end i.e. after the <object> (last line in html code). I want it to appear in between the 5 <br> tags (line 8 of html code).
Sorry for delaying, I was trying to figure it out myself.
createElement(tag_name) creates a HTML element defined by tag_name. Afaik, <text> can appear only inside of a <svg>. Is your purpose to create a custom HTML tag? If so, you need to use some other name for it.
appendChild() takes an element as an argument, not a string. Also when an element once is appended, it's moved from it's original position, i.e. the value of the variable used in the appendChild's argument becomes null. This means, that if you want to insert a new element twice, you'll have to recreate it before inserting again.
In modern browsers the childNodes collection contains also white-spaces and new-lines between tags, so you maybe need to re-calculate the index for insertBefore().
EDIT
After you edited your post, it's more understandable. I've stored a simplified fiddle for you. It maybe close what you need?
The basic code in the fiddle is like this:
var getexp = document.getElementsByTagName("td")[219];
var fsptag = document.createElement('div');
fsptag.innerHTML = append1 + fspRound + append2 + ratioRound;
getexp.insertBefore(fsptag, getexp.childNodes[10]);

string search in body.html() not working

Hi here is my total work to search a string in HTML and highlight it if it is found in document:
The problem is here
var SearchItems = text.split(/\r\n|\r|\n/);
var replaced = body.html();
for(var i=0;i<SearchItems.length;i++)
{
var tempRep= '<span class="highlight" style="background-color: yellow">';
tempRep = tempRep + SearchItems[i];
tempRep = tempRep + '</span>';
replaced = replaced.replace(SearchItems[i],tempRep); // It is trying to match along with html tags...
// As the <b> tags will not be there in search text, it is not matching...
}
$("body").html(replaced);
The HTML I'm using is as follows;
<div>
The clipboardData object is reserved for editing actions performed through the Edit menu, shortcut menus, and shortcut keys. It transfers information using the system clipboard, and retains it until data from the next editing operation replace s it. This form of data transfer is particularly suited to multiple pastes of the same data.
<br><br>
This object is available in script as of <b>Microsoft Internet Explorer 5.</b>
</div>
<div class='b'></div>
If I search for a page which is pure or without any html tags it will match. However, if I have any tags in HTML this will not work.. Because I am taking body html() text as the target text. It is exactly trying to match along with html tags..
In fiddle second paragraph will not match.
First of all, to ignore the HTML tags of the element to look within, use the .text() method.
Secondly, in your fiddle, it wasn't working because you weren't calling the SearchQueue function on load.
Try this amended fiddle

Categories