Переключить переменные строки запроса

Я ударился головой об этом.

Используя jquery или javascript, как я могу переключать переменные и значения, а затем перестраивать строку запроса? Например, мой стартовый URL:

http://example.com?color=red&size=small,medium,large&shape=round

Затем, если пользователь нажимает кнопку с надписью "red", я хочу в итоге:

http://example.com?size=small,medium,large&shape=round //color is removed

Затем, если пользователь снова нажмет "красный", я хочу в итоге:

http://example.com?size=small,medium,large&shape=round&color=red //color is added back

Затем, если пользователь нажимает кнопку с надписью "medium", я хочу в итоге:

http://example.com?size=small,large&shape=round&color=red //medium is removed from list

Затем, если пользователь снова нажмет метку "medium", я хочу в итоге:

http://example.com?size=small,large,medium&shape=round&color=red //medium added back

Не имеет значения, в каком порядке находится переменная; Я только что их довел до конца.

Ответ 1

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
}

параметры достаточно описаны, надеюсь эта помощь.

! 1: изменено с ...? '&' : '' на ... ? '&' : '?'

! 2: изменено с .replace('?&','?')... на .replace(/([&?]&)/,'$1')...

http://jsfiddle.net/ycw7788/Abxj8/

Ответ 2

Я написал функцию, которая эффективно приводит к ожидаемому поведению без использования каких-либо библиотек или фреймворков. динамическая демонстрация можно найти в этой скрипте: http://jsfiddle.net/w8D2G/1/

Документация

Определения:
Показанные примерные значения будут использоваться в разделе Usage, ниже
  - Haystack - строка для поиска (по умолчанию = строка запроса, например: ?size=small,medium)
  - Игла - ключ для поиска. Пример: size
  - Значение - значение для замены/добавления. Пример: medium.

Использование (пример: input > output):

  • qs_replace(needle, value)
    Если значение существует, удалите: ?size=small,medium > ?size=small
    Если значение не существует, добавьте: ?size=small > size=small,medium
  • qs_replace(needle, options)   Параметры объекта. Признанные варианты:
    • find
      Строка. Возвращает true, если это значение существует, false в противном случае.
    • add, remove или toggle
      Строка. Добавьте/удалите заданное значение в/из needle. Если используется remove, и значение было единственным значением, также удаляется needle. Значение не будет добавлено, если оно уже существует.
    • ignorecase
      Игнорировать регистр при поиске поисковых терминов (needle, add, remove или find).
    • separator
      Укажите разделитель для разделения значений needle. По умолчанию для запятой (,).

Примечание: Другое значение для String haystack также может быть определено путем добавления его в качестве первого аргумента: qs_replace(haystack, needle, value) или qs_replace(haystack, needle, options)

Код (примеры внизу). 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');
    }
}

Примеры (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);

Ответ 3

Это решение для вашей задачи: 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

строка параметров инициализации

{ size="small, medium,large", shape="round"} // size=small,medium,large&shape=round

Результаты

{ 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

Ответ 4

productOptions - это единственное, что вам нужно изменить здесь, чтобы просмотреть все доступные параметры и их состояние по умолчанию. Чтобы переключить параметр, вам нужно использовать публичную функцию API toggleOption().

(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;
})()

Пример использования:

// "%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"

Ответ 5

Я пробовал это, и это может дать результат желания

<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>