I want get my program parameters from rel attribute of element, first of all is it logical ?
and the rel attribute may contain this string rel="_p|b|w=300|h=200" or rel="_p|w=300"
, so I use split to split my string with | pattern :
var attr = $(this).attr('rel').split('|');
for _p and b there is no problem because I can check with indexOf but for w and h I should use regular expression because the w and h value will be change.
how can I use regular expression in indexOf ?
sorry for my bad English
EDIT:
if (attr.indexOf('b')) {
blank = true;
}
First of all, that isn't a very elegant way of retrieving data. Anyway, if you really want to do that in that way, then you can use regexes as follows:
var matches = $(this).attr('rel').match(/w=(\d+)/);
var w = (matches && matches[1]) || defaultValue;
Also, if there can be multiple elements that end in 'w', then you'd better change your regex to something like:
var matches = $(this).attr('rel').match(/(?:^|\|)w=(\d+)/);
I would have suggested the use of custom attributes as well, however these would not be w3-conform as you want them to.
A simple way would be to split the parameters and then loop through and check each index whether it is one of the attributes you are expecting:
var cust_params = $(this).attr('rel').split('|'); //or this.rel as GGG suggested in a comment?
for(var i=0;i<cust_params.length;i++) {
if('_p'==cust_params[i]) {
//...
}
//...
if(cust_params[i].match(/w=(\d+)/)) {
//you could even do this without a regular expression
}
}
I hope this doesn't violate some good practice that I'm unaware of because I always feel like there must be a more elegant way when I do this kind of thing :) As it is I get a kind of quick-and-dirty feel about this.
Sorry there is no way you can do it in one command with normal javascript, indexOf just doesn't support regular expression.
You can either loop through the array or use jquery supported command for array.
For example: once you have the array attr as you like, you can use jQuery.grep() http://api.jquery.com/jQuery.grep/
a_equal = jQuery.grep(attr, function(a, i){
return (a.match(/=/) and i > 0); // modify this as you like
});
to create an array a_equal with all the assignment argument.
disclaimer.. code not yet tested.
Like Paolo Bergantino I'd also suggest using data-attributes, or you could store the data in a JSON (again, in a data attribute) and parse that:
<a href="#" data-info='{"width": "300", "height": "200", "color": "#fff", "etc": "foo"}'>
var info = JSON.parse(a.getAttribute('data-info'));
Edit: replaced eval with Phrogz's suggestion.
(With eval: eval('(' + a.getAttribute('data-info') + ')'))
Related
I was wondering if it is necessary to check for the condition in this particular example.
The condition I'm talking about is if ( Id.indexOf("_") ).
It just checks to see if Id has an underscore and if so then set the variable to strip the underscore and replace with hyphen.
I know I can just use Id = Id.split("_").join("-"); without the if statement checking to see if the condition is true, but just wondering if in this case is it good practice to check for the condition first or not?
Which way would you do it? And explain why please.
Id = "My_ID";
var brand = "The Brand";
var b = brand.trim().toLowerCase();
var page = b.split(/\W+/g).join("-");
if ( Id.indexOf("_") ) {
Id = Id.split("_").join("-");
}
If there is no underscore your split() won't do anything, so no - there's no need for the if here. Go with something like that and you're fine:
Id = Id.split("_").join("-");
or
Id = Id.replace(/_/g, '-');
to avoid creating an array first.
This could answer your question:
console.log("mytext".split("_").join("-")); // mytext
console.log("my_text".split("_").join("-")); // my-text
furthermore condition in your code if (Id.indexOf("_")) does not work as you intended. You need to use if (Id.indexOf("_") > -1) or (~Id.indexOf("_"))
Say I have the following element:
<div class='selector' data-object='{"primary_key":123, "foreign_key":456}'></div>
If I run the following, I can see the object in the console.
console.log($('.selector').data('object'));
I can even access data like any other object.
console.log($('selector').data('object').primary_key); //returns 123
Is there a way to select this element based on data in this attribute? The following does not work.
$('.selector[data-object.foreign_key=456]');
I can loop over all instances of the selector
var foreign_key = 456;
$('.selector').each(function () {
if ($(this).data('object').foreign_key == foreign_key) {
// do something
}
});
but this seems inefficient. Is there a better way to do this? Is this loop actually slower than using a selector?
You can try the contains selector:
var key_var = 456;
$(".selector[data-object*='foreign_key:" + key_var + "']");
I think that you may gain a little speed here over the loop in your example because in your example jQuery is JSON parsing the value of the attribute. In this case it's most likely using the JS native string.indexOf(). The potential downside here would be that formatting will be very important. If you end up with an extra space character between the colon and the key value, the *= will break.
Another potential downside is that the above will also match the following:
<div class='selector' data-object="{primary_key:123, foreign_key:4562}"></div>
The key is clearly different but will still match the pattern. You can include the closing bracket } in the matching string:
$(".selector[data-object*='foreign_key:" + key_var + "}']");
But then again, formatting becomes a key issue. A hybrid approach could be taken:
var results = $(".selector[data-object*='" + foreign_key + "']").filter(function () {
return ($(this).data('object').foreign_key == foreign_key)
});
This will narrow the result to only elements that have the number sequence then make sure it is the exact value with the filter.
With a "contains" attribute selector.
$('selector[data-object*="foreign_key:456"]')
The question is simple, assume the following string:
var str = 'aaaaab\'s'
How do you extract the value of href. I would think something like
var arr = str.match(/(?:href=")(\w+)/g) ;
--> ["href="aaaa", "href="bb"]
Of course I want
["aaaa", "bb"]
Withoug the /g it get close, but it only matches "aaaa". Any suggestions how to fix this ?
Thanks!
DOM parsing with JS is so easy.
var str = 'aaaaab\'s',
help = document.createElement('div');
helper.innerHTML = str;
Array.prototype.forEach.call(help.querySelectorAll("a[href]"), function (elem) {
console.log(elem.getAttribute('href'));
});
http://jsfiddle.net/ExplosionPIlls/gtdFh/
Because Javascript doesn't have lookbehind, this may be what you want. Naturally there will be more elegant solutions:
input.match(/<[^href|/]*(href[\s]*=[\s]*")([^"]+)(?=">)/g).map(
function(x){return x.split('href')[1].replace(/[^"]+"(.*)/,'$1');
})
Additionally, you may be better off getting a HTML parsing plugin. And extracting the properties you need using that.
Cheers.
I have a javascript function that needs to retrieve certain nodes through xpath using document.evaluate, till now I am using something like
.//span[contains(#title, 'alerting')] | .//span[contains(#title, 'caution')]
But it turn in a very long string when values to match are more. I cannot use [#title = word], because I need to retrieve the elements whose atributes contains some string. I have tried things like
.//span[contains(#title, ('alerting'|'caution'))]
But it does not retrieve anything.
Can you give me an idea to shorten the first sintax?
Why not just create a function that creates the string and build the expression programmatically, and not worry about it? Roughly:
function spanContains(s) {
return ".//span[contains(#title, '" + s + "')]";
}
var contains = [spanContains('word1'), spanContains('word2')].join("|");
You could also try using matches instead of contains, although I'm not sure what the JavaScript syntax for that would be, or if it's supported.
XPath should be this way:-
.//span[contains(#title, 'alerting') or contains(#title, 'caution')]
.//span[contains(#title, ('alerting'|'caution'))]
This is invalid XPath -- the union operator | can only have arguments that are node-sets -- not strings.
Use:
.//span[#title
[contains(.,'alerting')
or
contains(.,'caution')
]
]
Instead of using document.evaluate(), you could use jquery in which case you could do:
$('span').filter(function() {
var title = $(this).attr('title');
return title != undefined && title.search(/(alerting|caution)/) != -1;
});
I need to rewrite a querysting using javascript.
First I check to see if the variable is present, if it is I want to replace it with a new search term. If it is not present then I just add the new variable
I'm able to get it to work with simple terms like hat, ufc hat
whitespaces are %20, so ufc hat is really ufc%20hat
I run into problem with terms like make-up, hat -baseball, coffee & tea, etc..
What is the proper regex for this?
Below is my code, which doesn't work.
var url = String(document.location).split('?');
querystring = url[1];
if(querystring.match(/gbn_keywords=/)!=null)
querystring=querystring.replace(/gbn_keywords=[a-zA-Z0-9%20.]+/,"gbn_keywords="+term);
else
querystring=querystring+"&gbn_keywords="+term;
No Regex needed. To get the query arguments, take everything after ?. Then, split the string by & to return each argument. Split again by = to get the arg name (right of =) and the value (left of =). Iterate through each argument, a rebuild the URL with each argument, excluding the one you don't want. You shouldn't run into problems here because ?, &, and - must be escaped if they are to be used in arguments. You also said you want to add the argument if it doesn't exist, so just set a variable to true, while you are iterating through each argument, if you find the argument. If you didn't append it to the end of the query string that you rebuilt.
location objects already have perfectly good properties like pathname, hostname etc. that give you the separate parts of a URL. Use the .search property instead of trying to hack the URL as a string (? may not only appear in that one place).
It's then a case of splitting on the & character (and maybe ; too if you want to be nice, as per HTML4 B2.2) and checking each parameter against the one you're looking for. For the general case this requires proper URL-decoding, as g%62n_keywords=... is a valid way of spelling the same parameter. On the way out naturally you will need to encode again, to stop & going on to the next parameter (as well as to include other invalid characters).
Here's a couple of utility functions you can use to cope with query string manipulation more easily. They convert between the ?... string as seen in location.search or link.search and a lookup Object mapping parameter names to arrays of values (since form-url-encoded queries can have multiple instances of the same parameter).
function queryToLookup(query) {
var lookup= {};
var params= query.slice(1).split(/[&;]/);
for (var i= 0; i<params.length; i++) {
var ix= params[i].indexOf('=');
if (ix!==-1) {
var name= decodeURIComponent(params[i].slice(0, ix));
var value= decodeURIComponent(params[i].slice(ix+1));
if (!(name in lookup))
lookup[name]= [];
lookup[name].push(value);
}
}
return lookup;
}
function lookupToQuery(lookup) {
var params= [];
for (var name in lookup)
for (var i= 0; i<lookup[name].length; i++)
params.push(encodeURIComponent(name)+'='+encodeURIComponent(lookup[name][i]));
return params.length===0? '' : '?'+params.join('&');
}
This makes the usage as simple as:
var lookup= queryToLookup(location.search);
lookup['gbn_keywords']= ['coffee & tea'];
var query= lookupToQuery(lookup);
& character is used to seperate key and value pairs in the querystring. So that you can match all the characters except for & by re-writing your code as follows:
querystring=querystring.replace(/gbn_keywords=[^&]+/,"gbn_keywords="+term);
[^&]+ matches one or more characters up to & or end of string. But if there may situations where the querystring data may look like ...?gbn_keywords= (no value) then a slight modification is needed to the above line:
querystring=querystring.replace(/gbn_keywords=[^&]*/,"gbn_keywords="+term);
Just change + to * so that the regex will match 0 or more characters. I think this is better.
Why don't you run a split on url[1] and than replace the value of the gbn_keywords in that new array?
And if you use a JavaScript Framework, there might be a handy function that does all that. In Prototype there is the function toQueryParams().