Problems with RegEx with Javascript - javascript

else if( (m = url.match(/^(https?:\/\/ww[\d]+\.sinaimg\.cn\/)([^\/]+)(\/.+)$/i)) ) {
if(m[2] != "large") {
document.location = m[1] + "large" + m[3];
}
}
So the above is a working piece of Javascript... And I am trying to make a regex of another URL that fits into the code... But I couldn't seemd to quite get how it works...
What is m[1] and m[3] BTW?
This is the URL I intend to change about:
a.up.w.com/i/EF8W-P67s6dqRPIj7cLlMQ!/fw/300/format/jpg/quality/90
How can I make a Regex that replaces 300 to 3000, jpg to png (or not) and 90 to 100?
I made this one but nothing seemed to work...
else if( (m = url.match(/^(https?:\/\/a\+\.up\.w\.com\/i\/)([^\/]+)(\/fw\/)([^\/]+)(\/format\/)([^\/+])(\/quality\/+)([^\/]+)$/i)) ) {
Thank you very much!!!

/^(https?://ww[\d]+.sinaimg.cn/)([^/]+)(/.+)$/i
To read regular expressions most people need some automated tool as a helper.
I created your regex with an example: https://regex101.com/r/mP5zI9/3
Example caught link: https://ww1.sinaimg.cn/aaa/bbb.jpg
1. https://ww1.sinaimg.cn/
2. aaa
3. /bbb.jpg
the m array contains the different parts of the match.
For full javascript details see: MDN documentation for String.prototype.match()

You might be going about this the wrong way. Sometimes it's easier to break a task down.
url = "http://a.up.w.com/i/EF8W-P67s6dqRPIj7cLlMQ!/fw/300/format/jpg/quality/90";
m = url.replace(
/\/fw\/\d+/,"/fw/3000"
).replace(
/\/format\/jpg/,"/format/png"
).replace(
/\/quality\/\d+/,"/quality/100"
);

May be you only need to care about this part /300/format/jpg/quality/90,
Then use replace like this.
url.replace(/(\d+)\/format\/jpg\/quality\/(\d+)/, function($0, $1, $2) {
return 3000 + '/format/png/quality/' + 100;
}

else if( (m = url.match(/^(https?:\/\/a+\.up+\.w+\.com\/i\/+)([^\/]+)(\/fw\/+)([^\/]+)(\/format\/+)([^\/+]+)(\/quality\/+)([^\/]+)$/i)) ) {
if(m[4] != "3000" || m[8] !=100) {
document.location = m[1] + m[2] + m[3] + "3000" + m[5] + m[6] + m[7] + "100";
}
}
Thanks everyone! I've got it! :P
Special thanks to #Lavi Avigdor for the inspiration (again)

Related

JavaScript string modification (Probably involves regular expression)

The problem I need to solve is to shorten file paths given by the user. If you didn't know, sometimes it's not possible to enter in paths with spaces in the command prompt. You are required to either put the path in quotes or rename the paths with spaces to "abcdef~1".
Example: "C:\Some Folder\Some File.exe" should become "C:\SomeFo~1\SomeFi~1.exe" (case insensitive).
I'm making a function in JavaScript to attempt to shorten file paths using this idea.
function ShortenFilePath(FilePath){
var Sections = FilePath.split("\\")
for (Index = 0; Index < Sections.length; Index++){
while (Sections[Index].length > 6 && Sections[Index].match(" ") && !Sections[Index].match("~1")){
alert(Sections[Index])
Sections[Index] = Sections[Index].replace(" ","")
Sections[Index] = Sections[Index].substring(0,6)
Sections[Index] = Sections[Index] + "~1"
alert(Sections[Index])
}
}
var FilePath = Sections.join("\\")
alert(FilePath)
return FilePath
}
The problem is, it will leave out the file extension and spit out "C:\SomeFo~1\SomeFi~1". I need help obtaining that file extension (probably through regular expression). If you feel that this function can be optimized, please do share your thoughts.
UPDATE: I believe the problem has been resolved.
UPDATE 2: There were some problems with the previous code, so I revised it a little.
UPDATE 3: Fresh new problem. Yikes. If the name of the file itself without the extension is under 7 letters, then it will turn up as "name.e~1.exe".
UPDATE 4: I think I've finally fixed the problem. I THINK.
function ShortenFilePath(FilePath){
var Sections = FilePath.split("\\")
Sections[Sections.length - 1] = Sections[Sections.length - 1].substring(0,Sections[Sections.length - 1].lastIndexOf("."))
for (Index = 0; Index < Sections.length; Index++){
while (Index > 0 && Sections[Index].match(" ") && !Sections[Index].match("~1")){
Sections[Index] = Sections[Index].replace(/ /gm,"")
Sections[Index] = Sections[Index].substring(0,6) + "~1"
}
}
return Sections.join("\\") + FilePath.substring(FilePath.lastIndexOf("."))
}
I would use this to get the extension:
someString.substring(someString.lastIndexOf("."))
you also asked for some code review, so:
1 - Your JS conventions are a little off, it looks more like C# :) Why the capital letter in variable and method names?
2 - You said you can go with the quotes option instead of using ~1, seems easier, why did you decide not to?
3 - Why do you need something like this in your JS?
How about this:
function ShortenFilePath(FilePath){
var Sections = FilePath.split("\\")
var suffix = FilePath.match(/(\..*$)/)
for (Index = 0; Index < Sections.length; Index++){
while (Sections[Index].length > 6 && Sections[Index].match(" ") && !Sections[Index].match("~1")){
alert(Sections[Index])
Sections[Index] = Sections[Index].replace(" ","")
Sections[Index] = Sections[Index].substring(0,6)
Sections[Index] = Sections[Index] + "~1"
alert(Sections[Index])
}
}
var FilePath = Sections.join("\\") + (suffix? suffix[1] : '')
alert(FilePath)
return FilePath
}
You could use String.prototype.replace with a callback:
function ShortenFilePath(FilePath){
return FilePath.replace(/([^:\\]+)([\\|\.[^\\]+)/g, function(text,match1, match2){
return match1.length > 8 ? match1.replace(' ', '').substr(0, 6) + '~1' + match2 : match1.replace(' ', '') + match2;
});
}
I am not 100% sure that this will output excactly what you need but probably you get the idea :)
jsFiddle
Fix for Update #3 problem:
if (FilePath.lastIndexOf(".") > 6){
Sections[Index] = Sections[Index].substring(0,6) + "~1"
} else {
Sections[Index] = Sections[Index].substring(0, FilePath.lastIndexOf(".")) + "~1"
}
And btw, this:
while (Sections[Index].match(" ")){
Sections[Index] = Sections[Index].replace(" ","")
}
Should probably look like this:
Sections[Index] = Sections[Index].replace(/ /gm, "");

Master JavaScript Regex Guru Needed For Recursive Filtering

I'm in serious trouble with a JavaScript regex. What I want is "regex only" solution to perform transformations like this :
{{ users.name.find(50, "q")|lower }} ---> lower(users.name.find(50, "q"))
I ended up with the following decomposition, and it works great :
var m = '{{ users.name.find(50, "q")|lower }}';
var p = m.replace(/{{2}[ ]*([^{}, ]*[^{}]*[^{}, ]+)[ ]*}{2}/g, "$1");
console.log(p); ---> users.name.find(50, "q")|lower
var k = p.replace(/(.+)(\|{1}(.*))+/g, "$3($1)");
console.log(k); ---> lower(users.name.find(50, "q")) ---> OK, it's fine.
But now, I want it to work with much complicated filtering like that :
var m = '{{ users.name.find(50, "q")|lower|filter(5, 9)|short|encode(true) }}';
I'm expecting something like this at the end :
console.log(
m.replace(/MagicalRegexFromHell/g)
.split(...).join(...)
.replace(/GuruRegex2/g, 'recursive thing that does not exists $n($n-1)')
.replace('/OkItsDone/g')
)
----> encode(short(filter(lower(users.name.find(50, "q")), 5, 9)), true)
I've spent hours on it, so please if anybody has a solution using only split() / replace() / regex and join() it would be cool because I'm not able to use branch statements in my code implementation (that's it: no switch, no if etc ...)
Thank you.
You could do something like that:
// var p comes from your code
var r = p.split(/|/).reduce(function(txt, f) {
var par = (f.indexOf("(") + 1) || f.length;
return f.substring(0, par)
+ (par == f.length ? "(" : "")
+ txt
+ (par == f.length ? ")" : ", ") + f.substring(par);
});
I don't think you can apply a regex recursively without a loop.

How to do Initial Caps With Javascript/jQuery

I have a Dynamic Breadcrumb set up with JavaScript. All I want is to do Initial Caps for each word.
Example:
Home > Some > Page
Currently I have them all converted to lowercase and have removed all - from the strings in pages that have multiple words. I just need to convert the string to Initial Caps. Here is my code that I have working so far:
var path = "",
href = document.location.href,
domain = href.match(/:\/\/(.[^/]+)/)[1],
replacedomain = 'http://' + domain + '/',
s = href.replace(/-/gi, " ").split("/"),
lastElement = document.location.href.split('/').splice(-1,1);
for (var i = 2; i < (s.length - 1); i++) {
path += "<a class='bc' href=\"" + href.substring(0, href.indexOf("/" + s[i]) + s[i].length + 1) + "/\">" + s[i] + "</a> > ";
if (i > 0) {
breadcrumb = path;
}
}
i = s.length - 1;
breadcrumb += "<span>" + s[i] + "</span>";
var breadcrumbl = breadcrumb.toLowerCase(),
domain = breadcrumbl.match(/:\/\/(.[^/]+)/)[1],
breadcrumb2 = breadcrumbl.replace(domain, "").replace(domain, ""),
breadcrumbs = breadcrumb2,
url = 'Home' + breadcrumbs;
document.getElementById('breadcrumb1').innerHTML=url;
I think the solution is with a regular expression but I'm not good at writing them and I'm having a hard time with the concept. Also if anyone thinks this script can be optimized further your feedback is welcome. I'll will make variable names more semantic for production.
You could use css:
span.breadcrump {
text-transform: capitalize;
}
I recently wrote this helper method to do this for me:
function autocase ( text ) {
return text.replace(/(&)?([a-z])([a-z]{2,})(;)?/ig,function ( all, prefix, letter, word, suffix ) {
if (prefix && suffix) {
return all;
}
return letter.toUpperCase() + word.toLowerCase();
});
}
It takes into account things such as ™
Edit: To use this method, simply pass it a string, and it will return the string auto cased. It does not work on html strings.
//...
document.getElementById('breadcrumb1').innerHTML=url;
function autocase ( text ) {
return text.replace(/(&)?([a-z])([a-z]{2,})(;)?/ig,function ( all, prefix, letter, word, suffix ) {
if (prefix && suffix) {
return all;
}
return letter.toUpperCase() + word.toLowerCase();
});
}
$("#breadcrumb1 a").text(function(i,text){
return autoCase(text);
});
Try using css property text-transform:capitalize; for the breadcrumb.
Mostlikely in you case it should be,
.breadcrumb1 a {
text-transform: capitalize;
}
My first thought is:
breadcrumb += "<span>" + s[i].substring(0,1).toUpperCase() + s[i].substring(1) + "</span>";
But #Esailija's answer is much easier.
Reference:
toUpperCase().
not to be a punk but why not just use css?
text-transform: capitalize;
Sorry if you really need JS but in CSS you can easily use text-transform:Capitalize;
Since the accepted answer didn't actually answer the question as it was asked, I figured this might help; it's a solution using Regex with JavaScript, originally found here: Regex capitalize first letter every word
Here's the snippet I found useful:
var re = /(\b[a-z](?!\s))/g;
var s = "fort collins, croton-on-hudson, harper's ferry, coeur d'alene, o'fallon";
s = s.replace(re, function(x){return x.toUpperCase();});
console.log(s); // "Fort Collins, Croton-On-Hudson, Harper's Ferry, Coeur D'Alene, O'Fallon"
Here's one:
s.replace(/(^[a-zA-Z]{1})/,function (s){
return s.toUpperCase();
});

getElementById.value and getElementById.value?

I have a problem regarding this two values from my textboxes (text, text2), seems like text2 only show its value, is there any way I can get rid of these things. Any help would be so much appreciated.
parameters = ('text=' + document.getElementById('text').value) && ('text2=' + document.getElementById('text2').value;
xmlhttp.open('POST', 'try.php', true);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send(parameters);
parameters = ('text=' + document.getElementById('text').value) && ('text2=' + document.getElementById('text2').value;
This line is wrong. && does not mean "concatenate": it means "logical and". Basically, it means "return false if either side of the operator is falsy, otherwise, return the right-hand-side". So this will always return 'text2=' + document.getElementById('text2').value, because this is the right-hand-side of the && operator.
You need to concatenate them, for which the operator, as you use quite correctly otherwise, is +.
parameters = 'text=' + document.getElementById('text').value + '&' + 'text2=' + document.getElementById('text2').value;
Note that you should probably also use encodeURIComponent to make sure you're making valid HTTP requests:
parameters = 'text=' + encodeURIComponent(document.getElementById('text').value) + '&' + 'text2=' + encodeURIComponent(document.getElementById('text2').value);
Don't use && to concatenate strings, use +. There are also unbalanced brackets and you are missing the "&" to separate your parameters in the URL string.
parameters = 'text=' + document.getElementById('text').value + '&text2=' + document.getElementById('text2').value;

Making a value plural (Greater than, Less than) in Javascript

I have the following code:
$(function(){
var total_click = 0;
$("#mapKey a.showKey").click(function(){
total_click = total_click + 1;
$("#counter").text("I cheated " + total_click + " whole" + (total_click = 1 ? + ' time' + ((total_click > 1) ? 's ' : ' ') : ''));
return false;
});
});
I'm trying to have it output as such:
Clicked once: "I cheated 1 whole time."
Clicked more than once: "I cheated X whole times."
-- With an 's' at the end of "times".
The counter is working fine, it's just the last part making the "time" or "times" show up appropriately that I am having difficulty with.
Any ideas what I'm doing wrong?
Thanks!
Here is your problem: total_click = 1. Try changing it to total_click == 1. I don't see why you have that conditional in there however, as it won't work as you expect anyway. Try $("#counter").text("I cheated " + total_click + " whole time" + ((total_click == 1) ? ' ' : 's '));
You are not using the ternary operator correctly, and also assigning total_click to 1 instead of checking its value. I would suggest moving this to a function to simplify things.
function pluralize(singular, times) {
if (times == 1) return singular;
else return singular + 's';
}
Then change the string to
var text = "I cheated " + clicks + " whole " + pluralize("time", clicks);
Here's an example.
$(function(){
var total_click = 0;
$("#mapKey a.showKey").click(function(){
total_click = total_click + 1;
$("#counter").text("I cheated " + total_click + " whole " + (total_click == 1 ? "time" : "times");
return false;
});
});
It's okay to use suggested implementations for a trivial cases, however it will not scale for a bigger set of problems and will not work for multiple languages (or it will get ugly very fast).
With this in mind, I’ve created a very simple JavaScript library that can be used to pluralize words in almost any language. It transparently uses CLDR database for multiple locales. It’s API is very minimalistic and integration is extremely simple. It’s called Numerous.
I’ve also written a small introduction article to it: «How to pluralize any word in different languages using JavaScript?».
Feel free to use it in your project. I will also be glad for your feedback on it!

Categories

Resources