Javascript Split properties into Object exclude inside Strings - javascript

What is the best method for splitting or extracting the css properties out of as string and into an object?
var cssProperties = 'background:green;content:"Content;";color:pink;';
The above should result in the following
var theObject = {
background:'green',
content:'"Content;"',
color:'pink'
}
Unfortunately I can not just use a split(";") and cycle through the array due to the semicolon in the url. I could create a giant loop that cycles through every character while skipping the ";" only while wrapped in quotes, but that seems kinda of wrong.
Is there a regex trick for this?
Optional:
Also are there any really good regex websites. I understand most of the syntax but there doesn't seem to be many practical really complicated examples on most of the websites I have found.

Here is a fiddle further demonstrating the function: http://jsfiddle.net/ZcEUL/
(function() {
var div = document.createElement('div'),
rprops =/[\w-]+(?=:)/g,
rcamelCase = /-(\D)/g,
fcamelCase = function(a,letter) {
return letter.toUpperCase();
};
window['styleToObject'] = function(str) {
var props = str.match(rprops),
prop, i = 0,
theObject = {};
div.style.cssText = str;
while (prop = props[i++]) {
var style=div.style[prop.replace(rcamelCase,fcamelCase)];
if (style) {
theObject[prop] = style;
}
}
return theObject;
};
})();

Here was the solution I made regarding your first css string you had listed... Not the best but maybe it'll help spark some ideas.
JSFiddle Example

Try this or something similar
var newString = cssProperties
.replace(":", ":'")
.replace(";", ", '");
var obj = eval(newString);

Related

Using str.replace for multiple words

I am creating a work tool for notepad abbreviations. As the company I work for is strict about downloading any external tools I've resorted to using Javascript and HTML built on notepad.
I've been able to replace single words such as when I type "Vacancy" it returns "VAC". Or when typing "Payment" it returns "PYMT". My issue is trying to replace multiple words into 1 small abbreviation. For instance "Follow Up" I want to return "F/U". With the spaces I'm finding it is not working.
Tried multiple ways but unable to figure this out.
Here is the code snippet that I've used
function myFunction() {
var str = document.getElementById("demo").value;
var mapObj = {
Payment:"PYMT",
Vacancy:"VAC",
str = str.replace(/Payment|Vacancy, fucntion(matched){
return mapObj[matched];
});
alert(str);
document.getElementById("demo").value = res;
}
What I would like to do is add my mabObj
so it would read
function myFunction() {
var str = document.getElementById("demo").value;
var mapObj = {
Follow Up:"F/U"
str = str.replace(/Follow Up|, fucntion(matched){
return mapObj[matched];
});
alert(str);
document.getElementById("demo").value = res;
}
JavaScript objects can have properties with spaces in them, but in order to do so, the property name needs to have quotes around it.
That said, I would suggest using a Map in this case, as it will allow you to match any string without worrying about naming collisions with properties from the object's prototype.
const abbreviation = new Map([
['Follow Up', 'F/U'],
['Payment', 'PYMT'],
['Vacancy', 'VAC']
]);
const input = 'Payment noise Vacancy noise Follow Up noise Vacancy';
const pattern = new RegExp(Array.from(abbreviation.keys()).join('|'),'g');
const result = input.replace(pattern, (matched) => {
return abbreviation.get(matched) || matched;
});
console.log(result); // 'PYMT noise VAC noise F/U noise VAC'
To include a key with a space in an object you can put it in brackets like {["Follow Up"]: "F/U"}
function replaceKeyWords(str) {
var mapObj = {
Payment:"PYMT",
Vacancy:"VAC",
["Follow Up"]:"F/U",
};
str = str.replace(/(Payment|Vacancy|Follow Up)/, function(matched){
return mapObj[matched];
});
return str;
}
console.log(replaceKeyWords("Payment"));
console.log(replaceKeyWords("Vacancy"));
console.log(replaceKeyWords("Follow Up"));

Mutate string originating from React state

Let's say for some delicate reason I have the following react state:
{ superGreeting: 'Hello!!!' }
Now, assume I have this complicated operation that basically takes the superGreeting string and works on it, in the end replacing a character at a specific position. New state then should be:
{ superGreeting: 'Hullo!!!' }
So, there would be my action:
action = (index) => {
var { superGreeting: newGreeting } = this.state;
newGreeting[index] = 'u';
this.setState({superGreeting: newGreeting});
}
Unfortunatelly, such approach does not work and ends with:
TypeError: Cannot assign to read only property '1' of string 'Hello!!!', indicating this line as the offending one: newGreeting[index] = 'u'
I use react.js, ES6, no redux, no mobx, no immutable.js. Thought that the issue is caused by the string still being related/used by the soon-to-be-previous state, so I thought that creating a copy would work (I tried newGreeting = newGreeting.toString(), '' + newGreeting, `${newGreeting}`, ''.concat(newGreeting), without any success). Any ideas?
Strings in JavaScript are immutable. Your example can be trimmed down to
(function(){
"use strict";
var str = 'Hullo!!!';
str[1] = 'e';
})();
If you want to mutate a string, you'll need to create a new string, e.g.
(function(){
"use strict";
var str = 'Hullo!!!';
str = str.slice(0, 1) + 'e' + str.slice(2);
})();
Strings in JS are immutable, but you can turn it into an array, work on it, then join it back together.. also there are string functions like substr and replace which return a new string if those are applicable.
var split = superGreeting.split('')
split[index] = 'u'
var newGreeting = split.join('')
Your problem here does not have anything to do with react. Strings in javascript are immutable.
You could create the following helper function:
var replaceCharAt = function(str, index, c) {
return str.slice(0, index) + c + str.slice(index+1)
}
so that
replaceCharAt('012', 1, 'x') === '0x2'

adding line breaks to array values javascript

Here is my javascript array:
var quizArray = [
'When the weather is agreeable what do you prefer to do the most?~Something outside...Obviously!~I tend to enjoy things that aren\'t dependent on weather.~Read, possibly outside if I can find my sunscreen.~Do what I always do, which is whatever I want.~Try something new, like Planking.~~~','It\'s a weeknight and friend invites you to an orchestra. You would?~Kindly refuse. It\'s just not my thing.~Go, unquestionably. I love all art forms.~Ask who the composer is, then read all about them before going.~Confuse Orchestra with Opera and begin singing in Latin.~Go if the tickets are free, otherwise no.~~~',]
When I load my html it won't display line breaks after each answer. I've tried adding a .join(<\br>) after split, but that breaks up every single word, here is the code I have:
function displayQuiz(ent, qnum) {
perPage++;
var qna = quizArray[qnum].split('~');
var od = []; for (var i = 1; qna[i] != null && qna[i] != ''; i++) od.push(i); od.sort( randOrd ); od.sort( randOrd );
var newF = document.createElement("form");
var newDq = document.createElement("div");
newDq.className = 'question';
newDq.appendChild(document.createTextNode(Number(qnum+1)+ ': ' +qna[0]));
newF.appendChild(newDq);
newDq = document.createElement("div");
newDq.className = 'answers';
for (var i = 1; qna[i] != null && qna[i] != ''; i++) {var newDa = document.createElement("label"); newDa.htmlFor = 'a'+qnum+i; /*#cc_on #if (#_jscript) var newR = document.createElement("<input name='a"+qnum+"'>"); #else */
var newR = document.createElement("input");
newR.name = 'a'+qnum; /* #end #*/
newR.type = 'radio';
newR.id = 'a'+qnum+i;
newR.value = od[i-1];
newDa.appendChild(newR);
newDa.appendChild(document.createTextNode(' '+qna[od[i-1]]+' '));
newDq.appendChild(newDa);}
newF.appendChild(newDq);
document.getElementById('quiz'+perPage).appendChild(newF);
}
I'll try my best to post additional info if needed. I did use this as a snippet and am very novice on Javascript. Not opposed to learning on my own but I've poured over the interwebs and cannot find my answer.
to make an array of Strings its better if you put your complete string in a var and after make a split(), and for add you can use a join() or a for()
It's better put this way the code
var quizArray = 'When the weather is agreeable what do you prefer to do the most?~Something outside...Obviously!~I tend to enjoy things that aren\'t dependent on weather.~Read, possibly outside if I can find my sunscreen.~Do what I always do, which is whatever I want.~Try something new, like Planking.~~~';
function displayQuiz(ent, qnum) {
perPage++;
var qna = quizArray.split('~');
var res = qna.join(" <br> ");
return res;
}
Here is the approach that I took, using .join to add the br element. I think you weren't specifying what to split on originally, if it added br after every word.
var string = 'When the weather is agreeable what do you prefer to do the most?~Something
outside...Obviously!~I tend to enjoy things that aren\'t dependent on weather.~Read, possibly outside if I can find my sunscreen.~Do what I always do, which is whatever I want.~Try something new, like Planking.~~~';
var quizArray = string.split('~');
var finalString = quizArray.join('<br/>');
document.getElementById('yourIdHere').innerHTML = finalString;
Here's a fiddle: http://jsfiddle.net/brettwlutz/Q35J2/1/
i thought arrays were made as so:
var arr = [val1, val2, val3];
you can use arr.push to append more values or arr.unshift to add values to the beginning of the array
http://jsfiddle.net/h_awk/K3kEv/
<script>
var arr = [1, 2, 3, 4], i;
for( i=0; i<arr.length; i++ )
{
document.write(arr[i] + '<br />');
}
</script>
First, to answer your question. The above code should work and make the variable qna contain the new, split array. Your solution of adding .join("") should then turn that new array into a single string with html newlines. That is, unless you want t JS newline, in which case you should instead use .join("\n").
My question for you is, why are you starting with an array with only one element? A string can be split into an array and joined back into a string the same way. Also, it may be easier to, instead of using the tilde ~ to seperate the statements you want to split, just use a form of proper array syntax, then get rid of the "split" and just use the joining:
var quizArray = ["When the weather is agreeable what do you prefer to do the most?", "Something outside...Obviously!, I tend to enjoy things that aren\'t dependent on weather.", "Read, possibly outside if I can find my sunscreen.", "Do what I always do, which is whatever I want.", "Try something new, like Planking."];
My only possible understanding is that you are still learning JS and this is just an example for learning how to split arrays, but this is not really a real-life application, which is why this post seems questionable to Stack Overflow users.

jQuery .each help, I want to trim() all the strings in an array

I'm splitting a string into an array, then I want to remove the white space around each element. I'm using jQuery. I'm able to do this successfully with 2 arrays but I know it's not correct. How do I loop thru an array and trim each element so the elements keep that change. Thanks for any tips. Here is my working code using two array. Please show me the correct way to do this.
var arVeh = vehicleText.split("|");
var cleanArry = new Array();
$.each(arVeh, function (idx, val) {
cleanArry.push($.trim(this));
});
Cheers,
~ck in San Diego
You don't even really need the idx or val parameters. This appears to work on jsFiddle:
var cleanVehicles = [];
$.each(vehicleText.split("|"), function(){
cleanVehicles.push($.trim(this));
});
EDIT: Now that I've seen what you're really after, try using map:
var cleanVehicles = $.map(vehicleText.split("|"), $.trim);
I'm going to suggest not using the overhead of jQuery for a simple for-loop...
var arVeh = vehicleText.split("|");
for (var i = 0, l = arVeh.length; i < l; ++i) {
arVeh[i] = $.trim(arVeh[i]);
});
Alternatively, get rid of the whitespace from the beginning, and avoid the need for another loop at all.
var arVeh = $.trim(vehicleText).split(/\s*\|\s*/);
Without 'creating' an array in the javascript code (an array will nevertheless be created in memory)
vehicles = $.map(vehicleText.split("|"), function(e,i) { return $.trim(e) });
var my_arr = [' cats', 'dogs ', ' what '];
$.each(my_arr, function (id, val) {
my_arr[id] = $.trim(val);
});
console.log(my_arr);
This will trim the value and set it to the indexed item.
You don't have to use JQuery. Here is your vanilla solution:
testArray.map(Function.prototype.call, String.prototype.trim);
Function.prototype.call calls trim() on each of the elements of the testArray. As simple as that!
Could you not just do this?
var arVeh = vehicleText.split("|");
$.each(arVeh, function (idx, val) {
arVeh[idx] = $.trim(this);
});
//a simple function
function trimArray(dirtyArray){
$.map(dirtyArray.split("|"), function(idx, val){
return $.trim(this);
});
}
trimArray(vehicleArray);
should do the trick
Or you could use some of the awesome power of javascript and use array.prototype. I'm still a little new at using the .prototype of any object... so this isnt guaranteed to work (but it certainly can be done).
Array.prototype.trim = function (){
$.map(dirtyArray.split("|"), function(idx, val){
return $.trim(this);
});
}
someArray.trim()
You need these two jQuery functions:
1.) iterate through array element with ability to edit items:
http://api.jquery.com/jquery.map/
2.) remove blank spaces from beginning and end of a string:
http://api.jquery.com/jQuery.trim/
Use them this way:
array = $.map(array, function(value) { return value.trim();});
Check this JSFiddle:
https://jsfiddle.net/L00eyL4x/49/

How to do multiple regular expressions, each time refining the results?

Why can't I output my regex to a variable, and then run regex on it a second time?
I'm writing a greasemonkey javascript that grabs some raw data, runs some regex on it, then runs some more regex on it to refine the results:
// I tried this on :: http://stackoverflow.com/
var tagsraw = (document.getElementById("subheader").innerHTML);
alert(tagsraw);
Getting the raw data (above code) works
var trimone = tagsraw.match(/title\W\W\w+\s\w+\s\w+\s\w+\s\w+/g);
alert(trimone);
running regex once works (above code); but running (code below) doesn't??
var trimtwo = trimone.match(/\s\w+\s\w+\s\w+\s\w+/g);
alert(trimtwo);
Can some advise me as to what is wrong with my code/approach?
The reason the first match works, is because innerHTML returns a string.
However the match returns an array, thus treat it as one:
for (var i=0; i<trimone.length; i++)
{
var trimtwo = trimone[i].match(/\s\w+\s\w+\s\w+\s\w+/g);
alert(trimtwo);
}
Edit:
Try this code instead though, I think this is a bit closer to what you want to achieve:
var trimone = tagsraw.match(/title\s*=\s*".*"/g);
alert(trimone);
for (var i=0; i<trimone.length; i++)
{
alert(trimone[i]);
}
You could do something like this:
var str = "<title> foo bar baz quux blah</title>",
re = [
/title\W\W\w+\s\w+\s\w+\s\w+\s\w+/g,
/\s\w+\s\w+\s\w+\s\w+/g
],
tmp = [str];
for (var i=0, n=re.length; i<n; ++i) {
tmp = tmp.map(function(val) {
return val.match(re[i])[0];
});
}
alert(tmp);
.match should be returning an array, not a string.
Your case is better suited to using .exec. You could even chain the two if you don't care about the intermediate result:
/\s\w+\s\w+\s\w+\s\w+/g.exec(/title\W\W\w+\s\w+\s\w+\s\w+\s\w+/g.exec(tagsraw));
The problem is that match() returns an array and there is no built-in function to perform a regular expression on an array.
So instead you should be able to do this with the exec function from the Regexp object. It will return the matched string. You can grab the matched string from the first regexp and use it for the second.
So it'd be something like this:
var patt1 = new Regexp(/title\W\W\w+\s\w+\s\w+\s\w+\s\w+/g);
var trimone = patt1.exec(tagsraw);
if (trimone != null) // might be null if no match is found
{
alert(trimone);
var patt2 = new Regexp(/\s\w+\s\w+\s\w+\s\w+/g);
var trimtwo = patt2.exec(trimone);
alert(trimtwo);
}
Note that exec returns null if no match is found so be sure to handle that in your code like I do above.

Categories