【问题标题】:Toggle query string variables切换查询字符串变量
【发布时间】:2011-10-29 06:38:24
【问题描述】:

我一直在努力解决这个问题。

使用 jquery 或 javascript,如何切换变量和值,然后重建查询字符串?例如,我的起始 URL 是:

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

然后,如果用户单击标记为“红色”的按钮,我想最终得到:

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

然后,如果用户单击标有“中”的按钮,我想结束:

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

然后,如果用户再次点击标记为“中”,我想结束:

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

变量的顺序并不重要;我已经把它们写到最后了。

【问题讨论】:

  • 并不能真正处理单个变量中的多个值,但我可能可以将它们拼凑起来。感谢您的发现。
  • 对不起,我没有时间为你做一个通用的东西
  • 这个问题很感兴趣,谢谢!
  • 不得不说人们......这些解决方案中的每一个都震撼了!

标签: javascript jquery query-string


【解决方案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:从...? '&amp;' : '' 更改为... ? '&amp;' : '?'

!2:从.replace('?&amp;','?')... 更改为.replace(/([&amp;?]&amp;)/,'$1')...

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

【讨论】:

  • 这真的很酷而且很紧凑。但我认为我遇到了一个错误。将键/值对“color=red”发送到toggle(),然后再次将相同的键/值对发送回toggle(),然后第三次发送相同的键/值对,我丢失了“? "。
  • 最后一个错误。从三个不同的键切换三个不同的值。然后,关闭第二个值。您最终会在查询字符串中使用“&&”。
  • 您应该在使用之前正确地转义keyval。例如,当您使用key=(foo 时,您的代码会抛出错误,因为( 具有特殊的RegExp 含义。
【解决方案2】:

我编写了一个函数,它可以有效地产生预期的行为,而无需使用任何库或框架。 动态演示可以在 this fiddle:http://jsfiddle.net/w8D2G/1/

找到

文档

定义
下面的“用法”部分将使用显示的示例值
-   Haystack - 要搜索的字符串(默认 = 查询字符串。例如:?size=small,medium
-   Needle - 搜索的关键。示例:size
-   Value - 要替换​​/添加的值。示例:medium

用法(例如:input &gt; output):

  1. qs_replace(needle, value)
    如果值存在,删除:?size=small,medium &gt; ?size=small
    如果值不存在,添加:?size=small &gt; size=small,medium
  2. qs_replace(needle, options)     对象选项。公认的选项:
    • find
      字符串。如果值存在则返回true,否则返回false
    • addremovetoggle
      字符串。在needle 中添加/删除给定值。如果使用remove,并且该值是唯一值,则needle 也会被删除。如果值已经存在,则不会添加。
    • ignorecase
      在查找搜索词时忽略大小写(needleaddremovefind)。
    • separator
      指定分隔符以分隔 needle 的值。默认为逗号 (,)。

注意:还可以为 String haystack 定义不同的值,方法是将其添加为第一个参数:qs_replace(haystack, needle, value)qs_replace(haystack, needle, options)

代码(底部示例)。 小提琴: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');
    }
}

示例(小提琴: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
    

    【讨论】:

    • @joeyr 你有机会尝试一下吗?
    • 是的 - 首先测试在 URL 上留下了一个空值的键。需要更多测试。
    • 你能复制粘贴你的输入数据并解释什么不起作用吗?
    • @joeyr,这是您可以在答案中找到的最干净的代码并且它有效,您需要仔细检查 jsFiddle
    【解决方案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"
    

    【讨论】:

    • 这是一个很棒的答案!你能提供jfFiddle吗?它有效,您将赢得赏金,20 小时后结束
    • 这是一个 jsfiddle jsfiddle.net/hSp4J。它在 html 中有 urldecoded 版本,在控制台日志中有原始结果
    【解决方案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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-11
      • 2017-04-13
      • 1970-01-01
      • 2014-04-25
      • 1970-01-01
      • 2011-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多