How can I do a complex substitution that using javascript and jQuery? - javascript

On my web pages I have source that looks like this:
<div id="opt_3" >A)</div>
<div id="opt_2" >B)</div>
<div id="opt_4" >C)</div>
<div id="opt_5" >D)</div>
<div id="opt_1" >E)</div>
What I need is to create a javascript that when running takes something like this as an input var:
Text 1 word word word this is a text 3 word word.
and changes it to
<strong>E</strong> word word word this is a <strong>A</strong> word word.
or
abc text 4 word
and changes it to
abc <strong>C</strong> word
The job of my javascript will be to taken the number inside of the string "Text X" or "text X", look at the first character of the id field that matches the value of X and substitute that character for "Text X".
I have jQuery loaded. Can that help by giving me some suggestioins? Do I need to use javascript as well as jQuery?
Can someone give me some advice on how I could do this. I am not very familiar with javascript or with jQuery.

You should this
var myText = 'Lorem {0} Dolor {1} Amet is a {2} text.';
var textReplace = function(txt) {
for (var i = 0, ii = arguments.length - 1; i < ii; i++) {
txt = txt.replace('{' + i + '}', arguments[i + 1]);
}
return txt;
}
textReplace(myText, 'ipsum', 'sit', 'dummy');
This function requires arguments. The first one is the text that you want to replace in a way. Other arguments will be replaced in your text. I suggest you to use wrapper texts with curly braces instead Text 4 or whatever.
I hope this will help.

The following code should do exactly as you describe:
var input = "Text 1 word word word this is a text 3 word word.";
input = input.toLowerCase();
var split = input.split(" ");
for(var i = 0; i < split.length; i++) {
if(split[i].toLowerCase() == "text") {
var num = split[i+1];
var val = $("#opt_" + num).text();
input = input.replace("text " + num, "<strong>" + val + "</strong>");
}
}
alert(input);
You can see it working here. It splits your string on spaces, then loops through the resulting array, looking for occurences of the word "text". When it finds one, it replaces that word and the next word (which will be a number according to your instructions) with the value of the corresponding element, wrapped in strong tags.

You could do a case-insensitive RegExp replace with a callback function, like this:
function textReplace(v){
return v.replace(/text ([0-9])/gi,function(i,e){
return "<strong>"+$("#opt_"+e).text().substring(0,1)+"</strong>";
});
}
example: http://jsfiddle.net/niklasvh/pLpxN/

For this you will need jQuery
//get the original text
txt = $('#text-container').text();
//split the whole text by the words "Text"
// this way each string in the array arr will contain as its first member the number
// without the splitting text
arr = txt.split('Text');
answerText = '';
for(i=0; i < arr.size(); i++){
words=arr[i].split(' '); //split by spaces
//the first word will be the number
nr = words[0];
//then we look up the corresponding option, and substitute the number
words[0] = $('#opt_'+nr).text();
//and rebuild the original text
answerText += words.join(' ');
}

Related

How do you create divs in javascript?

I am given a string as input, and the last letter in every word of the string should be capitalized, and then it is formed into their own div.
The one thing that I am finding tricky is that no matter what the string is there should always be enough divs to be separated, which to me means that I need to have a loop that generates it, which is what I am not sure how to write that logic.
I need this to be the output:
<div>
partY
</div>
<div>
likE
</div>
<div>
itS
</div>
<div>
2015
</div>
This is what I have so far:
function yay (input) {
input = input.toLowerCase().split("").reverse().join("").split(" ");
for(var i = 1 ; i < input.length ; i++){
var len = input[i].length-1;
input[i] = input[i].substring(0, len) + input[i].substr(len).toUpperCase();
}
return input .reverse().join(" ");
}
console.log(yay("Party like its 2015"));
Well, just a few minor changes to your code, which was on the right track... I basically removed the unnecessary reversing and wrapped each word in a div in the loop and viola:
function yay (input) {
input = input.toLowerCase().split(" ");
for(var i = 0 ; i < input.length ; i++){
var len = input[i].length-1;
input[i] = '<div>'+input[i].substring(0, len) + input[i].substr(len).toUpperCase()+'</div>';
}
return input.join("");
}
console.log(yay("Party like its 2015"));
document.write(yay("Party like its 2015"));
Output:
<div>partY</div><div>likE</div><div>itS</div><div>2015</div>
You can use document.createElement('div') and document.createTextNode('text') to simply get what you need.
You can return the content element directly to append to your node of your need, or you can use the innerHTML to do some text manipulations.
EDIT
Modified, I totally missed the last character needs to be uppercase
function yay(str) {
var arr = str.split(' ');
var content = document.createElement('div');
for(var part in arr) {
var sub = document.createElement('div');
var lastChar = arr[part].charAt(arr[part].length-1).toUpperCase();
var appendStr = arr[part].substring(0,arr[part].length-1);
sub.appendChild(document.createTextNode(appendStr+lastChar));
content.appendChild(sub);
}
return content.innerHTML;
}
console.log(yay("Party like its 2015"));
How about this:
function capitalizeLastLetter(input) {
return input.substring(0, input.length - 1) + input.charAt(input.length - 1).toUpperCase();
}
function yay(input) {
return input
.toLocaleLowerCase()
.split(" ")
.map(function(s){ return "<div>" + capitalizeLastLetter(s) + "</div>"; })
.join("");
}
console.log(yay("Party like its 2015"));
document.write(yay("Party like its 2015"));
Remixes this answer on how to capitalize the first letter of a word.
Add newlines where appropriate if you actually need those in your output.
You might want to use String.prototype.replace and feed it with a regular expression:
function yay(input) {
return input.
toLocaleLowerCase().
replace(/([^\s.,:;!?]*)([^\s.,:;!?")])([^\s]*)/g,
function(match, sub1, sub2, sub3) {
return '<div>' + sub1 + sub2.toLocaleUpperCase() + sub3 + '</div>';
});
}
The regex captures zero or more (because regular expressions are "greedy" by default, the algorithm will capture as many characters as it can) non-whitespace (to support alphabets other than Latin) and non-punctuation characters and exactly one non-whitespace/non-punctuation character following them (the last letter in the word, even if it's the only letter forming the word). The last group is zero or more of the previously specified punctuation marks (.,:;!?")). What it says is "non-whitespace character", but the presence of the two previous parenthesized groups implies that it must be a punctuation mark.
The replacement callback here uses four arguments, one (unused in this case) for the entire match and three for submatches corresponding to the parenthesized groups in the regex.
The value returned from the callback replaces the entire match in each successive replacement cycle (abcd in abcd efgh will be replaced with <div>abcD</div> and so on, note that whitespaces will be preserved).
In the callback function, the first submatch consists of all the letters in a word except the last one. It is returned as is, but the other match (which is the last letter) is capitalized. Optionally, a punctuation mark is appended if present in the original input. Everything is then wrapped in the <div> HTML tag and returned.
You can assign the value returned by the yay function to the innerHTML property of an HTML element, for example:
document.querySelector('#container').innerHTML = yay('Party like its 2015');
Spaces present in the input will remain. There is no need to replace them with new line characters, as all whitespaces are treated equally in HTML and will result in the same behavior.
Edit:
Now you can pass input containing punctuation to the function. The following line:
yay('Hello there, how about using some punctuation? "Quote" (Parentheses) ("What?")')
will result in:
'<div>hellO</div> <div>therE,</div> <div>hoW</div> <div>abouT</div> <div>usinG</div> <div>somE</div> <div>punctuatioN?</div> <div>"quotE"</div> <div>(parentheseS)</div> <div>("whaT?")</div>'

split string into array of n words per index

I have a string that I'd like to split in an array that has (for example) 3 words per index.
What I'd also like it to do is if it encounters a new line character in that string that it will "skip" the 3 words limit and put that in a new index and start adding words in that new index until it reaches 3 again. example
var text = "this is some text that I'm typing here \n yes I really am"
var array = text.split(magic)
array == ["this is some", "text that I'm", "typing here", "yes I really", "am"]
I've tried looking into regular expressions, but so far I can't really make sense of the syntax that is used in regex.
I have written a way to complicated function that splits my string into lines of 3 by first splitting it into an array of separate words using .split(" "); and then using a loop to add add it per 3 into another array. But with that I can't take the new line character into account.
You can try with this pattern:
var result = text.match(/\b[\w']+(?:[^\w\n]+[\w']+){0,2}\b/g);
since the quantifier {0,2} is greedy by default, it will take a value less than 2 (N-1) only if a newline is found (since newlines are not allowed here: [^\w\n]+) or if you are a the end of the string.
If you're interested in a regexp solution, it goes like this:
text.match(/(\S+ \S+ \S+)|(\S+ \S+)(?= *\n|$)|\S+/g)
// result ["this is some", "text that I'm", "typing here", "yes I really", "am"]
Explanation: match either three space separated words, or two words followed by spaces + newline, or just one word (a "word" being simply a sequence of non-spaces).
For any number of words, try this:
text.match(/((\S+ ){N-1}\S+)|(\S+( \S+)*)(?= *\n|$)|\S+/g)
(replace N-1 with a number).
Try something like this:
words = "this is some text that I'm typing here \n yes I really am".split(" ");
result = [];
temp = "";
for (i = 0; i < words.length; i++) {
if ((i + 1) % 3 == 0) {
result.push(temp + words[i] + " ");
temp = "";
} else if (i == words.length - 1) {
result.push(temp + words[i]);
} else {
temp += words[i] + " ";
}
}
console.log(result);
Basically what this does is splits the string by words, then loops through each word. Every third word it gets to, it adds that along with what is stored in temp into the array, otherwise it adds the word to temp.
Only if you know there are no words 'left', so the number of words is always a multiple of 3:
"this is some text that I'm typing here \n yes I really am".match(/\S+\s+\S+\s+\S+/g)
=> ["this is some", "text that I'm", "typing here \n yes", "I really am"]
but if you add a word:
"this is some text that I'm typing here \n yes I really am FOO".match(/\S+\s+\S+\s+\S+/g)
the result will be exactly the same, so "FOO" is missing.
here one more way:
use this pattern ((?:(?:\S+\s){3})|(?:.+)(?=\n|$))
Demo

javascript split when space but not always

I have got a text area and a function that splits the pasted content based on the spaces between content elements and turns them into labels one by one:
Say I have the following content to be pasted:
1234,john smith,john#test.com 4312,jack gold,jack#yahoo.com 5678,Brian,brian#gmail.com
and obviously I use
$('#testArea').on("paste", ".maininput", function (event) {
var text = $(element).val();
var contentArray = text.split(" ");
}
The result should be 3 labels with the following format (users mobile number,full name, email)
But because of the fact that there are spaces between firstname and lastname I am not able to get the right result.
What I am trying to achieve is sort of escaping the spaces when its between first and last name.
has anyone got any idea how to do it?
Don't split on spaces. Instead, scan for what you want:
var s = "1234,john smith,john#test.com 4312,jack gold,jack#yahoo.com 5678,Brian,brian#gmail.com"
var lines = s.match(/\S[^,]+,[^,]+,[^ ]+/g)
for (var i=lines.length;i--;){
console.log(lines[i].split(','));
}
// ["5678", "Brian", "brian#gmail.com"]
// ["4312", "jack gold", "jack#yahoo.com"]
// ["1234", "john smith", "john#test.com"]
That regex says:
Find something other than whitespace
Followed by one or more things that are not a comma
Followed by a comma
Followed by one or more things that are not a comma
Followed by a comma
Followed by one or more things that are not a space
Better to use a regular expression to match the pattern.
var str = "1234,john smith,john#test.com 4312,jack gold,jack#yahoo.com 5678,Brian,brian#gmail.co";
var matchGroups = str.match(/([^,]*,[^,]*,[^ ]*)/g); //look for pattern "XXX,XXX,XXX" followed by whitespace or end of line
console.log(matchGroups);
//Now work with the sections
for( var i=0;i<matchGroups.length;i++){
var parts = matchGroups[i].split(","); //split it into your parts on commas
console.log(parts);
}
JSFiddle
you can run a for loop to check the next character of space, and based on it you can replace space with or leave it as it is. I mean if the next character is a number you can simply leave the space as it is and if it is a letter change space to
For example, replace <space><digit> with |<digit> and then split on |:
text.replace(/ (\d)/g, "|$1").split("|")
Example:
"1234,john smith,john#test.com 4312,jack gold,jack#yahoo.com 5678,Brian,brian#gmail.com".replace(/ (\d)/g, "|$1").split("|")
["1234,john smith,john#test.com",
"4312,jack gold,jack#yahoo.com",
"5678,Brian,brian#gmail.com"]
jQuery( window ).load(function() {
jQuery("#FullNametest").change(function(){
var temp = jQuery(this).val();
var fullname = temp.split(" ");
var firsname='';
var middlename='';
var lastname = '';
firstname=fullname[0];
lastname=fullname[fullname.length-1];
for(var i=1; i < fullname.length-1; i++)
{
middlename = middlename +" "+ fullname[i];
}
jQuery('#FirstName').val(firstname);
jQuery('#middlename').val(middlename);
jQuery('#LastName').val(lastname);
});
});

jQuery Uppercase word locator

I need to locate words for more than 4 characters that are written between <p> </p> in uppercase and add them a style (ex. italic).
I know about the function isUpperCase() but don't know how to apply it to check if the string is more than 4 characters.
function isUpperCase( string ) {
(?)
}
Thanks.
var ps = [].slice.call(document.getElementsByTagName("p"))
ps.forEach(function (p) {
p.textContent.split(" ").forEach(function (word) {
if (word.length > 4 && word.toUpperCase() === word) {
// 4character UPPERCASE word
}
})
})
You could use a regex to replace any uppercase text longer than four characters in the innerHTML of every <p> element with that text surrounded by the markup you're trying to insert:
$('p').each(function(){
var pattern = /([-A-Z0-9]{4,})/g;
var before = '<span style="color: red;">';
var after = '</span>';
$(this).html($(this).html().replace(pattern, before+"$1"+after));
});
http://jsfiddle.net/eHPVg/
Yeah, like Rob said, I don't think Raynos's answer will work cross-browser and it also won't let you modify the matches within the paragraph.
Here's a slightly modified version:
var i = 0, ps = document.getElementsByTagName("p");
for(len = ps.length; i<len; i++)
{
var p = ps[i];
p.innerHTML = p.innerHTML.replace(/\b([A-Z]{4,})\b/g, "<span style='font-style:italic'>$1</span>";
}
You can change the span code to be whatever style you want to add. Just make sure to leave the $1, which refers the original uppercase word.

Count number of words in string using JavaScript

I am trying to count the number of words in a given string using the following code:
var t = document.getElementById('MSO_ContentTable').textContent;
if (t == undefined) {
var total = document.getElementById('MSO_ContentTable').innerText;
} else {
var total = document.getElementById('MSO_ContentTable').textContent;
}
countTotal = cword(total);
function cword(w) {
var count = 0;
var words = w.split(" ");
for (i = 0; i < words.length; i++) {
// inner loop -- do the count
if (words[i] != "") {
count += 1;
}
}
return (count);
}
In that code I am getting data from a div tag and sending it to the cword() function for counting. Though the return value is different in IE and Firefox. Is there any change required in the regular expression? One thing that I show that both browser send same string there is a problem inside the cword() function.
[edit 2022, based on comment] Nowadays, one would not extend the native prototype this way. A way to extend the native protype without the danger of naming conflicts is to use the es20xx symbol. Here is an example of a wordcounter using that.
Old answer: you can use split and add a wordcounter to the String prototype:
if (!String.prototype.countWords) {
String.prototype.countWords = function() {
return this.length && this.split(/\s+\b/).length || 0;
};
}
console.log(`'this string has five words'.countWords() => ${
'this string has five words'.countWords()}`);
console.log(`'this string has five words ... and counting'.countWords() => ${
'this string has five words ... and counting'.countWords()}`);
console.log(`''.countWords() => ${''.countWords()}`);
I would prefer a RegEx only solution:
var str = "your long string with many words.";
var wordCount = str.match(/(\w+)/g).length;
alert(wordCount); //6
The regex is
\w+ between one and unlimited word characters
/g greedy - don't stop after the first match
The brackets create a group around every match. So the length of all matched groups should match the word count.
This is the best solution I've found:
function wordCount(str) {
var m = str.match(/[^\s]+/g)
return m ? m.length : 0;
}
This inverts whitespace selection, which is better than \w+ because it only matches the latin alphabet and _ (see http://www.ecma-international.org/ecma-262/5.1/#sec-15.10.2.6)
If you're not careful with whitespace matching you'll count empty strings, strings with leading and trailing whitespace, and all whitespace strings as matches while this solution handles strings like ' ', ' a\t\t!\r\n#$%() d ' correctly (if you define 'correct' as 0 and 4).
You can make a clever use of the replace() method although you are not replacing anything.
var str = "the very long text you have...";
var counter = 0;
// lets loop through the string and count the words
str.replace(/(\b+)/g,function (a) {
// for each word found increase the counter value by 1
counter++;
})
alert(counter);
the regex can be improved to exclude html tags for example
//Count words in a string or what appears as words :-)
function countWordsString(string){
var counter = 1;
// Change multiple spaces for one space
string=string.replace(/[\s]+/gim, ' ');
// Lets loop through the string and count the words
string.replace(/(\s+)/g, function (a) {
// For each word found increase the counter value by 1
counter++;
});
return counter;
}
var numberWords = countWordsString(string);

Categories