I've looked around a bit and I cannot seem to find out how to remove a DOM element if its count gets over 50 amount. Basically it's similar to a chat.
JS
function append(aVal) {
document.getElementById('elem').innerHTML += "<br/>" + aVal;
}
Usage
appendvalues("<span>Your message " + message + ".</span>");
HTML
<div id="elem" class="container"></div>
I'm trying to remove the br & span tags. I feel that making a class for the span tag would be better since I have other span tags on the page.
I assume you want to do it FIFO...
function append(aVal) {
var el = document.getElementById('elem');
el.insertAdjacentHTML("beforeend", "<br/>" + aVal);
var spans = el.getElementsByTagName("span");
if (spans.length > 50) {
el.removeChild(spans[0].nextSibling);
el.removeChild(spans[0]);
}
}
Note that I'm using .insertAdjacentHTML instead of .innerHTML +=.... This is a much less destructive way to add content from HTML.
Does this do what you want?
$("#elem > span:gt(50)").remove();
Related
I have HTML structures in a form system where a html node will have data-src="formname" and this will contain lots of html nodes with data-fld="fieldname". This would be easy to parse but sometimes a field can be a host of a subform that itself contains data-src and data-fld.
When I search for [data-src='name'] using jquery find selectors I get both the immediate data-fld elements and the ones contained in a child data-src, I only want the former, not the latter.
I've created a fiddle to demonstrate:
<div data-src="mainform">
<div data-fld="field1">fld1</div>
<div data-fld="field2">
<div data-src="subform">
<div data-fld="subfield1">subfld1</div>
</div>
</div>
</div>
<div id="info"></div>
And the JS:
var result = "";
var find = "mainform";
var src = $("[data-src='" + find + "']");
src.find("[data-fld]").each(function() {
var ele = $(this);
if (ele.closest("[data-src='" + find + "']") === src) {
result += "Child field : " + $(this).data("fld") + " ";
}
});
$("#info").text(result);
The above code works, by virtue of that IF statement, I think it would be nice to be able to select "[data-fld]" where its closest "[data-src]" is the one I'm working on, and I wondered if (a) there's an inherent JQuery/CSS selector way of doing this or (b) is there otherwise a better solution to this code.
Not only because we want elegant code but also because asking for closest on every loop iteration is going to be a performance issue, possibly.
using immediate children selector
var result = "";
var find = "mainform";
var src = $("[data-src='" + find + "']");
src.find("[data-fld]").first().each(function() {
var ele = $(this);
result += "Child field : " + $(this).data("fld") + " ";
});
$("#info").text(result);
I need to put a span around the last two characters within a div.
The current structure looks like this:
<div id="price">3199</div>
I need to output something like this:
<div id="price">31<span id="smaller">99</span></div>
It's for a price in a dynamic HTML5 banner ad. I need the ability to format the final two characters smaller than the first two, but the integer from the dynamic feed is simply 3199 or 2099 etc. etc.
I've found some jQuery solutions but I need this to be plain JavaScript.
This fiddle solves it well with jQuery, and I'm sure it doesn't need much tweaking to work without jQuery but my javascript skills can't quite crack it.
You can use replace() with regex .{2}$
var ele=document.getElementById('price');
ele.innerHTML=ele.innerHTML.replace(/.{2}$/,'<span id="smaller">$&</span>')
#smaller{
font-size:10px;
}
<div id="price">3199</div>
Exaple using substring, not as nice as regex but works.
var str = document.getElementById('price').innerHTML;
cut = str.substring(str.length, 2);
document.getElementById('price').innerHTML = str.slice(0, -2) + '<span id="smaller">' + cut + '</span>';
#smaller{
font-size:10px;
}
<div id="price">3199</div>
Fiddle
If you already have event handlers on that HTML, you can't just reset innerHTML, you have to use a more foolproof of breaking up text nodes, using DOM manipulation.
var priceNode = document.getElementById('price');
var textNode = priceNode.firstChild;
var newTextNode = textNode.splitText(textNode.data.length - 2); // Index of where to break the text node
var span = document.createElement('span');
span.className = 'decimal';
span.appendChild(newTextNode);
priceNode.appendChild(span);
.decimal {
font-size: 50%;
}
<div id="price">3199</div>
Here's a case where innerHTML manipulation breaks an existing handler
$('.wholeamount').hover(
function(){ $(this).addClass('highlight')},
function(){ $(this).removeClass('highlight')}
);
$('button').click(function() {
var ele=document.getElementById('price');
ele.innerHTML=ele.innerHTML.replace(/.{2}$/,'<span class="decimal">$&</span>')
});
.highlight {
background-color: yellow;
}
.decimal {
font-size: 50%
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre>Hover over the 24 to see it highlight</pre>
<div id="price"><span class="wholeamount">24</span>.99</div> <hr />
<button>Make decimal</button>
<pre>The highlight will be gone when you manipulate innerHTML</pre>
Use slice function to edit the innerHTML
This is the cleanest way to do it.
var ele=document.getElementById('price');
ele.innerHTML = ele.innerHTML.slice(0, 2) + "<span id='smaller'>" + ele.innerHTML.slice(2) + "</span>";
Basically I have a load of H1 H2 and H3 tags on a website and I want to be able to put a span around PART of these heading tags.
At the moment I have this:
jQuery(document).ready(function(){
// get all headings first
jQuery('h1, h2, h3').each(function(){
// get the text
var theHtml = jQuery(this).html();
// split by spaces
var theWords = theHtml.split(" ");
// count the words
var wordCount = theWords.length;
var newHtml;
if(wordCount < 2){
// only one word
newHtml = theHtml;
}
else if(wordCount == 2){
// word count is 2...
newHtml = theWords[0]+" <span style='color: #000'>"+theWords[1]+"</span>";
}
else {
// add the first two words:
newHtml = theWords[0]+" "+theWords[1]+" <span style='color:#000'>";
// need to loop through the array now
for(var i = 2; i<wordCount; i++){
newHtml = newHtml+theWords[i];
if(i+1 < wordCount){
newHtml = newHtml+" ";
}
}
//end
newHtml = newHtml+"</span>";
}
jQuery(this).html(newHtml);
});
});
Which works quite well. But now I have a problem which is sometimes there is an a element or a div (for an inline editor if logged in as an admin) in the titles which is breaking this...
How would I get around this? I need to potentially get all the html from the header tag, strip the HTML tags, add the span around the latter part, then put the html back in!
Any ideas?
Thank you.
Edit:
This is what the problematic html looks like:
<h1 class="entry-title"><div data-type="input" data-post_id="12" class="fee-field fee-filter-the_title">Bristish Society of Blood and Marrow Transplantation</div></h1>
And like this:
<h2 class="entry-title"><div data-type="input" data-post_id="62" class="fee-field fee-filter-the_title">About the Registry</div></h2>
But if not logged in as an administrator then the div's go away.
Hey! Nice one, I think this is possible with regular expressions. I made a quick example for you, covering the a and the div for the biggest part. All spaces that are not meant as real whitespaces (in the tags) are replaced with symbols like ___ or ---, which are changed back afterwards.
Take a look at this jsfiddle!
theHtml = theHtml.replace(/[\s]+\</gi,'<');
theHtml = theHtml.replace(/\s+[\'\"]/gi,'___');
theHtml = theHtml.replace(/[\'\"]\s+/gi,'---');
theHtml = theHtml.replace(/a\s/gi,'a_');
theHtml = theHtml.replace(/div\s/gi,'div_');
and backwards:
newHtml = newHtml.replace(/___/gi,' "');
newHtml = newHtml.replace(/---/gi,'" ');
newHtml = newHtml.replace(/div_/gi,'div ');
newHtml = newHtml.replace(/a_/gi,'a ');
COMMENT after your edit
This will not work for the example h1 and h2 you posted. This is just an idea of how to approach this. I hope this will help you! Good luck!
COMMENT2 after my own edit ;-)
It does work, I just forgot to add case insensitivity and recursivity! It's just not finished yet. There are more checks needed such as ' or " etc. Here you go, I hope this will get you on the right track.
Please use the jQuery .text() function to strip out all the text within any particular H1, H2 tags etc. Other HTML inside these tags will be ignored.
But, i'm not sure how you will restore all the Inner HTML tags back.
Have you tried jQuery's wrapInner() function? I think it does what you're looking for in just one line.
$('h1, h2, h3').wrapInner('<span></span>');
If you know what class will be in the "inner" HTML element, you can just grab that.
var outer = $('.entry-title');
var html = html.find('.fee-field');
if(html === null){
html = outer;
}
// html will either be your `h` element or your inner most element.
www.powersource.se
The last link, "Add some stuff" doesn't work properly. It's supposed to add a bit of text when you press it and then remove the text when you press it again. I've made the add-part work, but I haven't managed to make the remove-part.
function add_module(title, text)
{
container = document.getElementById('text-main');
the_text ='<div class="text-header" id="added-text-header">' + title + '</div><div id="added-text">' + text + '</div>';
if(container.innerHTML != container.innerHTML + the_text)
{
container.innerHTML = container.innerHTML + the_text;
}else if(container.div.innerHTML == container.innerHTML + the_text)
{
text_container = container.getElementById('added-text-header');
parent = text_container.parentNode;
parent.removeChild(text_container);
text_container = container.getElementById('added-text');
parent = text_container.parentNode;
parent.removeChild(text_container);
}
}
You're using + to add text in. That's how JavaScript concatenates two strings.
The problem comes when you try to use - to remove. That won't work. The minus sign is for subtracting numbers, not for taking something away from a string.
I'd suggest using jQuery or another JavaScript library that has good cross-browser DOM manipulation. When you insert more text in, use a function to add a chunk of HTML. Use the p tag: <p>some text</p>. Then you'll be able to hunt down the p tags and delete the last one.
When you say string1 + string2 you're actually creating a brand new string, + is just shorthand for "mash these two together."
If you want to be able to add and remove that text you'll have to do it another way. The real issue is that once you've concatenated the strings together you have no idea which part of the string is the original, and which part is the user's.
In jQuery you can use DOM manipulation to better handle this. First I would put your div tags with the text-header and the text inside your container, but leave them empty. That way you don't have to create them on the fly. Then (assuming your text div has a class of "text-body"):
var textHeader = $("#text-main .text-header");
var textBody = $("#text-main .text-body");
//If the header doesn't contain the title set it, otherwise remove it
if(textHeader.text() != title) {
textHeader.text(title)
} else {
textHeader.text("");
}
//If the text body doesn't contain the text set it, otherwise remove it
if(textBody.text() != text) {
textBody.text(text)
} else {
textBody.text("");
}
I was wondering if it is possible to use JavaScript to add a <div> tag around a word in an HTML page.
I have a JS search that searches a set of HTML files and returns a list of files that contain the keyword. I'd like to be able to dynamically add a <div class="highlight"> around the keyword so it stands out.
If an alternate search is performed, the original <div>'s will need to be removed and new ones added. Does anyone know if this is even possible?
Any tips or suggestions would be really appreciated.
Cheers,
Laurie.
In general you will need to parse the html code in order to ensure that you are only highlighting keywords and not invisible text or code (such as alt text attributes for images or actual markup). If you do as Jesse Hallett suggested:
$('body').html($('body').html().replace(/(pretzel)/gi, '<b>$1</b>'));
You will run into problems with certain keywords and documents. For example:
<html>
<head><title>A history of tables and tableware</title></head>
<body>
<p>The table has a fantastic history. Consider the following:</p>
<table><tr><td>Year</td><td>Number of tables made</td></tr>
<tr><td>1999</td><td>12</td></tr>
<tr><td>2009</td><td>14</td></tr>
</table>
<img src="/images/a_grand_table.jpg" alt="A grand table from designer John Tableius">
</body>
</html>
This relatively simple document might be found by searching for the word "table", but if you just replace text with wrapped text you could end up with this:
<<span class="highlight">table</span>><tr><td>Year</td><td>Number of <span class="highlight">table</span>s made</td></tr>
and this:
<img src="/images/a_grand_<span class="highlight">table</span>.jpg" alt="A grand <span class="highlight">table</span> from designer John <span class="highlight">Table</span>ius">
This means you need parsed HTML. And parsing HTML is tricky. But if you can assume a certain quality control over the html documents (i.e. no open-angle-brackets without closing angle brackets, etc) then you should be able to scan the text looking for non-tag, non-attribute data that can be further-marked-up.
Here is some Javascript which can do that:
function highlight(word, text) {
var result = '';
//char currentChar;
var csc; // current search char
var wordPos = 0;
var textPos = 0;
var partialMatch = ''; // container for partial match
var inTag = false;
// iterate over the characters in the array
// if we find an HTML element, ignore the element and its attributes.
// otherwise try to match the characters to the characters in the word
// if we find a match append the highlight text, then the word, then the close-highlight
// otherwise, just append whatever we find.
for (textPos = 0; textPos < text.length; textPos++) {
csc = text.charAt(textPos);
if (csc == '<') {
inTag = true;
result += partialMatch;
partialMatch = '';
wordPos = 0;
}
if (inTag) {
result += csc ;
} else {
var currentChar = word.charAt(wordPos);
if (csc == currentChar && textPos + (word.length - wordPos) <= text.length) {
// we are matching the current word
partialMatch += csc;
wordPos++;
if (wordPos == word.length) {
// we've matched the whole word
result += '<span class="highlight">';
result += partialMatch;
result += '</span>';
wordPos = 0;
partialMatch = '';
}
} else if (wordPos > 0) {
// we thought we had a match, but we don't, so append the partial match and move on
result += partialMatch;
result += csc;
partialMatch = '';
wordPos = 0;
} else {
result += csc;
}
}
if (inTag && csc == '>') {
inTag = false;
}
}
return result;
}
Wrapping is pretty easy with jQuery:
$('span').wrap('<div class="highlight"></div>'); // wraps spans in a b tag
Then, to remove, something like this:
$('div.highlight').each(function(){ $(this).after( $(this).text() ); }).remove();
Sounds like you will have to do some string splitting, though, so wrap may not work unless you want to pre-wrap all your words with some tag (ie. span).
The DOM API does not provide a super easy way to do this. As far as I know the best solution is to read text into JavaScript, use replace to make the changes that you want, and write the entire content back. You can do this either one HTML node at a time, or modify the whole <body> at once.
Here is how that might work in jQuery:
$('body').html($('body').html().replace(/(pretzel)/gi, '<b>$1</b>'));
couldn't you just write a selector as such to wrap it all?
$("* :contains('foo')").wrap("<div class='bar'></div>");
adam wrote the code above to do the removal:
$('div.bar').each(function(){ $(this).after( $(this).text() ); }).remove();
edit: on second thought, the first statement returns an element which would wrap the element with the div tag and not the sole word. maybe a regex replace would be a better solution here.