Collect first 3 paragraphs in html using javascript - javascript

Assume an article generated my markdown which has 1-N paragraphs in it. My brain is a bit fried tonight, all I could come up with was
var chunks = s.split('</p>');
if ( chunks.length > 3)
{
s = chunks[1]+'</p>'+chunks[2]+'</p>'+chunks[3]+'</p>';
}
Is there a more sane way to collect the first three paragraphs into a string? The markdown processor guarantees the paragraphs should be legal HTML. But I'm sure there must be a more clever regex solution. Also this won't guarantee three paragraphs if there is something else like a but that's OK.

Something like this?
var s= '<p>Paragraph 1</p><p>Paragraph <em>2</em></p><p>Paragraph 3</p><p>Paragraph 4</p><p>Paragraph 5</p>';
s= (s.split('</p>')
.splice(0,3)
.join('</p>') +
'</p>'
).replace(/\<\/p> *\<\/p>/g,'</p>');
console.log(s);

Id use something used to handling the DOM.... say jQuery
var arrP = $("body p").slice(0,3);
var strP = "";
for(var i = 0; i < arrP.length; i++)
{
strP += arrP[i].outerHTML;
}
console.log(strP);
//Or Taking the article in as a string
var strArticle = "<p>Parra <em>1</em></p><p>Parra <strong>2</strong></p><p>Parra 3</p><p>Parra 4</p>";
var divArticle = document.createElement('div');
divArticle.innerHTML = strArticle;
arrP = $(divArticle).find("p").slice(0,3);
strP = "";
for(var i = 0; i < arrP.length; i++)
{
strP += arrP[i].outerHTML;
}
console.log(strP);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>Parra <em>1</em></p>
<p>Parra <strong>2</strong></p>
<p>Parra 3</p>
<p>Parra 4</p>
<div id="target"></div>
I wouldn't just use jQuery for this, but if you're already using it or looking for an excuse to use it, this is an option. Otherwise go for Ricks answer. Regex is only appropriate for parsing HTML given very tight control over the input. Some would say it should never be used.
Or vanilla Javascript
var arrP = document.body.getElementsByTagName("p");
var strP = ""
for(var i = 0; i < 3; i++)
{
strP += arrP[i].outerHTML;
}
console.log(strP);
//Or Taking Article body as a string
var strArticle = "<p>Parra <em>1</em></p><p>Parra <strong>2</strong></p><p>Parra 3</p><p>Parra 4</p>";
var divArticle = document.createElement('div');
arrP = document.body.getElementsByTagName("p");
strP = ""
for(var i = 0; i < 3; i++)
{
strP += arrP[i].outerHTML;
}
console.log(strP);
<p>Parra <em>1</em></p>
<p>Parra <strong>2</strong></p>
<p>Parra 3</p>
<p>Parra 4</p>
<div id="target"></div>

There is a one line regular expression, of course, but it is pretty hard to read.
var s= '<p>Paragraph 1</p><p>Paragraph <em>2</em></p><p>Paragraph 3</p><p>Paragraph 4</p><p>Paragraph 5</p>';
regex = /(?:\<p\>.*?\<\/p\>){3}/;
s = regex.exec(s);
console.log(s);
The regular expression matches some non-capturing group exactly three times. Digging into the non-capturing group, we see several characters have to be escaped and that we need to use a lazy quantifier. I'd take your way over the clever regex any day.

You could get the paragraphs and just concat them together until you reach three.
var pars = '';
//Get the p tags, go through some of them. Use your favorite library to do this.
Array.prototype.some.call(document.querySelectorAll('p'), function(current, index) {
console.log("This should only go to 2", index);
pars = pars + ['<p>', current.innerHTML, '</p>'].join('');
return index >= 2; //Counting by zero
});
console.log(pars);
<p>This is one.</p>
<p>This is two.</p>
<p>This is five, er, three.</p>
<p>FOUR</p>
<p>FOUR PLUS ONE</p>
<p>FOUR PLUS TWO</p>

Related

Use Javascript to write names that don't appear in master list to div with id

Working demo at http://verlager.com/pairing.php uses document.write() but I would prefer to write to a div's ID. I have tried several methods but I can't get the for loop to write to div with id of "textDiv".
<script>
function newly_minted() {
var res = "Attaya, James J|Blazak, Stephen A|Cavanaugh, Michael P|Decker, Howard|";
document.getElementById("textDiv").textContent = res;
}
newly_minted();
</script>
<div id="textDiv" style="background:green; color:fff; display:table; height:10rem; width:40rem; margin:4rem auto; clear:both;"></div>
For original post:
This code replaces textDiv content because of the simple assignment used:
var div = document.getElementById("textDiv");
div.textContent = resort;
var text = div.textContent; //should append not replace!
Try the '+=' operator instead:
var div = document.getElementById("textDiv");
div.textContent += resort;
var text = div.textContent; //should append not replace!
For the updated post:
Declare newly_minted before calling it from a different script element. Hoisting function declarations only applies to the script element in which the function is declared.
Replace $( resort) with resort (and split resort on "|" as in the original). The trailing "|" is not altered in this demonstration:
function newly_minted() {
var res = "Attaya, James J|Blazak, Stephen A|Cavanaugh, Michael P|Decker, Howard|".split('|');
for (let i = 0; i < res.length; i++) {
var resort = res[i] + " ● ";
$( "#textDiv" ).append(resort);
}}
newly_minted();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="textDiv"></div>
Alternatively, without using jQuery, preparing text content first and removing trailing dots:
function newly_minted() {
var res = "Attaya, James J|Blazak, Stephen A|Cavanaugh, Michael P|Decker, Howard|".split('|');
for (var i = 0, text =""; i < res.length; i++) {
text += res[i] + " \u25cf ";
}
text = text.replace(" \u25cf \u25cf ", ""); // remove two trailing dots
document.getElementById("textDiv").textContent = text;
}
newly_minted();
<div id="textDiv"></div>

Javascript regex to remove unmatched closing HTML tags?

I'm trying to remove the excessive closing tags in javascript and anything that follows after that.
Here is a possible sample:
<div class="dummy">
<div class="main">
<div></div>
<img src="a.jpg">
<br>
<img src="b.jpg />
<strong>
<span>text</span>
</strong>
</div>
</div>
***excessive tags below***
</div>
</div>
<div class="footer">
text
</div>
</body>
</html>
Any ideas about how to do it efficiently?
The part I want to extract is always a div, but the problem is that it may have as many nested divs, and I'm not sure how to deal with this scenario.
If it can be done in multiple steps or with callbacks is also fine, as long as it works.
Edit
My question is actually easier than it seems.
The sample always starts with the div that I want to extract.
So all I need is to find the matching closing tag, and filter anything that follows.
Don't care about any other tags...
Don't use regex, from my understanding, you want to retain the dummy class div and the footer class div so why not replace the body with that?
E.g.
var dummy = document.getElementsByClassName('dummy')[0];
var footer = document.getElementsByClassName('footer')[0]
var body = document.getElementsByTagName('body')[0];
body.innerHTML = '';
body.appendChild(dummy);
body.appendChild(footer);
https://jsfiddle.net/1kq11ry2/
data='<div class="dummy"><div class="main"><div></div><img src="a.jpg"><br><div></div><img src="b.jpg /><strong><span>text</span> </strong></div><div><div></div></div><div><div></div></div></div>***excessive tags below***</div></div><div class="footer">text</div></body></html>';
var starting_tags = [];
var closing_tags = [];
var startIndex, index=0;
var searchStrLen = 4;
while ((index = data.indexOf('<div', startIndex)) > -1) {
starting_tags.push(index);
startIndex = index + searchStrLen;
}
index,startIndex=0;
searchStrLen = 6;
while ((index = data.indexOf('</div>', startIndex)) > -1) {
closing_tags.push(index);
startIndex = index + searchStrLen;
}
var nest_level=0;
for (var i=0; i<closing_tags.length && nest_level<closing_tags.length && nest_level<=closing_tags.length; ++i) {
for (var j=0+nest_level; j<starting_tags.length; ++j) {
if (starting_tags[j]<closing_tags[nest_level])
nest_level++;
}
}
result = data.substr(startIndex[starting_tags], closing_tags[nest_level-1]+6);
console.log(nest_level);
console.log(starting_tags);
console.log(closing_tags);
console.log(result);
I was able to solve it. The code above calculates the level of div nesting, and then chops it off if it finds excessive closing tags.
https://jsfiddle.net/89j7yakz/2/

How can I add element after match character in jquery?

Trying to place an element after match second or more dots in a text if it has a specific number of characters. Example:
<div id="mytext">
This is just a example. I need to find a solution. I will appreciate any help. Thank you.
</div>
<script>
var chars = 55;
if ($('#mytext').text().length > chars){
//add <br> after first dot found after number of chars specified.
}
</script>
... The output would be:
This is just a example. I need to find a solution. I will appreciate any help.<br>
Thank you.
You can try this
var chars = 55;
if ($('#mytext').text().length > chars){
var text = $('#mytext').text(); // div text
var chars_text = text.substring(0, chars); // chars text
var rest = text.replace(chars_text, '').replace(/\./g,'. <span>After Dot</span>'); // rest of text and replace dot of rest text with span
$('#mytext').html(chars_text+rest); // apply chars and rest after replace to the div again
}
span{
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mytext">
This is just a example. I need to find a solution. I will appreciate any help. Thank you.
</div>
Note: if you just need to replace the next one dot after chars you can
use '.' instead of /\./g
this way : With JQUERY Substring
<p>
this is test string with jquery . test 1 2 3 4 45 5 . test test test
</p>
<b></b>
<script>
var a = $('p').text();
var _output = '';
var _allow_index = 40;
if (a.length > _allow_index)
{
var x = a.split('.');
for(var i=0; i<x.length; i++)
{ if (_output.length < _allow_index) { _output+=x[i]+'.'; } }
}
else { _output = a; }
$('b').html(_output + '<br>'+a.substr(_output.length,a.length));
</script>
Doing that doesn't seem to be a very good practise, for instance length may vary for localised languages.
Besides, you're assuming you have a plain text, rather than an HTML text and length is different in both cases. You may want to use html() instead of text().
However here is a way for the given case:
var container = $('#mytext');
var length = 55;
var insert = '<br/>';
var text = container.text().trim(); // text() or html()
var dotPosAfterLength = text.indexOf(".", length);
if (dotPosAfterLength != -1) {
container.html(
text.substring(0, dotPosAfterLength+1)
+insert
+text.substring(dotPosAfterLength+1)
);
}
You just need to add this property in CSS.
<div id="mytext">
This is just a example. I need to find a solution.
I will appreciate any help. Thank you.
</div>
<style>
div#mytext{
word-wrap: break-word;
}
</style>

Get and evaluate every character inside an element for brace matching

<div id = "board>
<div>{abc</div>
<div>def</div>
<div>ghi}</div>
</div>
I want compare every char inside the div at their position and do something when if found { or }
Im aware that this is possible by wrapping every char within <span></span>
Is there a way to do this without using a span? I will use this for brace matching of my code editor project. this is what i've done using span wrapping, but it is so slow..
$exceedingInlineDiv = $('#board_code_dup > div').eq(x);
if( $exceedingInlineDiv.text() == ''){
var chars = '<span> <br> </span>';
$exceedingInlineDiv.html(chars);
}
else{
var chars = jQuery.map($exceedingInlineDiv.text().split(''), function(c) {
return '<span>' + c + '</span>';
});
$exceedingInlineDiv.html(chars.join(''));
}//else
I'm not sure what you want to do, but maybe you want something like this:
var board = document.getElementById("board"),
divs = board.getElementsByTagName("div"),
texts = [], i = 0;
for (; i < divs.length; i++)
texts.push(divs[i].innerHTML);
// texts => ["{abc", "def", "ghi}"]

Regular expression getElementById

I need to use pure Javascript for the first time in a long while, and having gotten used to the comfy mattress of jQuery, all the important stuff is escaping me.
I need to select a bunch of divs on regular expression. So I have stuff like this;
<div id="id_123456_7890123"> .. </div>
<div id="id_123456_1120092"> .. </div>
<div id="id_555222_1200192"> .. </div>
<div id="id_123456_9882311"> .. </div>
And I'd need to create a loop that goes through all the divs with an id that begins with id_123456_. How would I go about doing that?
I used jQuery with the :regex filter plugin before, but looking at it, it doesn't seem like there's much I could salvage in a pure javascript rewrite.
In plain javascript, you could do this generic search which should work in every browser:
var divs = document.getElementsByTagName("div"), item;
for (var i = 0, len = divs.length; i < len; i++) {
item = divs[i];
if (item.id && item.id.indexOf("id_123456_") == 0) {
// item.id starts with id_123456_
}
}
Working example: http://jsfiddle.net/jfriend00/pYSCq/
HTML DOM querySelectorAll() method will work here.
document.querySelectorAll('[id^="id_"]');
Borrowed from StackOverFlow here
This works by recursively traversing the whole DOM.
It's possibly not the most efficient, but should work on every browser.
function find_by_id(el, re, s) {
s = s || [];
if (el.tagName === 'DIV' && re.exec(el.id) !== null) {
s.push(el);
}
var c = el.firstChild;
while (c) {
find_by_id(c, re, s);
c = c.nextSibling;
}
return s;
}
var d = find_by_id(document.body, /^id_123456_/);
See http://jsfiddle.net/alnitak/fgSph/
Here you are: http://jsfiddle.net/howderek/L4z9Z/
HTML:
<div id="nums">
<div id="id_123456_7890123">Hey</div>
<div id="id_123456_1120092">Hello</div>
<div id="id_555222_1200192">Sup</div>
<div id="id_123456_9882311">Boom</div>
</div>
<br/>
<br/>
<div id="result"></div>​
Javascript:
divs = document.getElementsByTagName("div");
divsWith123456 = new Array();
for (var i = 0;i < divs.length;i++) {
if (divs[i].id.match("id_123456") != null) {
divsWith123456.push(divs[i]);
document.getElementById("result").innerHTML += "Found: divs[" + i + "] id contains id_123456, its content is \"" + divs[i].innerHTML + "\"<br/><br/>";
}
}​

Categories