Equivalent of PHP preg_match, substr in javaScript - javascript

i'm makeing a tinyMce plugin that change word/letter space between highlighted text. My fn() looks like this:
function wordsLettersSpace(words, letters) {
var inst = tinyMCE.activeEditor;
var currSelection = $.trim(inst.selection.getSel());
if(currSelection != ""){
var content = "";
content = inst.selection.getContent({
format: 'html'
});
contentReplace = '<span style="word-spacing: '+words+'px; letter-spacing: '+letters+'px;">' + inst.selection.getContent({
format: 'html'
}) + '</span>';
inst.selection.setContent(content.replace(content, contentReplace));
window.alert(content);
}else{
Hyphenator.hyphenate(inst.getBody(), language);
}
tinyMceUpdate();
}
Now i need to find closest tag before select start position (if exist) and get style values of "word-spacing" and "letter-spacing". Also i need to get rid of any inside of selection, but only tags not the text, knowing that span tags can have different styles so simple str.replace won't work.
I know that there is a built-in plugin for that, but i need to do it outside of tinyMce iframe, and customize it.
Any sugestions?

JS regexes are available and do exactly what you want with preg_match.
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Regular_Expressions
Substring in javascript is str.substr(start, length)

Related

Javascript - How can I replace text in HTML with text in script

I am new to javascript. I was thinking getelementbyid but i don't know how to make it work
Like the title, here is what I mean
For example I have in HTML:
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
So what I want is to make script to replace those fw_93 fw_94 to what I want.
For example
Instead of displaying "fw_93" I want it to display "9.3". Same with fw_94 to 9.4
Replace fw_ with nothing, divide the number by 10:
Array.prototype.forEach.call(document.getElementsByTagName('p'), function(el) {
el.innerHTML = parseInt(el.innerHTML.replace(/[A-Za-z_]*/, '')) / 10;
});
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
Okay so select the tags.
Loop over the collection
read the html
match the string
replace the html
var ps = document.querySelectorAll("p");
for (var i=0; i<ps.length; i++) {
var p = ps[i];
var txt = p.innerHTML; //.textContent
var updated = txt.replace(/.+(\d)(\d)/, "$1.$2");
p.innerHTML = updated;
}
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
Using JQuery
Not sure why I did it with JQuery, guess I wasn't paying enough attention. No point in me re-writing as there are already good answers in JS. Though I will leave this in case it's of use to anyone that is using JQuery.
You can loop though each <p> element and covert the contents, something like this:
$("p").each(function() {
var text = $(this).html();
var text = text.substring(text.indexOf("_") + 1);
var text = text[0] + "." + text.substring(1);
$(this).html(text);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
You may need to add validation depending on how reliable your input is.
Note that the code makes the following assumptions:
There will always be a _ followed by at least 2 digits
The . will always go after the first digit
Your HTML:
<p id="p1">init_value</p>
Your JS:
document.getElementById("p1").innerHTML = "new_value";

JAVASCRIPT - if last character is : (colon), change font weight

Is it possible to change font weight if last character is colon with JavaScript?
I have site, where people can add recipe. And i want to highlight parts of ingredients of recipe. For example:
topping:
-chocolate
-milk
filling:
-...
-...
I searched and i found that codes:
for last character
if (myString.charAt(myString.length - 1) == ':')
and for weight change
function changeWeight(600)
{
document.getElementById("id_1").style.fontWeight = fontWeight;
}
I do not know how to write the code to work. I am beginner.
Thank you very much.
Try this
if (myString.charAt(myString.length - 1) == ':') {
changeWeight("600");
}
function changeWeight(weight) {
document.getElementById("id_1").style.fontWeight = weight;
}
It seems that you want to make specific text bold, not all text within an element. You would need to get the text out of the element, change it, and put it back.
You can use code like this to but a bold tag around all words in the element that ends with a colon:
var element = document.getElementById("id_1");
var text = element.innerHTML;
text = text.replace(/([A-Za-z]+:)/g, '<strong>$1</strong>');
element.innerHTML = text;
Note: For that to work properly, you can't have other HTML elements inside the element that has words with colons in the actual markup. I you have for example SO in the code, it would break because of the http: in the link.
If you have that single word alone in an element, you would get the text and check for the colon:
var element = document.getElementById("id_1");
var text = element.innerHTML;
if (text.charAt(text.length - 1)) == ':') {
element.style.fontWeight = 'bold';
}

The first letter of each <h3> into a hyperlink

Using javascript I'm looping through my H3 elements like this:
$('h3').each(function(){ });
I'm then generating an anchor for that tag formatted like this: "section-x" where x increments for each H3 on the page. The problem I have is that I'd like the first letter of the header to be an anchor link, like this:
*H*eading
.. where H is underlined, representing a link. I can format the anchors however I don't know how to wrap a hyperlink tag around the first letter in each heading. Some help would be greatly appreciated.
Regards,
kvanberendonck
Something like this?
$('h3').each(function(){
var currentHeading = $(this).text();
$(this).html("<a href='link'>" + currentHeading.substr(0,1) + "</a>" + currentHeading.substr(1, currentHeading.length - 1));
});
Let's throw some plain javascript into the mix:
$('h3').html(function(i){
var self = $(this)
, html = self.html()
return html[0].anchor('section-'+i) + html.substring(1)
})
html (and most other setter functions) accepts a function as an argument and uses the return value for each element
"string".link(target) creates the code string. A nice vintage useful method
edit: switched from .link to .anchor. Anchors are deprecated though, you should start using IDs for that:
$('h3').html(function(i){
var self = $(this)
, text = self.text()
// give the H3 an id and link to it
// ideally the headers should already have an id
this.id = 'section-'+i
return text[0].link('#section-'+i) + text.substring(1)
})
$('h3').each(function(i){
var firstLetter = $(this).text()[0];
$(this).html('' + firstLetter + '' + $(this).text().substr(1));
});
Not sure where you'd like to put section-x in that heading, but you can use i inside that each() to get the current iteration index.

JavaScript RegExp match text ignoring HTML

Is it possible to match "the dog is really really fat" in "The <strong>dog</strong> is really <em>really</em> fat!" and add "<span class="highlight">WHAT WAS MATCHED</span>" around it?
I don't mean this specifically, but generally be able to search text ignoring HTML, keeping it in the end result, and just add the span above around it all?
EDIT:
Considering the HTML tag overlapping problem, would it be possible to match a phrase and just add the span around each of the matched words? The problem here is that I don't want the word "dog" matched when it's not in the searched context, in this case, "the dog is really really fat."
Update:
Here is a working fiddle that does what you want. However, you will need to update the htmlTagRegEx to handle matching on any HTML tag, as this just performs a simple match and will not handle all the cases.
http://jsfiddle.net/briguy37/JyL4J/
Also, below is the code. Basically, it takes out the html elements one by one, then does a replace in the text to add the highlight span around the matched selection, and then pushes back in the html elements one by one. It's ugly, but it's the easiest way I could think of to get it to work...
function highlightInElement(elementId, text){
var elementHtml = document.getElementById(elementId).innerHTML;
var tags = [];
var tagLocations= [];
var htmlTagRegEx = /<{1}\/{0,1}\w+>{1}/;
//Strip the tags from the elementHtml and keep track of them
var htmlTag;
while(htmlTag = elementHtml.match(htmlTagRegEx)){
tagLocations[tagLocations.length] = elementHtml.search(htmlTagRegEx);
tags[tags.length] = htmlTag;
elementHtml = elementHtml.replace(htmlTag, '');
}
//Search for the text in the stripped html
var textLocation = elementHtml.search(text);
if(textLocation){
//Add the highlight
var highlightHTMLStart = '<span class="highlight">';
var highlightHTMLEnd = '</span>';
elementHtml = elementHtml.replace(text, highlightHTMLStart + text + highlightHTMLEnd);
//plug back in the HTML tags
var textEndLocation = textLocation + text.length;
for(i=tagLocations.length-1; i>=0; i--){
var location = tagLocations[i];
if(location > textEndLocation){
location += highlightHTMLStart.length + highlightHTMLEnd.length;
} else if(location > textLocation){
location += highlightHTMLStart.length;
}
elementHtml = elementHtml.substring(0,location) + tags[i] + elementHtml.substring(location);
}
}
//Update the innerHTML of the element
document.getElementById(elementId).innerHTML = elementHtml;
}
Naah... just use the good old RegExp ;)
var htmlString = "The <strong>dog</strong> is really <em>really</em> fat!";
var regexp = /<\/?\w+((\s+\w+(\s*=\s*(?:\".*?"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/gi;
var result = '<span class="highlight">' + htmlString.replace(regexp, '') + '</span>';
A simpler way with JQuery would be.
originalHtml = $("#div").html();
newHtml = originalHtml.replace(new RegExp(keyword + "(?![^<>]*>)", "g"), function(e){
return "<span class='highlight'>" + e + "</span>";
});
$("#div").html(newHtml);
This works just fine for me.
Here is a working regex example to exclude matches inside html tags as well as javascripts:
http://refiddle.com/lwy6
Use this regex in a replace() script.
/(a)(?!([^<])*?>)(?!<script[^>]*?>)(?![^<]*?<\/script>|$)/gi
this.keywords.forEach(keyword => {
el.innerHTML = el.innerHTML.replace(
RegExp(keyword + '(?![^<>]*>)', 'ig'),
matched => `<span class=highlight>${matched}</span>`
)
})
You can use string replace with this expression </?\w*> and you'll get your string
If you use jQuery, you can use the text property on the element containing the text you're searching for. Given this markup:
<p id="the-text">
The <strong>dog</strong> is really <em>really</em> fat!
</p>
This would yield "The dog is really really fat!":
$('#the-text').text();
You could do your regex search on that text instead of trying to do so in the markup.
Without jQuery, I'm unsure of an easy way to extract and concatenate the text nodes from all child elements.

removing part of string UPDATED

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("");
}

Categories