Excluding Links from Javascript - javascript

I want to start off by saying I am very very new to javascript, and basically did a lot of googling to find this place and various other resources. While I found a script to modify into something I wanted (and managed to get it to work) it interferes with any links that are made within the specified div. Is there a way to exclude the links from the javascript, and just have the javascript affect the text?
This is the javascript. While I have no problem getting the first part to work (where I replace quoted text), I can't seem to exclude links and images that has html which possesses quotation marks in them.
$("div.gam-posttem div").each(function(){
this.innerHTML = this.innerHTML.replace(/\"([^\"]+)\"/g,
'<div class="gam-quotetext">"$1"</div>');
});
$not('div.gam-posttem > div > a').each(function(){});
And here's the html I am using.
<div class="gam-posttem"><div class="gam-posttem1">
"quote here" and regular text here. "more quote here"
<br><br>Link is Here
</div></div>
Any help is greatly appreciated, and if you need any more info, such as CSS, please feel free to ask.

What makes this particularly tricky is that JavaScript Regular Expressions do not allow look-behind. What you want to do is try and match " pairs where there are an equal number of < and > characters (outside of other " characters) before it. And even if you could, that'd be a pretty nasty looking regex...
However, you only care about characters outside of <> pairs, which matching using Regex (while not advisable) is possible:
<(?:[^><\"\']*?(?:([\"\']).*?\1)?[^><\'\"]*?)+(?:>|$) will match all <> pairs, ignoring close angle brackets within quotes within the tag. Hence you want to match everything outside these tags.
There's probably a better way to do this, but you can try the following idea:
Match all tags
For each tag, get the start position and length => calculate end position
add the start index of the string to the front of the end positions
add the length of the string to the start positions
for each (end, start) pair (as we are inverting the matches), run your replace method and modify the string.
String.prototype.spliceish = function(start, end, newSubStr) {
return this.slice(0, start) + newSubStr + this.slice(end);
};
var tagMatch = /<(?:[^><\"\']*?(?:([\"\']).*?\1)?[^><\'\"]*?)+(?:>|$)/g;
var tokenMatch = /\"([^\"]+)\"/g;
function invertedMatch(htmlString) {
var returnString = htmlString;
var startIndexes = [],
lengths = [],
match = tagMatch.exec(htmlString);
while(match !== null)
{
startIndexes.push(match.index);
lengths.push(match[0].length);
match = tagMatch.exec(htmlString);
}
var endIndexes = startIndexes.map(function(val, ix) { return val + lengths[ix]; });
var invertedStarts = [0].concat(endIndexes); // we are inverting, so capture start text.
var invertedEnds = startIndexes.concat(htmlString.length);
// will need to go backwards
for(var i = invertedStarts.length - 1; i >= 0; i--) {
var start = invertedStarts[i],
end = invertedEnds[i];
var stringReplace = htmlString.substring(start, end);
returnString = returnString.spliceish(start, end, stringReplace.replace(tokenMatch,
'<div class="gam-quotetext">"$1"</div>'));
};
return returnString;
}
$("#root").html(invertedMatch($("#root").html()));
.gam-quotetext{
color: green
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="root">
<div class="gam-posttem">
<div class="gam-posttem1">
"quote here" and regular text here. "more quote here"
<br>
<br>
Link is Here
</div>
</div>
</div>

Related

Overflowed text with html in another div

I want to have a text that overflows in another div, so I found and used this answer from another question at Stackoverflow.
The problem is that only plain text is displayed; links, bold/italics and paragraphs are ignored.
Here is the same jsfiddle from the answer, but with added html tags. How do i get to display them?
Code:
var currentCol = $('.col:first');
var text = currentCol.text();
currentCol.text('');
var wordArray=text.split(' ');
$.fn.hasOverflow = function() {
var div= document.getElementById( $(this).attr('id') );
return div.scrollHeight>div.clientHeight;
};
for ( var x = 0; x < wordArray.length; x++ ) {
var word = wordArray[x];
currentCol.append(word+' ');
if ( currentCol.hasOverflow() ) {
currentCol = currentCol.next('.col');
}
}
Any tips or advice will be appreciated :)
jQuery .text method returns only plain text. Try using .html instead.
Example:
var text = currentCol.html();
But if your tags contain any spaces (like <span class="some-class">) then the following line from your code will do a mess with your text
var wordArray=text.split(' ');
You might want to change it to
text = text.replace(/ (?![^<>]*>)/gi, '%^%');
var wordArray = text.split('%^%');
This is kind of workaround since you could iterate over each regex match and substring it on every space character but IMHO the above idea with %^% combination is much more simple. you can replace those 3 signs with anything you want. I just thought it is unique enough that won't be used in any other purpose.
Above regular expression is simplified and assumes that you don't use < and > signs in your text.
If you actually do I would recommend to replace them with < and > anyway.

Split in to Sentences and Wrap With Tags

I'm trying to build a text fixing page for normalising text written in all capital letters, all lower case or an ungrammatical mixture of both.
What I'm currently trying to do is write a regular expression to find all full stops, question marks and line breaks, then split the string in to various strings containing all of the words up to and including each full stop.
Then I'm going to wrap them with <span> tags and use CSS :first-letter and text-transform:capitalize; to capitalise the first letter of each sentence.
The last stage will be writing a dictionary function to find user-specified words for capitalisation.
This question only concerns the part about writing a regex and splitting in to strings.
I've tried too many methods to post here, with varying results, but here's my current attempt:
for(var i=0; i < DoIt.length; i++){
DoIt[i].onclick = function(){
var offendingtext = input.value.toString();
var keeplinebreaks = offendingtext.replace(/\r?\n/g, '<br />');
var smalltext = keeplinebreaks.toLowerCase();
//split at each character I specify
var breakitup = smalltext.split(/[/.?\r\n]/g);
breakitup.forEach(function(i){
var i;
console.log(i);
var packagedtogo = document.createElement('span');
packagedtogo.className = 'sentence';
packagedtogo.innerHTML = breakitup[i];
output.appendChild(packagedtogo);
i++;
});
}
}
It was splitting at the right places before, but it was printing undefined in the output area between the tags. I've been at this for days, please could someone give me a hand.
How can I split a string in to multiple string sentences, and then wrap each string with html tags?
Your regex for the split is fine. Just forgot to escape a few characters:
var str = "SDFDSFDSF?sdf dsf sdfdsf. sdfdsfsdfdsfdsfdsfdsfsdfdsf sdf."
str.split( (/[\.\?\r\n]/g))
//["SDFDSFDSF", "sdf dsf sdfdsf", " sdfdsfsdfdsfdsfdsfdsfsdfdsf sdf", ""]
Use for each iteration capabilities like this:
breakitup.forEach(function(element){
var packagedtogo = document.createElement('span');
packagedtogo.className = 'sentence';
packagedtogo.innerHTML = element;//breakitup is undefiend
output.appendChild(packagedtogo);
//No need to increase index
});

Replace Last Match in Regex

I have an autocomplete user-tagging system that fills in usernames that come after an # symbol. I have this problem however, where I have two users with a matching substring. For example:
Tagging #billy and #b
When a user fills in the #b tag with a user named (for example) #brendan, it'll replace the #billy tag. How do I go backwards and replace only the last tag?
Edit: this is my current solution, but it feels kludgy. Is there a way to do this just with RegEx?:
function tagUser (chosenUsername) {
var userRegex = new RegExp('(^|\\s)#([' + lastUserTag() + ']*)$', 'gi');
var caption = $("#example").val();
var match = caption.match(userRegex);
var lastMatch = match[match.length - 1];
$("#example").val(caption.replace(lastMatch, " #" + chosenUsername));
}
Not sure if I understood your problem entirely. However just to let you know you can use negative lookahead to replace only last matched text like this:
var str='#billy and #b';
str = str.replace(/#b\b(?!.*?#b\b)/, 'brendan');

Match characters at start of string, ignore strings in html tags

A little help required please...
I have a regular expression that matches characters at the start of a string as follows:
If I have a set of strings like so:
Ray Fox
Foster Joe
Finding Forrester
REGEX
/\bfo[^\b]*?\b/gi
This will match 'FO' in Fox, Foster, and Forrester as expected:
However, I am faced with an issue where if the set of strings are wrapped in html tags like so;-
<span class="fontColor1">Ray Fox</span>
<span class="fontColor2">Foster Joe</span>
<span class="fontColor3">Finding Forrester</span>
This will match 'FO' in fontColor* as well.
I'm fairly green with Regular expressions, I need a little help updating the query so that it only searches values between HTML tags where HTML tags exist, but still works correctly if HTML tags do not exist.
You can use a html parser and extract pure text, and match that.
var root;
try {
root = document.implementation.createHTMLDocument("").body;
}
catch(e) {
root = document.createElement("body");
}
root.innerHTML = '<span class="fontColor1">Ray Fox</span>\
<span class="fontColor2">Foster Joe</span>\
<span class="fontColor3">Finding Forrester</span>';
//If you are using jQuery
var text = $(root).text();
//Proceed as normal with the text variable
If you are not using jQuery, you can replace $(root).text() with findText(root), where findText:
function findText(root) {
var ret = "",
nodes = root.childNodes;
for (var i = 0; i < nodes.length; ++i) {
if (nodes[i].nodeType === 3) {
ret += nodes[i].nodeValue;
} else if (nodes[i].nodeType === 1) {
ret += findText(nodes[i]);
}
}
return ret;
}
What about
<.*?span.*?>(.*?)<\s?\/.*?span.*?>
And where do you have text where html tags don't exist? That makes no sense.
EDIT:
This solution will not match nested tags, but as the question is written, that doesn't seem to be an issue.

JS Regex to find href of several a tags

I need a regex to find the contents of the hrefs from these a tags :
<p class="bc_shirt_delete">
delete
</p>
Just the urls, not the href/ tags.
I'm parsing a plain text ajax request here, so I need a regex.
You can try this regex:
/href="([^\'\"]+)/g
Example at: http://regexr.com?333d1
Update: or easier via non greedy method:
/href="(.*?)"/g
This will do it nicely. http://jsfiddle.net/grantk/cvBae/216/
Regex example: https://regex101.com/r/nLXheV/1
var str = '<p href="missme" class="test">delete</p>'
var patt = /<a[^>]*href=["']([^"']*)["']/g;
while(match=patt.exec(str)){
alert(match[1]);
}
Here is a robust solution:
let href_regex = /<a([^>]*?)href\s*=\s*(['"])([^\2]*?)\2\1*>/i,
link_text = 'another article link',
href = link_text.replace ( href_regex , '$3' );
What it does:
detects a tags
lazy skips over other HTML attributes and groups (1) so you DRY
matches href attribute
takes in consideration possible whitespace around =
makes a group (2) of ' and " so you DRY
matches anything but group (1) and groups (3) it
matches the group (2) of ' and "
matches the group (1) (other attributes)
matches whatever else is there until closing the tag
set proper flags i ignore case
You may don't need Regex to do that.
o = document.getElementsByTagName('a');
urls = Array();
for (i =0; i < o.length; i++){
urls[i] = o[i].href;
}
If it is a plain text, you may insert it into a displayed non DOM element, i.e display: none, and then deal with it regularly in a way like I described.
It might be easier to use jQuery
var html = '<li><h2 class="saved_shirt_name">new shirt 1</h2><button class="edit_shirt">Edit Shirt</button><button class="delete_shirt" data-eq="0" data-href="/CustomContentProcess.aspx?CCID=13524&OID=3936923&A=Delete">Delete Shirt</button></li><li><h2 class="saved_shirt_name">new shirt 2</h2><button class="edit_shirt">Edit Shirt</button><button class="delete_shirt" data-eq="0" data-href="/CustomContentProcess.aspx?CCID=13524&OID=3936924&A=Delete">Delete Shirt</button></li><li><h2 class="saved_shirt_name">new shirt 3</h2><button class="edit_shirt">Edit Shirt</button><button class="delete_shirt" data-eq="0" data-href="/CustomContentProcess.aspx?CCID=13524&OID=3936925&A=Delete">Delete Shirt</button></li>';
$(html).find('[data-href]');
And iterate each node
UPDATE (because post updated)
Let html be your raw response
var matches = $(html).find('[href]');
var hrefs = [];
$.each(matches, function(i, el){ hrefs.push($(el).attr('href'));});
//hrefs is an array of matches
I combined a few solutions around and came up with this (Tested in .NET):
(?<=href=[\'\"])([^\'\"]+)
Explanation:
(?<=) : look behind so it wont include these characters
[\'\"] : match both single and double quote
[^] : match everything else except the characters after '^' in here
+ : one or more occurrence of last character.
This works well and is not greedy with the quote as it would stop matching the moment it finds a quote
var str = "";
str += "<p class=\"bc_shirt_delete\">";
str += "delete";
str += "</p>";
var matches = [];
str.replace(/href=("|')(.*?)("|')/g, function(a, b, match) {
matches.push(match);
});
console.log(matches);
or if you don't care about the href:
var matches = str.match(/href=("|')(.*?)("|')/);
console.log(matches);
how about spaces around = ?
this code will fix it:
var matches = str.match(/href( *)=( *)("|'*)(.*?)("|'*)( |>)/);
console.log(matches);
It's important to be non-greedy. And to cater for —matching— ' or "
test = "<a href="#" class="foo bar"> banana
<a href='http://google.de/foo?yes=1&no=2' data-href='foobar'/>"
test.replace(/href=(?:\'.*?\'|\".*?\")/gi,'');
disclaimer: The one thing it does not catch is html5 attribs data-href...
In this specified case probably this is fastest pregmatch:
/f="([^"]*)/
gets ALL signs/characters (letters, numbers, newline signs etc.) form f=" to nearest next ", excluding it, flags for example /is are unnecesary, return null if empty
but if the source contains lots of other links, it will be necessary to determine that this is exactly the one you are looking for and here we can do it this way, just include in your pregmatch more of the source code, for example (of course its depend from source site code...)
/bc_shirt_delete">\s*<a href="([^"]*)

Categories