I've a JS code that take the UTM and other url parameter so when the user navigate between pages I don't lose their track. The code is working great when the href is a page but not when it's related to an id element
I tried to exclude it in the if statement or to add the parameters after the id.
function getRefQueryParam(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};
var utmParamQueryString = '',
utmParamQueryStringTrimmed = '',
utm_source = '',
utm_medium = '',
utm_content = '',
utm_campaign = '',
utm_term = '';
(function() {
utm_source = getRefQueryParam("utm_source");
utm_medium = getRefQueryParam("utm_medium");
utm_content = getRefQueryParam("utm_content");
utm_campaign = getRefQueryParam("utm_campaign");
utm_term = getRefQueryParam("utm_term");
gclid = getRefQueryParam("gclid");
fbclid = getRefQueryParam("fbclid");
if (utm_source) {
utmParamQueryString += '&utm_source=' + utm_source;
}
if (utm_medium) {
utmParamQueryString += '&utm_medium=' + utm_medium;
}
if (utm_content) {
utmParamQueryString += '&utm_content=' + utm_content;
}
if (utm_campaign) {
utmParamQueryString += '&utm_campaign=' + utm_campaign;
}
if (utm_term) {
utmParamQueryString += '&utm_term=' + utm_term;
}
if (gclid) {
utmParamQueryString += '&gclid=' + gclid;
}
if (fbclid) {
utmParamQueryString += '&fbclid=' + fbclid;
}
if(utmParamQueryString.length > 0) {
utmParamQueryString = utmParamQueryString.substring(1);
utmParamQueryStringTrimmed = utmParamQueryString;
utmParamQueryString = utmParamQueryString;
}
if (!utmParamQueryString) return;
var navLinks = document.querySelectorAll('a');
navLinks.forEach(function(item) {
if (item.href.indexOf('/') === 0 || item.href.indexOf(location.host) !== -1 ) {
if (item.href.indexOf('?') === -1) {
item.href += '?';
} else {
item.href += '&';
}
item.href += utmParamQueryString;
}
});
})();
So it's searching every anchor tag and after the page uri the code insert the parameters that the current URL have. The issue is that it inserts code even what it's an id call and the call doesn't work anymore because the parameters isn't insert after but in between like so:
utm_source=google&utm_medium=cpc&utm_campaign=test_cpc&utm_term=test #top &utm_source=google&utm_medium=cpc&utm_campaign=test_cpc&utm_term=test
You can try use attribute selector on your querySelectorAll like this:
document.querySelectorAll('a:not([href^="#"])')
This will pick all a tags that the href attribute does not start with #.
You can, of course, try and modify it based on your needs.
I am constructing a query string in Javascript based on whether a checkbox is checked or not.
Some of the options in the checkboxes are
"Annual"
"Grass"
"Shrub (Evergreen)"
"Shrub (Deciduous)"
I found a function online that updates the url parameter:
function updateUrlParameter(uri, key, value) {
value = value.replace(/\s/g, "%20");
var i = uri.indexOf('#');
var hash = i === -1 ? '' : uri.substr(i);
uri = i === -1 ? uri : uri.substr(0, i);
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (!value) {
// remove key-value pair if value is empty
uri = uri.replace(new RegExp("([&]?)" + key + "=.*?(&|$)", "i"), '');
if (uri.slice(-1) === '?') {
uri = uri.slice(0, -1);
}
} else {
console.log("value is " + value)
uri = uri + separator + key + "=" + value;
}
return uri + hash;
}
Using the above function, if I check the checkboxes for the above four starting from top down, my query string becomes
?plantType=Annual&plantType=Grass&plantType=Shrub%20(Evergreen)&plantType=Shrub%20(Deciduous
Why is the function ignoring the last ')' in the string? Is there a work around this? I would like to keep the parenthesis in the query string because this will make querying the database easier.
I created a function to iterate through input checkboxes. If they are checked, then use the updateUrlParameter function to update the URI.
function getQueryString() {
var inputsContainerChildren = $('#floatingDivForFilter').children();
var input = document.createElement('input')
var uri = '';
for (var i = 0; i < inputsContainerChildren.length; i++) {
var currChild = inputsContainerChildren[i].firstElementChild;
if (currChild) {
if (currChild.tagName === 'INPUT') {
if (currChild.checked) {
var id = currChild.id;
console.log(uri)
uri = updateUrlParameter(uri, currChild.name, currChild.value);
}
}
}
}
console.log(uri);
}
The photo below shows a snapshot of the URL produced. I can't figure out why the last ')' is chopped off.
url photo
The issue you are seeing is just the Chrome developer tools trying to be too clever.
When logging the url to the console, Chrome will not recognize the full url as a link but exclude the closing ")". They probably do that because it will be very common that people write an url in braces and it is not expected that the closing brace is part of the url.
Since this is only an issue of the developer tools, you can ignore the issue. It will not affect the runtime behaviour of your code.
The issue will be solved when you correctly escape special characters in the parameters (as you should do anyway):
function updateUrlParameter(uri, key, value) {
// removed because escape will do that
// value = value.replace(/\s/g, "%20");
var i = uri.indexOf('#');
var hash = i === -1 ? '' : uri.substr(i);
uri = i === -1 ? uri : uri.substr(0, i);
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (!value) {
// remove key-value pair if value is empty
uri = uri.replace(new RegExp("([&]?)" + key + "=.*?(&|$)", "i"), '');
if (uri.slice(-1) === '?') {
uri = uri.slice(0, -1);
}
} else {
console.log("value is " + value)
// Use escape on key and value
uri = uri + separator + escape(key) + "=" + escape(value);
}
return uri + hash;
}
let s = "http://chrome.is.too.clever/";
s = updateUrlParameter(s, "plantType", "Annual");
s = updateUrlParameter(s, "plantType", "Grass");
s = updateUrlParameter(s, "plantType", "Shrub (Evergreen)");
s = updateUrlParameter(s, "plantType", "Shrub (Deciduous)");
console.log(s);
Fiddle
Instead of using a regular expression, just convert the params to an object, modify said object, and convert it back into params.
var url = 'https://x.y?plantType=Annual&plantType=Grass&plantType=Shrub%20(Evergreen)&plantType=Shrub%20(Deciduous)';
function updateUrlParameter(uri, key, value) {
let url = new URL(uri), object = deserializeQuery(url.search); // params to obj
object[key] = value; // modify obj
return url.origin + '?' + serializeQuery(object); // obj to url + params
}
console.log(updateUrlParameter(url, 'plantType', [ 'Pine', 'Palm', 'Rose (Red)' ]));
/** ======= Serialization / Deserialization functions below ======== */
// https://stackoverflow.com/a/47517503/1762224
function deserializeQuery(queryString, queryKey) {
let query = {}, pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('='), key = decodeURIComponent(pair[0]), value = decodeURIComponent(pair[1] || '');
value = (value.indexOf(',') === -1 ? value : value.split(','));
query[key] = query[key] ? (query[key].constructor === Array ? query[key].concat(value) : [query[key], value]) : value;
}
return typeof queryKey === 'undefined' ? query : query[queryKey];
}
// https://stackoverflow.com/a/53528203/1762224
function serializeQuery(params, keys = [], isArray = false) {
const p = Object.keys(params).map(key => {
let val = params[key];
if ("[object Object]" === Object.prototype.toString.call(val) || Array.isArray(val)) {
keys.push(Array.isArray(params) ? "" : key);
return serializeQuery(val, keys, Array.isArray(val));
} else {
let tKey = keys.length > 0 ? ((isArray ? keys : [...keys, key]).reduce((str, k) => "" === str ? k : `${str}[${k}]`, "")) : key;
if (isArray) {
return encodeURIComponent(tKey) + '=' + encodeURIComponent(val);
}
}
}).join('&');
keys.pop();
return p;
}
.as-console-wrapper {
top: 0;
max-height: 100% !important;
}
.as-console-row {
white-space: pre-wrap;
word-break: break-all;
}
I have the following code which works well to convert data entered into the "Firstname" field in our data enrollment software application to uppercase and return the converted value back to the application.
However, it doesn't handle names with "-", "'" or spaces in them, for example Anne-Marie, Jean Jacques, O’Brian. Could someone please help me in adding a few lines of code to handle these name types as well as preserving my original code which works for standard names without these characters in? Here is my code.
var tc_event = changeValue();
function changeValue() {
// Parse the JSON string for script information.
var tcInfo = JSON.parse(TC_Info);
/* FROM ENGINEERING: The “TC_Info” variable contains the user id and IP address of the user running the script.
* We have at least one customer that wanted that information */
var userId = tcInfo.userId;
var ipAddress = tcInfo.ipAddress;
// Parse the JSON string for fields and properties.
var tcData = JSON.parse(TC_Event);
// The following several lines of code loops over the workflow fields passed in to the script and saves references to the fields named “Lastname” and “LastnameUppercase”
var Lastname, LastnameUppercase, Firstname, Firstname1stUppercase;
// Iterate through parsed JSON.
for (var index in tcData) {
// Fetch each field i.e each key/value pair.
var field = tcData[index];
// Find the fields to process.
if (field.name === 'Lastname') {
Lastname = field;
} else if (field.name === 'LastnameUppercase') {
LastnameUppercase = field;
} else if (field.name === 'Firstname') {
Firstname = field;
} else if (field.name === 'Firstname1stUppercase') {
Firstname1stUppercase = field;
} else if (field.name === 'PersNr') {
PersNr = field;
} else if (field.name === 'TikNr') {
TikNr = field;
}
}
// Were the fields found? If so, proceed.
if (Lastname && LastnameUppercase && Firstname && Firstname1stUppercase && PersNr && TikNr) {
// This line of code states the LastnameUppercase field value will be the Lastname field value in uppercase
LastnameUppercase.value = Lastname.value.toUpperCase();
Firstname1stUppercase.value = Firstname.value.charAt(0).toUpperCase() + Firstname.value.slice(1);
var strLtr = PersNr.value.substring(0, 2);
var strNum = PersNr.value.substring(2, 6);
if (strLtr === '00') {
strLtr = 'A';
} else if (strLtr === '01') {
strLtr = 'M';
} else if (strLtr === '31') {
strLtr = 'B';
} else if (strLtr === '71') {
strLtr = 'F';
}
TikNr.value = strLtr + strNum;
}
// Return the updated fields and properties.
return JSON.stringify(tcData);
}
This will capitalize both the firstName that do not contain symbols and the ones that do:
function capitalize(name) {
let capitalizedName = '';
const nameSplit = name.split(/\W/g);
const symbols = name.match(/\W/g);
for(let i = 0; i< nameSplit.length; i++) {
capitalizedName += nameSplit[i][0].toUpperCase() +
nameSplit[i].slice(1)
if(i < nameSplit.length -1) capitalizedName += symbols[i];
}
return capitalizedName
}
I have used this function successfully:
function capitalizeName(str) {
var result = str.replace(/\w\S*/g, function(txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
return result.replace(/\s\s+/g, ' ');
}
calling the function:
capitalName = capitalizeName(lowerCaseName)
Looks like you should change
Firstname1stUppercase.value = Firstname.value.charAt(0).toUpperCase() + Firstname.value.slice(1);
to
var delimiter = ''; //char value
if(Firstname.value.indexOf(' ') != -1){ //name has a space
delimiter = ' ';
}else if(Firstname.value.indexOf('-') != -1){ //name has -
delimiter = '-';
}else if(Firstname.value.indexOf('\'') != -1){ //name has a '
delimiter = '\'';
}
Firstname1stUppercase.value = Firstname.split(delimeter).map(function(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
}).join(delimeter);
The last line is what you were doing but written for any separating character be it a space, apostrophe, or hyphen.
You could split by non alphabetic letters, like this:
text.split(/[^A-Za-z]/);
inspired from here: Split string by non-alphabetic characters
Now, let's implement the function you need:
function myUpperCase(input) {
var parts = input.split(/[^A-Za-z]/);
var output = parts[0];
for (var i = 1; i < parts.length; i++) {
if (parts[i].length) parts[i] = parts[i][0].toUpperCase() + parts[i].substring(1);
output += input[output.length] + parts[i];
}
return output;
}
I have following java script code:
var product = getQueryVariable("product");
$('a.link').each(function()
{
$(this).attr("href", $(this).attr("href") + "&product=" + getQueryVariable("product"));
});
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var variables = query.split("&");
for (var iCount = 0; iCount < variables.length; iCount++)
{
var pair = variables[iCount].split("=");
if (pair[0] == variable)
return pair[1];
}
}
If url is: http://www.xxxx.com/index.htm?product=abc, It sets a link to an anchor tag
<a class="link" href="http://www.aaaa.com/index.htm">Click here</a>
as
<a class="link" href="http://www.aaaa.com/index.htm?product=abc">Click here</a>
which is what I want, and it does it well.
But if anchor tag already has product variable in its href like
<a class="link" href="http://www.aaaa.com/index.htm?product=xyz">Click here</a>
then I get
<a class="link" href="http://www.aaaa.com/index.htm?product=xyz&product=abc">Click here</a>
while I was expecting that if product variable is present in href of anchor tag, it will replace existing product variable. And if there is no product variable in href tag, it will append it.
The code appends well, but does not replace existing product variable in href of anchor tag.
So, the question is how do I get 'product' param from all a tags that have class 'link'? so that I can replace it in my code if found. And can I fetch it in $('a.link').each(function() ?
How can I do it?
Try this,
Array.prototype.contains = function(x){
return this.indexOf( x ) > -1 ? true : false;
}
var getUrlVars = function(url){
var vars = [], hash;
var hashes = url.slice(url.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++){
hash = hashes[i].split('=');
vars.push(decodeURIComponent(hash[0]));
vars[decodeURIComponent(hash[0])] = decodeURIComponent(hash[1]);
}
if(vars[0] == url){
vars =[];
}
return vars;
}
var getUrl = function(url){
var urlParams = getUrlVars(window.location.href),
linkParams = getUrlVars(url),
altered = false;
for(i = 0; i < linkParams.length; i++){
var t = linkParams[i];
if(urlParams.contains(t)){
linkParams[t] = urlParams[t];
altered = true;
}
}
return altered ? url.split("?")[0] + "?" + linkParams.map(function(y){return y + "=" + linkParams[y]}).join("&") : url;
}
$("a.link").each(function (i,link) {
link.attr("href",getUrl(link.attr("href")));
})
Try this
$('a.link').each(function()
{
$(this).attr("href", $(this).attr("href").split("product=")[0] + "product=" + getQueryVariable("product"));
});
This works with links already containing product value
You can do something like this:
function changeLinkQueries(link,parameter,replacedVal) {
// This function is anonymous, is executed immediately and
// the return value is assigned to QueryString!
var query_string = {};
var query = link.split('?')[1];
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
// If first entry with this name
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = decodeURIComponent(pair[1]);
// If second entry with this name
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]],decodeURIComponent(pair[1]) ];
query_string[pair[0]] = arr;
// If third or later entry with this name
} else {
query_string[pair[0]].push(decodeURIComponent(pair[1]));
}
}
var queries = query_string,
linkArr = [];
queries[parameter] = replacedVal;
for(query in queries){
linkArr.push(query + '=' + queries[query]);
}
return link.split('?')[0] + '?' + linkArr.join('&');
};
The function usage is : changeLinkQueries(link,parameter,replacedVal):
link : is the link that you want to modify
parameter: the parameter you want to change
replacedVal: the value that you want to replace with it
Example: changeLinkQueries('http://www.aaaa.com/index.htm?product=xyz','product','test') returns ==> http://www.aaaa.com/index.htm?product=test
Add this function to your code and update your code to :
var product = getQueryVariable("product");
$('a.link').each(function(){
$(this).attr("href", changeLinkQueries($(this).attr("href"),'product',getQueryVariable('product')));
});
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var variables = query.split("&");
for (var iCount = 0; iCount < variables.length; iCount++)
{
var pair = variables[iCount].split("=");
if (pair[0] == variable)
return pair[1];
}
}
This code worked:
$('a.link').each(function()
{
var anchor_url = $(this).attr("href");
var product_val = '';
if (-1 == anchor_url.indexOf('&product='))
{
if (-1 == anchor_url.indexOf('?product='))
product_val = anchor_url.substr(anchor_url.indexOf('?product=')+'?product='.length);
}
else
product_val = anchor_url.substr(anchor_url.indexOf('&product=')+'&product='.length);
if (product_val.indexOf('&') != -1) product_val = product_val.substr(0, product_val.indexOf('&'))
if (product_val == '') new_link = anchor_url+'&product='+getQueryVariable("product");
else new_link = anchor_url.split(product_val).join(getQueryVariable("product"));
$(this).attr("href", new_link);
});
i hope this will help,
$(this).attr("href", getQueryVariable($(this).attr("href"), "product"));
function getQueryVariable(hrefLink, variable)
{
if(hrefLink.contains("product")){
return hrefLink;
}else{
//write your code here and return full url
}
}
I've been banging my head over this.
Using jquery or javascript, how can I toggle variables & values and then rebuild the query string? For example, my starting URL is:
http://example.com?color=red&size=small,medium,large&shape=round
Then, if the user clicks a button labeled "red", I want to end up with:
http://example.com?size=small,medium,large&shape=round //color is removed
Then, if the user clicks "red" again, I want to end up with:
http://example.com?size=small,medium,large&shape=round&color=red //color is added back
Then, if the user clicks a button labeled "medium", I want to end up with:
http://example.com?size=small,large&shape=round&color=red //medium is removed from list
Then, if the user clicks the labeled "medium" again, I want to end up with:
http://example.com?size=small,large,medium&shape=round&color=red //medium added back
It doesn't really matter what order the variable are in; I've just been tacking them to the end.
function toggle(url, key, val) {
var out = [],
upd = '',
rm = "([&?])" + key + "=([^&]*?,)?" + val + "(,.*?)?(&.*?)?$",
ad = key + "=",
rmrplr = function(url, p1, p2, p3, p4) {
if (p2) {
if (p3) out.push(p1, key, '=', p2, p3.substr(1));
else out.push(p1, key, '=', p2.substr(0, p2.length - 1));
} else {
if (p3) out.push(p1, key, '=', p3.substr(1));
else out.push(p1);
}
if (p4) out.push(p4);
return out.join('').replace(/([&?])&/, '$1').replace(/[&?]$/, ''); //<!2
},
adrplr = function(s) {
return s + val + ',';
};
if ((upd = url.replace(new RegExp(rm), rmrplr)) != url) return upd;
if ((upd = url.replace(new RegExp(ad), adrplr)) != url) return upd;
return url + (/\?.+/.test(url) ? '&' : '?') + key + '=' + val; //<!1
}
params self described enough, hope this help.
!1: changed from ...? '&' : '' to ... ? '&' : '?'
!2: changed from .replace('?&','?')... to .replace(/([&?]&)/,'$1')...
http://jsfiddle.net/ycw7788/Abxj8/
I have written a function, which efficiently results in the expected behaviour, without use of any libraries or frameworks. A dynamic demo can be found at this fiddle: http://jsfiddle.net/w8D2G/1/
Documentation
Definitions:
The shown example values will be used at the Usage section, below
- Haystack - The string to search in (default = query string. e.g: ?size=small,medium)
- Needle - The key to search for. Example: size
- Value - The value to replace/add. Example: medium.
Usage (Example: input > output):
qs_replace(needle, value)
If value exists, remove: ?size=small,medium > ?size=small
If value not exists, add: ?size=small > size=small,medium
qs_replace(needle, options) Object options. Recognised options:
findString. Returns true if the value exists, false otherwise.
add, remove or toggleString. Add/remove the given value to/from needle. If remove is used, and the value was the only value, needle is also removed. A value won't be added if it already exists.
ignorecaseIgnore case while looking for the search terms (needle, add, remove or find).
separatorSpecify a separator to separate values of needle. Default to comma (,).
Note : A different value for String haystack can also be defined, by adding it as a first argument: qs_replace(haystack, needle, value) or qs_replace(haystack, needle, options)
Code (examples at bottom). Fiddle: http://jsfiddle.net/w8D2G/1/:
function qs_replace(haystack, needle, options) {
if(!haystack || !needle) return ""; // Without a haystack or needle.. Bye
else if(typeof needle == "object") {
options = needle;
needle = haystack;
haystack = location.search;
} else if(typeof options == "undefined") {
options = needle;
needle = haystack;
haystack = location.search;
}
if(typeof options == "string" && options != "") {
options = {remove: options};
var toggle = true;
} else if(typeof options != "object" || options === null) {
return haystack;
} else {
var toggle = !!options.toggle;
if (toggle) {
options.remove = options.toggle;
options.toggle = void 0;
}
}
var find = options.find,
add = options.add,
remove = options.remove || options.del, //declare remove
sep = options.sep || options.separator || ",", //Commas, by default
flags = (options.ignorecase ? "i" :"");
needle = encodeURIComponent(needle); //URL-encoding
var pattern = regexp_special_chars(needle);
pattern = "([?&])(" + pattern + ")(=|&|$)([^&]*)(&|$)";
pattern = new RegExp(pattern, flags);
var subquery_match = haystack.match(pattern);
var before = /\?/.test(haystack) ? "&" : "?"; //Use ? if not existent, otherwise &
var re_sep = regexp_special_chars(sep);
if (!add || find) { //add is not defined, or find is used
var original_remove = remove;
if (subquery_match) {
remove = encodeURIComponent(remove);
remove = regexp_special_chars(remove);
remove = "(^|" + re_sep + ")(" + remove + ")(" + re_sep + "|$)";
remove = new RegExp(remove, flags);
var fail = subquery_match[4].match(remove);
} else {
var fail = false;
}
if (!add && !fail && toggle) add = original_remove;
}
if(find) return !!subquery_match || fail;
if (add) { //add is a string, defined previously
add = encodeURIComponent(add);
if(subquery_match) {
var re_add = regexp_special_chars(add);
re_add = "(^|" + re_sep + ")(" + re_add + ")(?=" + re_sep + "|$)";
re_add = new RegExp(re_add, flags);
if (subquery_match && re_add.test(subquery_match[4])) {
return haystack;
}
if (subquery_match[3] != "=") {
subquery_match = "$1$2=" + add + "$4$5";
} else {
subquery_match = "$1$2=$4" + sep + add + "$5";
}
return haystack.replace(pattern, subquery_match);
} else {
return haystack + before + needle + "=" + add;
}
} else if(subquery_match){ // Remove part. We can only remove if a needle exist
if(subquery_match[3] != "="){
return haystack;
} else {
return haystack.replace(pattern, function(match, prefix, key, separator, value, trailing_sep){
// The whole match, example: &foo=bar,doo
// will be replaced by the return value of this function
var newValue = value.replace(remove, function(m, pre, bye, post){
return pre == sep && post == sep ? sep : pre == "?" ? "?" : "";
});
if(newValue) { //If the value has any content
return prefix + key + separator + newValue + trailing_sep;
} else {
return prefix == "?" ? "?" : trailing_sep; //No value, also remove needle
}
}); //End of haystack.replace
} //End of else if
} else {
return haystack;
}
// Convert string to RegExp-safe string
function regexp_special_chars(s){
return s.replace(/([[^$.|?*+(){}\\])/g, '\\$1');
}
}
Examples (Fiddle: http://jsfiddle.net/w8D2G/1/):
qs_replace('color', 'red'); //Toggle color=red
qs_replace('size', {add: 'medium'}); //Add `medium` if not exist to size
var starting_url = 'http://example.com?color=red&size=small,medium,large&shape=round'
starting_url = qs_replace(starting_url, 'color', 'red'); //Toggle red, thus remove
starting_url = qs_replace(starting_url, 'color', 'red'); //Toggle red, so add it
alert(starting_url);
This is the solution for your task: http://jsfiddle.net/mikhailov/QpjZ3/12/
var url = 'http://example.com?size=small,medium,large&shape=round';
var params = $.deparam.querystring(url);
var paramsResult = {};
var click1 = { size: 'small' };
var click2 = { size: 'xlarge' };
var click3 = { shape: 'round' };
var click4 = { shape: 'square' };
var clickNow = click4;
for (i in params) {
var clickKey = _.keys(clickNow)[0];
var clickVal = _.values(clickNow)[0];
if (i == clickKey) {
var ar = params[i].split(',');
if (_.include(ar, clickVal)) {
var newAr = _.difference(ar, [clickVal]);
} else {
var newAr = ar;
newAr.push(clickVal);
}
paramsResult[i] = newAr.join(',');
} else {
paramsResult[i] = params[i];
}
}
alert($.param(paramsResult)) // results see below
Init params string
{ size="small, medium,large", shape="round"} // size=small,medium,large&shape=round
Results
{ size="small"} => { size="medium,large", shape="round"} //size=medium%2Clarge&shape=round
{ size="xlarge"} => { size="small,medium,large,xlarge", shape="round"} // size=small%2Cmedium%2Clarge%2Cxlarge&shape=round
{ shape="round"} => { size="small,medium,large", shape=""} //size=small%2Cmedium%2Clarge&shape=
{ shape="square"} => { size="small,medium,large", shape="round,square"} //size=small%2Cmedium%2Clarge&shape=round%2Csquare
productOptions is the only thing you need to modify here to list all the available options and their default state. You only need to use the public API function toggleOption() to toggle an option.
(function(){
//Just keep an object with all the options with flags if they are enabled or disabled:
var productOptions = {
color: {
"red": true,
"blue": true,
"green": false
},
size: {
"small": true,
"medium": true,
"large": true
},
shape: {
"round": true
}
};
//After this constructing query becomes pretty simple even without framework functions:
function constructQuery(){
var key, opts, qs = [], enc = encodeURIComponent, opt,
optAr, i;
for( key in productOptions ) {
opts = productOptions[key];
optAr = [];
for( i in opts ) {
if( opts[i] ) {
optAr.push( i );
}
}
if( !optAr.length ) {
continue;
}
qs.push( enc( key ) + "=" + enc( optAr.join( "," ) ) );
}
return "?"+qs.join( "&" );
};
//To toggle a value and construct the new query, pass what you want to toggle to this function:
function toggleOption( optionType, option ) {
if( optionType in productOptions && option in productOptions[optionType] ) {
productOptions[optionType][option] = !productOptions[optionType][option];
}
return constructQuery();
}
window.toggleOption = toggleOption;
})()
Example use:
// "%2C" = url encoded version of ","
toggleOption(); //Default query returned:
"?color=red%2Cblue&size=small%2Cmedium%2Clarge&shape=round"
toggleOption( "color", "red" ); //Red color removed:
"?color=blue&size=small%2Cmedium%2Clarge&shape=round"
toggleOption( "color", "blue" ); //Blue color removed, no color options so color doesn't show up at all:
"?size=small%2Cmedium%2Clarge&shape=round"
toggleOption( "color", "blue" ); //Blue color enabled again:
"?color=blue&size=small%2Cmedium%2Clarge&shape=round"
toggleOption( "shape", "round" ); //The only shape option removed
"?color=blue&size=small%2Cmedium%2Clarge"
I have tried this and this may give the desire result
<script>
var url='http://example.com?color=red&size=small,medium,large&shape=round';
var mySplitResult = url.split("?");
var domain=mySplitResult[0];
var qstring=mySplitResult[1];
var proparr=new Array();
var valarr=new Array();
var mySplitArr = qstring.split("&");
for (i=0;i<mySplitArr.length;i++){
var temp = mySplitArr[i].split("=");
proparr[i]=temp[0];
valarr[i]=temp[1].split(",");
}
function toggle(property,value)
{
var index;
var yes=0;
for (i=0;i<proparr.length;i++){
if(proparr[i]==property)
index=i;
}
if(index==undefined){
proparr[i]=property;
index=i;
valarr[index]=new Array();
}
for (i=0;i<valarr[index].length;i++){
if(valarr[index][i]==value){
valarr[index].splice(i,1);
yes=1;
}
}
if(!yes)
{
valarr[index][i]=value;
}
var furl=domain +'?';
var test=new Array();
for(i=0;i<proparr.length;i++)
{
if(valarr[i].length)
{
test[i]=valarr[i].join(",");
furl +=proparr[i]+"="+test[i]+"&";
}
}
furl=furl.substr(0,furl.length-1)
alert(furl);
}
</script>
<div>
<input id="color" type="button" value="Toggle Red" onclick="toggle('color','red')"/>
<input id="shape" type="button" value="Toggle shape" onclick="toggle('shape','round')"/>
<input id="size" type="button" value="Toggle Small" onclick="toggle('size','small')"/>
<input id="size" type="button" value="Toggle large" onclick="toggle('size','large')"/>
<input id="size" type="button" value="Toggle medium" onclick="toggle('size','medium')"/>
<input id="size" type="button" value="Toggle new" onclick="toggle('new','yes')"/>
</div>