Custom Backbonejs route parameters - javascript

Consider this URL:
domains.google.com/registrar#t=b
note:
#t=b
In this example, the variable "t" stores the current tab on the page where "b" is for billing.
How can I achieve query like parameters in backbone as shown above?
I understand Backbone has routes that support parameters in urls, but this is limited to when the data is in a hierarchy, for example: item/:id
But what about application settings that would not work well in a directory like structure?
The only solution I can think of is a custom parser and break up the key/values myself.
Any ideas?

Expanding on #try-catch-finally's comment, I'm going to show you how to create your own route with a simple RegEx pattern that will match your conditions.
Here's the regex we'll use:
^\w+? # match one word (or at least a character) at the
# beginning of the route
[=] # until we parse a single 'equals' sign
( # then start saving the match inside the parenthesis
[a-zA-Z0-9]* # which is any combination of letters and numbers
) # and stop saving
Putting it all together the regex looks like: /^\w+?[=]([a-zA-Z0-9]*)/.
Now we set up our router,
var MyRouter = Backbone.Router.extend({
initialize: function(options) {
// Matches t=b, passing "b" to this.open
this.route(/^\w+?(?<=[=])(.*)/, "testFn");
},
routes: {
// Optional additional routes
},
testFn: function (id) {
console.log('id: ' + id );
}
});
var router = new MyRouter();
Backbone.history.start();
The TL;DR is that in the MyRouter.initialize we added a route that takes the regex above and invokes the MyRouter.testFn function. Any call to http://yourdomain.com#word1=word2 will call the MyRouter.testFn with the word after the parenthesis as a parameter. Of course, your word place setting could be a single character like in your question t=b.
Expanding your parameters
Say you want to pull multiple parameters, not just the one. The key to understanding how Backbone pulls your parameters is the capturing group (). A capturing group allows your to "save" the match defined within the parenthesis into variables local to the regex expression. Backbone uses these saved matches as the parameters it applies to the the route callback.
So if you want to capture two parameters in your route you'd use this regex:
^\w+?[=]([a-zA-Z0-9]*)[,]\w+?[=]([a-zA-Z0-9]*)
which simply says to expect a comma delimiter between the two parameter placeholders. It would match,
t=b,some=thing
More general route patterns
You can repeat the [,]\w+?[=]([a-zA-Z0-9]*) pattern as many times as you need. If you want to generalize the pattern, you cold use the non-capturing token (?: ... ) and do something like,
^\w+?[=]([a-zA-Z0-9]*)(?:[,]\w+?[=]([a-zA-Z0-9]*))?(?:[,]\w+?[=]([a-zA-Z0-9]*))?
The regex above will look for at least one match and will optionally take two more matches. By placing a ? token at the end of the (?: ... ) group, we say the pattern in the parenthesis may be found zero or one times (i.e. it may or may not be there). This allows you to set a route when you know you can expect up to 3 parameters, but sometimes you may want only one or two.
Is there a truly general route?
You may be asking yourself, why not simply use one greedy (?: ... ) group that will allow an unlimited number of matches. Something like,
^\w+?[=]([a-zA-Z0-9]*)(?:[,]\w+?[=]([a-zA-Z0-9]*))*
With this regex pattern you must supply one parameter, but you can take an unlimited number of subsequent matches. Unfortunately, while the regex will work fine, you won't get the desired result. (See, for example, this Question.)
That's a limitation of JavaScript. With repeating capturing-groups (i.e. the ([a-zA-Z0-9]*) capturing-group will repeat with every repetition of the (?: ... ) non-capturing-group) JavaScript only saves the last match. So if you pass a route like t=b,z=d,g=f,w=1ee, you'll only save 1ee. So, unfortunately you have to have an idea of what the maximum number of parameters your route should take, and manually code them into your regex pattern like we did above.

Related

jQuery parameters replace and upload between two strings in all URL's

WordPress' FacetWP plugin has a 'facetwp-loaded' jQuery event that allows for changes when facets are refreshed.
This is the 'facetwp-loaded' event's usage from FacetWP's documentation:
(function($) {
$(document).on('facetwp-loaded', function() {
// Changes go here
});
})(jQuery);
Facets produce URL's like:
http://website.com/hotels?fwp_location=worldwide
or
http://website.com/hotels/worldwide?fwp_location=europe
So I would like to make a global Regex redirection to substitute what is between
hotels
and
=
with
/
In the above examples, that would result in:
http://website.com/hotels/worldwide
or
http://website.com/hotels/europe
Can someone help me with this?
Thanks in advance
UPDATE
I've tried different Regex methods, but it seems to need jQuery parameter replace/update.
I don't have a way to test this using the Wordpress regex engine, so you'll have to check it, but it works in the R regex engine. Hopefully Wordpress supports perl style regex expressions.
Regex: Match: (?<=hotels).*?= and replace with /
In this case the piece of the string we want to remove is preceded by "hotels" and ends with an equal sign. So we want to match everything immediately after hotels, ending at the equal sign. To start matching immediately after "hotels" but not include it, we need to look backwards. So we use a look behind before the match. (?<=hotels) means look backwards from the current position in the string, and see if "hotels" precedes the current position. So when the engine gets to the "/" after hotels, it looks back and sees hotels (but it doesn't match, because it's a look behind). . matches any character, * means match zero or more (so zero or more of any character), and ? modifies the * telling the star to match zero or more characters, but only until the next character can be matched, in this case =.

Find all function signatures with more than 2 arguments in javascript

I need to find all function signatures accepting more than X arguments (say 2).
I tried something like function\s*\((\w*,){3,10} (which would catch all signature with 3-10 args, but it did not work. Variations on it are yielding unexpected results. I guess I'm just not that good at regex, but any help is appreciated.
update: I should point out that I am writing a sort of code inspection tool. Among the many things, I want to spot functions that accept more than 2 arguments (as I promote the usage of functions with few arguments, and 1 argument in case of constructors). So I cannot call arguments.length etc.
Just think "easy":
A method typically has (...): \(\)
A method with 3 parameters has 2 , inside the brackets: \(,{2,2}\)
each , NEEDS to be preceeded AND followed by strings: \((?:\w+,\w+){2,2}\)
no double matches occur, so does not work - let's make the leading string mandatory, the following optional, but finally it needs to stop with a string:
\((?:\w+,\w*){2,2}\w+\)
usually a method declaration starts with function name: function\s+\w+\s*\((?:\w*,\w*){2,2}\)
finally, there could be whitespaces arround the paremeters: function\s+\w+\s*\((?:\s*\w+\s*,\s*\w*\s*){2,2}\w+\s*\)
There you go. This should cover all "common" method declarations, except nameless lambda-expressions:
function\s+\w+\s*\((?:\s*\w+\s*,\s*\w*\s*){2,2}\w+\s*\)
Debuggex Demo
Matching two to two commas will find signatures with 3 parameters.
Matchint two to five commas will find signatures with 3 upto 6 parameters.
First of all, JavaScript is not a regular language, as a result, one cannot use a regex to fully grasp the language, and thus there is a possibility that you will either accept false positives, or false negatives.
A regex that probably comes close is:
function(?:\s+\w+)*\s*\(([^),]*)(\s*,\s*[^),]*){2,}\)
The regex works as follows:
function searches for the function keyword.
next there is an optional group \s+\w+ this group is used to identify with the name of the function: it is possible to define an anonymous function with no name, so the group must be optional.
Next \s*\( there is an arbitrary number of space and a bracket to open the parameter list;
Now between the brackets, we start looking for the parameters. To cover (most) cases, we will define a parameter as [^,)]* (a sequence of characters not containing a comma nor the closed bracket).
Now for the next parameters, we need to skip a comma, this is enforced by the \s*,\s* pattern (\s* is actually unnecessary). Next again a group for a parameter name and of course we need to skip at least two commas.
Finally, an (optional) closing bracket.
You'd want to use function\s*\w+\s*\(\s*(\w+,?){3,10} to match non-anonymous (named) functions, and remove the \w+\s* to get function\s*\(\s*(\w+,?){3,10} for anonymous functions.
These can be combined to get function\s*(?:\w+\s*)?\(\s*(\w+,?){3,10} (the ?: is the non-capturing group)

How to match two strings to one route express.js

I've got a single route function that I want to match two different paths to. The idea is to create profile pages for team members of a website. They'll be at www.domain.com/name. The issue is, some people have nicknames. So, I need www.domain.com/nickname to go to the same place as www.domain.com/name.
Here's what I've got so far:
website.get('/name|nickname', websiteRoutes.about);
The problem is things like /asdasdfdnickname and /namezzzzzzzz will match as well.
How do I match either the name or nickname only without any extra characters. I believe this is called an exclusive or?
So here are some working solutions
Passing in ['/name', '/nickname'] into the routing function.
And from John's answer below: /^\/?(name|nickname)\/?$/i
Try /^\/?(name|nickname)\/?$/i which will match exactly name/nickname only.
This regex means it can optionally start with a forward slash, it will match "name" or "nickname" case insensitively, then it will optionally allow another forward slash at the end.

Capturing optional part of URL with RegExp

While writing an API service for my site, I realized that String.split() won't do it much longer, and decided to try my luck with regular expressions. I have almost done it but I can't find the last bit. Here is what I want to do:
The URL represents a function call:
/api/SECTION/FUNCTION/[PARAMS]
This last part, including the slash, is optional. Some functions display a JSON reply without having to receive any arguments. Example: /api/sounds/getAllSoundpacks prints a list of available sound packs. Though, /api/sounds/getPack/8Bit prints the detailed information.
Here is the expression I have tried:
req.url.match(/\/(.*)\/(.*)\/?(.*)/);
What am I missing to make the last part optional - or capture it in whole?
This will capture everything after FUNCTION/ in your URL, independent of the appearance of any further / after FUNCTION/:
FUNCTION\/(.+)$
The RegExp will not match if there is no part after FUNCTION.
This regex should work by making last slash and part after optional:
/^\/[^/]*\/[^/]*(?:\/.*)?$/
This matches all of these strings:
/api/SECTION/FUNCTION/abc
/api/SECTION
/api/SECTION/
/api/SECTION/FUNCTION
Your pattern /(.*)/(.*)/?(.*) was almost correct, it's just a bit too short - it allows 2 or 3 slashes, but you want to accept anything with 3 or 4 slashes. And if you want to capture the last (optional) slash AND any text behind it as a whole, you simply need to create a group around that section and make it optional:
/.*/.*/.*(?:/.+)?
should do the trick.
Demo. (The pattern looks different because multiline mode is enabled, but it still works. It's also a little "better" because it won't match garbage like "///".)

express js: Conditional route parameters with RegEx

I need to match a route that has this form: /city-state-country
Where city can be in formats: san-francisco (multiword separated by '-') or newtown (single word).
And also some countries have state missing, so '-state' param in route should be optional.
How can I strictly match match my route pattern, meaning that it will take either 2 or 3 parameters separated by '-'?
I had something like this:
app.get(/([A-Za-z\-\']+)-([A-Za-z\']+)-([A-Za-z\']+)/, routes.index_location);
but, it didn't work.
Ultimately, cases like these should not work:
/c/san-jose-ca-us
/san-jose-ca-us-someweirdstuff
san-jose-ca-us-someweirdstuff can be parsed as san-jose-ca (city) - us (state) - someweirdstuff (country), so it's perfectly valid case
Unless you missed something, the task is impossible in general. We know that us isn't a state, but regexp doesn't.
You can try to limit an amount of dashes in the city to one, or enumerate all possible countries, or do something like that... Anyway, this has nothing to do with regular expressions, really.
Actually, there is a way. But, it would take a multi step process. In the first pass, replace all two letter states (since they are optional) with a different delimiter. In the second pass, replace all of the countries with a different delimiter so you can recognize cities. In the third pass, replace all city dashes with some other character and add back the states and countries with dash delimiters. In the final pass, replace your cities with a different delimiter with the delimiter you expect.
For instance:
replace /-(al|ca|az...)/ with ~$1 san-jose-ca-us = san-jose~ca-us
replace /-(.+)$/ with ~$1 san-jose~ca-us = san-jose~ca~us
replace /-/ with *$1 san-jose~ca~us = san*jose~ca~us
replace /~/ with - san*jose~ca~us = san*jose-ca-us
etc.
If you only want to keep your information on 1 level hierarchy you can try the underscore delimiter. So, your url be like: city_state_country

Categories