pugjs إضافة معلمة إلى عنوان URL مع JavaScript




pugjs (21)

في تطبيق الويب الذي يستخدم مكالمات AJAX ، أحتاج إلى إرسال طلب ولكن إضافة معلمة إلى نهاية عنوان URL ، على سبيل المثال:

عنوان URL الأصلي:

http://server/myapp.php?id=10

عنوان URL الناتج:

http://server/myapp.php?id=10 & enabled = true

تبحث عن وظيفة JavaScript تقوم بتوزيع عنوان URL يبحث في كل معلمة ، ثم يضيف المعامل الجديد أو يقوم بتحديث القيمة إذا كان موجود بالفعل.


محاولة
التعبيرات العادية ، بطيئة جدًا ، بالتالي:

var SetParamUrl = function(_k, _v) {// replace and add new parameters

    let arrParams = window.location.search !== '' ? decodeURIComponent(window.location.search.substr(1)).split('&').map(_v => _v.split('=')) : Array();
    let index = arrParams.findIndex((_v) => _v[0] === _k); 
    index = index !== -1 ? index : arrParams.length;
    _v === null ? arrParams = arrParams.filter((_v, _i) => _i != index) : arrParams[index] = [_k, _v];
    let _search = encodeURIComponent(arrParams.map(_v => _v.join('=')).join('&'));

    let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + (arrParams.length > 0 ? '?' +  _search : ''); 

    // window.location = newurl; //reload 

    if (history.pushState) { // without reload  
        window.history.pushState({path:newurl}, null, newurl);
    }

};

var GetParamUrl = function(_k) {// get parameter by key

    let sPageURL = decodeURIComponent(window.location.search.substr(1)),
        sURLVariables = sPageURL.split('&').map(_v => _v.split('='));
    let _result = sURLVariables.find(_v => _v[0] === _k);
    return _result[1];

};

مثال:

        // https://some.com/some_path
        GetParamUrl('cat');//undefined
        SetParamUrl('cat', "strData");// https://some.com/some_path?cat=strData
        GetParamUrl('cat');//strData
        SetParamUrl('sotr', "strDataSort");// https://some.com/some_path?cat=strData&sotr=strDataSort
        GetParamUrl('sotr');//strDataSort
        SetParamUrl('cat', "strDataTwo");// https://some.com/some_path?cat=strDataTwo&sotr=strDataSort
        GetParamUrl('cat');//strDataTwo
        //remove param
        SetParamUrl('cat', null);// https://some.com/some_path?sotr=strDataSort

أنا أحب جواب محمد فاتح يلدز حتى أنه لم يجيب على السؤال بأكمله.

في نفس السطر مثل إجابته ، أستخدم هذا الرمز:

"لا تتحكم في وجود المعلمة ، ولا تغير القيمة الحالية. إنها تضيف المعلمة إلى النهاية"

  /** add a parameter at the end of the URL. Manage '?'/'&', but not the existing parameters.
   *  does escape the value (but not the key)
   */
  function addParameterToURL(_url,_key,_value){
      var param = _key+'='+escape(_value);

      var sep = '&';
      if (_url.indexOf('?') < 0) {
        sep = '?';
      } else {
        var lastChar=_url.slice(-1);
        if (lastChar == '&') sep='';
        if (lastChar == '?') sep='';
      }
      _url += sep + param;

      return _url;
  }

والفاحص:

  /*
  function addParameterToURL_TESTER_sub(_url,key,value){
    //log(_url);
    log(addParameterToURL(_url,key,value));
  }

  function addParameterToURL_TESTER(){
    log('-------------------');
    var _url ='www.google.com';
    addParameterToURL_TESTER_sub(_url,'key','value');
    addParameterToURL_TESTER_sub(_url,'key','Text Value');
    _url ='www.google.com?';
    addParameterToURL_TESTER_sub(_url,'key','value');
    _url ='www.google.com?A=B';
    addParameterToURL_TESTER_sub(_url,'key','value');
    _url ='www.google.com?A=B&';
    addParameterToURL_TESTER_sub(_url,'key','value');
    _url ='www.google.com?A=1&B=2';
    addParameterToURL_TESTER_sub(_url,'key','value');

  }//*/

إليك إصدار مبسط إلى حد كبير ، مما يجعل المقايضات للوضوح وخطوط أقل من الشفرات بدلاً من الأداء الأمثل للجزئيات (ونحن نتحدث عن اختلاف بضعة ميلي ثانية ، واقعيًا ... بسبب طبيعة هذا (التشغيل في موقع المستند الحالي ) ، من المرجح أن يتم تشغيل هذا مرة واحدة على الصفحة).

/**
* Add a URL parameter (or changing it if it already exists)
* @param {search} string  this is typically document.location.search
* @param {key}    string  the key to set
* @param {val}    string  value 
*/
var addUrlParam = function(search, key, val){
  var newParam = key + '=' + val,
      params = '?' + newParam;

  // If the "search" string exists, then build params from it
  if (search) {
    // Try to replace an existance instance
    params = search.replace(new RegExp('([?&])' + key + '[^&]*'), '$1' + newParam);

    // If nothing was replaced, then add the new param to the end
    if (params === search) {
      params += '&' + newParam;
    }
  }

  return params;
};

يمكنك عندئذ استخدام هذا مثل:

document.location.pathname + addUrlParam(document.location.search, 'foo', 'bar');

تحقق من https://github.com/derek-watson/jsUri

Uri ومعالجة سلسلة الاستعلام في javascript.

يحتوي هذا المشروع على مكتبة تعبير معتادة parseUri ممتازة من قبل ستيفن ليفيثان. يمكنك تحليل عناوين URL بأمان من جميع الأشكال والأحجام ، ولكن غير صالحة أو البشعة.


طيب هنا أقارن اثنين من الوظائف ، واحد قدمه نفسي (regExp) وآخر من صنع (annakata).

صفيف الانقسام:

function insertParam(key, value)
{
    key = escape(key); value = escape(value);

    var kvp = document.location.search.substr(1).split('&');

    var i=kvp.length; var x; while(i--) 
    {
        x = kvp[i].split('=');

        if (x[0]==key)
        {
                x[1] = value;
                kvp[i] = x.join('=');
                break;
        }
    }

    if(i<0) {kvp[kvp.length] = [key,value].join('=');}

    //this will reload the page, it's likely better to store this until finished
    return "&"+kvp.join('&'); 
}

طريقة Regexp:

function addParameter(param, value)
{
    var regexp = new RegExp("(\\?|\\&)" + param + "\\=([^\\&]*)(\\&|$)");
    if (regexp.test(document.location.search)) 
        return (document.location.search.toString().replace(regexp, function(a, b, c, d)
        {
                return (b + param + "=" + value + d);
        }));
    else 
        return document.location.search+ param + "=" + value;
}

حالة الاختبار:

time1=(new Date).getTime();
for (var i=0;i<10000;i++)
{
addParameter("test","test");
}
time2=(new Date).getTime();
for (var i=0;i<10000;i++)
{
insertParam("test","test");
}

time3=(new Date).getTime();

console.log((time2-time1)+" "+(time3-time2));

يبدو أنه حتى مع أبسط حل (عندما يستخدم regexp الاختبار فقط ولا تدخل وظيفة .replace) فإنه لا يزال أبطأ من spliting ... حسنا. Regexp هو بطيء نوعا ما ولكن ... uhh ...


كانت هذه محاولة مني ، لكنني سأستخدم الإجابة عن طريق annakata كما يبدو أكثر نظافة:

function AddUrlParameter(sourceUrl, parameterName, parameterValue, replaceDuplicates)
{
    if ((sourceUrl == null) || (sourceUrl.length == 0)) sourceUrl = document.location.href;
    var urlParts = sourceUrl.split("?");
    var newQueryString = "";
    if (urlParts.length > 1)
    {
        var parameters = urlParts[1].split("&");
        for (var i=0; (i < parameters.length); i++)
        {
            var parameterParts = parameters[i].split("=");
            if (!(replaceDuplicates && parameterParts[0] == parameterName))
            {
                if (newQueryString == "")
                    newQueryString = "?";
                else
                    newQueryString += "&";
                newQueryString += parameterParts[0] + "=" + parameterParts[1];
            }
        }
    }
    if (newQueryString == "")
        newQueryString = "?";
    else
        newQueryString += "&";
    newQueryString += parameterName + "=" + parameterValue;

    return urlParts[0] + newQueryString;
}

أيضا ، لقد وجدت هذا البرنامج المساعد jQuery من وظيفة أخرى على ، وإذا كنت بحاجة إلى مزيد من المرونة يمكنك استخدام ذلك: http://plugins.jquery.com/project/query-object

أعتقد أن الشفرة ستكون (لم تختبر):

return $.query.parse(sourceUrl).set(parameterName, parameterValue).toString();

إذا كان لديك سلسلة تحتوي على عنوان url تريد تزيينه باستخدام المعلمة ، فيمكنك تجربة ذلك:

urlstring += ( urlstring.match( /[\?]/g ) ? '&' : '?' ) + 'param=value';

هذا يعني ذلك ؟ ستكون بادئة المعلمة ، لكن إذا كان لديك بالفعل ؟ في urlstring ، من & سوف تكون البادئة.

أود أن أوصي أيضًا encodeURI( paramvariable ) إذا لم تكن معلمة ضمنية ، ولكنها داخل paramvariable ؛ أو إذا كان لديك أحرف مضحكة في ذلك.

راجع javascript URL Encoding لاستخدام وظيفة encodeURI .


شكرا لكم جميعا على مساهمتكم. استخدمت شفرة annakata وتعديلها لتتضمن أيضًا الحالة التي لا تحتوي على سلسلة استعلام في عنوان url على الإطلاق. آمل أن هذا من شأنه أن يساعد.

function insertParam(key, value) {
        key = escape(key); value = escape(value);

        var kvp = document.location.search.substr(1).split('&');
        if (kvp == '') {
            document.location.search = '?' + key + '=' + value;
        }
        else {

            var i = kvp.length; var x; while (i--) {
                x = kvp[i].split('=');

                if (x[0] == key) {
                    x[1] = value;
                    kvp[i] = x.join('=');
                    break;
                }
            }

            if (i < 0) { kvp[kvp.length] = [key, value].join('='); }

            //this will reload the page, it's likely better to store this until finished
            document.location.search = kvp.join('&');
        }
    }

/**
* Add a URL parameter 
* @param {string} url 
* @param {string} param the key to set
* @param {string} value 
*/
var addParam = function(url, param, value) {
   param = encodeURIComponent(param);
   var a = document.createElement('a');
   param += (value ? "=" + encodeURIComponent(value) : ""); 
   a.href = url;
   a.search += (a.search ? "&" : "") + param;
   return a.href;
}

/**
* Add a URL parameter (or modify if already exists)
* @param {string} url 
* @param {string} param the key to set
* @param {string} value 
*/
var addOrReplaceParam = function(url, param, value) {
   param = encodeURIComponent(param);
   var r = "([&?]|&amp;)" + param + "\\b(?:=(?:[^&#]*))*";
   var a = document.createElement('a');
   var regex = new RegExp(r);
   var str = param + (value ? "=" + encodeURIComponent(value) : ""); 
   a.href = url;
   var q = a.search.replace(regex, "$1"+str);
   if (q === a.search) {
      a.search += (a.search ? "&" : "") + str;
   } else {
      a.search = q;
   }
   return a.href;
}

url = "http://www.example.com#hashme";
newurl = addParam(url, "ciao", "1");
alert(newurl);

ويرجى ملاحظة أنه يجب ترميز المعلمات قبل إلحاقها في سلسلة الاستعلام.

http://jsfiddle.net/48z7z4kx/


هذا هو الحل البسيط جدا. لا تتحكم في وجود المعلمة ، ولا تغير القيمة الحالية. يضيف المعلمة الخاصة بك إلى نهاية ، بحيث يمكنك الحصول على أحدث قيمة في رمز الخلفية.

function addParameterToURL(param){
    _url = location.href;
    _url += (_url.split('?')[1] ? '&':'?') + param;
    return _url;
}

أبسط حل أستطيع التفكير فيه هو هذه الطريقة ، والتي ستعيد عنوان URI المعدل. أشعر أن معظمكم يعمل بطريقة صعبة للغاية.

function setParam(uri, key, val) {
    return uri
        .replace(new RegExp("([?&]"+key+"(?=[=&#]|$)[^#&]*|(?=#|$))"), "&"+key+"="+encodeURIComponent(val))
        .replace(/^([^?&]+)&/, "$1?");
}

على أفضل ما يمكنني أن أقول لا شيء من الإجابات أعلاه تتناول الحالة التي تحتوي فيها سلسلة الاستعلام على معلمات هي في حد ذاتها مصفوفة وبالتالي ستظهر أكثر من مرة ، على سبيل المثال:

http://example.com?sizes[]=a&sizes[]=b

الوظيفة التالية هي ما كتبت لتحديث document.location.search . يتطلب الأمر صفيفًا من صفائف الأزواج الرئيسية / القيمة كحجة وسيعيد إصدارًا منقحًا من هذا الأخير الذي يمكنك فعله بما تريد. أنا أستخدمها على هذا النحو:

var newParams = [
    ['test','123'],
    ['best','456'],
    ['sizes[]','XXL']
];
var newUrl = document.location.pathname + insertParams(newParams);
history.replaceState('', '', newUrl);

إذا كان عنوان url الحالي هو:

http://example.com/index.php?test=replaceme&sizes[]=XL

هذا من شأنه أن يجعلك

http://example.com/index.php?test=123&sizes[]=XL&sizes[]=XXL&best=456

وظيفة

function insertParams(params) {
    var result;
    var ii = params.length;
    var queryString = document.location.search.substr(1);
    var kvps = queryString ? queryString.split('&') : [];
    var kvp;
    var skipParams = [];
    var i = kvps.length;
    while (i--) {
        kvp = kvps[i].split('=');
        if (kvp[0].slice(-2) != '[]') {
            var ii = params.length;
            while (ii--) {
                if (params[ii][0] == kvp[0]) {
                    kvp[1] = params[ii][1];
                    kvps[i] = kvp.join('=');
                    skipParams.push(ii);
                }
            }
        }
    }
    var ii = params.length;
    while (ii--) {
        if (skipParams.indexOf(ii) === -1) {
            kvps.push(params[ii].join('='));
        }
    }
    result = kvps.length ? '?' + kvps.join('&') : '';
    return result;
}

في وقت ما نرى ? في نهاية عنوان URL ، وجدت بعض الحلول التي تولد النتائج مثل file.php?&foo=bar . توصلت مع حل بلدي العمل تماما كما أريد!

location.origin + location.pathname + location.search + (location.search=='' ? '?' : '&') + 'lang=ar'

ملاحظة: location.origin لا يعمل في IE ، هنا هو الإصلاح الخاص به .


سيبدو التنفيذ الأساسي الذي ستحتاج إلى تكييفه كما يلي:

function insertParam(key, value)
{
    key = encodeURI(key); value = encodeURI(value);

    var kvp = document.location.search.substr(1).split('&');

    var i=kvp.length; var x; while(i--) 
    {
        x = kvp[i].split('=');

        if (x[0]==key)
        {
            x[1] = value;
            kvp[i] = x.join('=');
            break;
        }
    }

    if(i<0) {kvp[kvp.length] = [key,value].join('=');}

    //this will reload the page, it's likely better to store this until finished
    document.location.search = kvp.join('&'); 
}

هذا أسرع مرتين تقريبًا من حل regex أو البحث المستند إلى البحث ، ولكن هذا يعتمد تمامًا على طول سلسلة الاستعلام والفهرس في أي تطابق

طريقة regex البطيئة التي قُمت بها مقابل الإكمالات (حوالي 150٪ أبطأ)

function insertParam2(key,value)
{
    key = encodeURIComponent(key); value = encodeURIComponent(value);

    var s = document.location.search;
    var kvp = key+"="+value;

    var r = new RegExp("(&|\\?)"+key+"=[^\&]*");

    s = s.replace(r,"$1"+kvp);

    if(!RegExp.$1) {s += (s.length>0 ? '&' : '?') + kvp;};

    //again, do what you will here
    document.location.search = s;
}

إذا كنت تتلاعب بعناوين url في الروابط أو في مكان آخر ، فقد تضطر إلى أخذ التجزئة أيضًا بعين الاعتبار. هنا بسيطة إلى حد ما لفهم الحل. ربما ليس أسرع لأنه يستخدم regex ... ولكن في 99.999 ٪ من الحالات ، لا يهم الفرق حقا!

function addQueryParam( url, key, val ){
    var parts = url.match(/([^?#]+)(\?[^#]*)?(\#.*)?/);
    var url = parts[1];
    var qs = parts[2] || '';
    var hash = parts[3] || '';

    if ( !qs ) {
        return url + '?' + key + '=' + encodeURIComponent( val ) + hash;
    } else {
        var qs_parts = qs.substr(1).split("&");
        var i;
        for (i=0;i<qs_parts.length;i++) {
            var qs_pair = qs_parts[i].split("=");
            if ( qs_pair[0] == key ){
                qs_parts[ i ] = key + '=' + encodeURIComponent( val );
                break;
            }
        }
        if ( i == qs_parts.length ){
            qs_parts.push( key + '=' + encodeURIComponent( val ) );
        }
        return url + '?' + qs_parts.join('&') + hash;
    }
}

هذا سوف يعمل في جميع المتصفحات الحديثة.

function insertParam(key,value) {
      if (history.pushState) {
          var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' +key+'='+value;
          window.history.pushState({path:newurl},'',newurl);
      }
    }

var MyApp = new Class();

MyApp.extend({
    utility: {
        queryStringHelper: function (url) {
            var originalUrl = url;
            var newUrl = url;
            var finalUrl;
            var insertParam = function (key, value) {
                key = escape(key);
                value = escape(value);

                //The previous post had the substr strat from 1 in stead of 0!!!
                var kvp = newUrl.substr(0).split('&');

                var i = kvp.length;
                var x;
                while (i--) {
                    x = kvp[i].split('=');

                    if (x[0] == key) {
                        x[1] = value;
                        kvp[i] = x.join('=');
                        break;
                    }
                }

                if (i < 0) {
                    kvp[kvp.length] = [key, value].join('=');
                }

                finalUrl = kvp.join('&');

                return finalUrl;
            };

            this.insertParameterToQueryString = insertParam;

            this.insertParams = function (keyValues) {
                for (var keyValue in keyValues[0]) {
                    var key = keyValue;
                    var value = keyValues[0][keyValue];
                    newUrl = insertParam(key, value);
                }
                return newUrl;
            };

            return this;
        }
    }
});


من خلال الإنجازات الجديدة في JS هنا ، يمكنك إضافة معلمة طلب البحث إلى عنوان URL:

var protocol = window.location.protocol,
    host = '//' + window.location.host,
    path = window.location.pathname,
    query = window.location.search;

var newUrl = protocol + host + path + query + (query ? '&' : '?') + 'param=1';

window.history.pushState({path:newUrl}, '' , newUrl);

انظر أيضا هذه الإمكانية Moziila URLSearchParams.append ()


أسهل حل ، يعمل إذا كان لديك بالفعل علامة أم لا ، ويزيلها تلقائيًا حتى لا يبقى إضافة علامات متساوية ، يستمتع

function changeURL(tag)
{
if(window.location.href.indexOf("?") > -1) {
    if(window.location.href.indexOf("&"+tag) > -1){

        var url = window.location.href.replace("&"+tag,"")+"&"+tag;
    }
    else
    {
        var url = window.location.href+"&"+tag;
    }
}else{
    if(window.location.href.indexOf("?"+tag) > -1){

        var url = window.location.href.replace("?"+tag,"")+"?"+tag;
    }
    else
    {
        var url = window.location.href+"?"+tag;
    }
}
  window.location = url;
}

ثم

changeURL("i=updated");

لدي "فئة" تقوم بذلك وهذا هو:

function QS(){
    this.qs = {};
    var s = location.search.replace( /^\?|#.*$/g, '' );
    if( s ) {
        var qsParts = s.split('&');
        var i, nv;
        for (i = 0; i < qsParts.length; i++) {
            nv = qsParts[i].split('=');
            this.qs[nv[0]] = nv[1];
        }
    }
}

QS.prototype.add = function( name, value ) {
    if( arguments.length == 1 && arguments[0].constructor == Object ) {
        this.addMany( arguments[0] );
        return;
    }
    this.qs[name] = value;
}

QS.prototype.addMany = function( newValues ) {
    for( nv in newValues ) {
        this.qs[nv] = newValues[nv];
    }
}

QS.prototype.remove = function( name ) {
    if( arguments.length == 1 && arguments[0].constructor == Array ) {
        this.removeMany( arguments[0] );
        return;
    }
    delete this.qs[name];
}

QS.prototype.removeMany = function( deleteNames ) {
    var i;
    for( i = 0; i < deleteNames.length; i++ ) {
        delete this.qs[deleteNames[i]];
    }
}

QS.prototype.getQueryString = function() {
    var nv, q = [];
    for( nv in this.qs ) {
        q[q.length] = nv+'='+this.qs[nv];
    }
    return q.join( '&' );
}

QS.prototype.toString = QS.prototype.getQueryString;

//examples
//instantiation
var qs = new QS;
alert( qs );

//add a sinle name/value
qs.add( 'new', 'true' );
alert( qs );

//add multiple key/values
qs.add( { x: 'X', y: 'Y' } );
alert( qs );

//remove single key
qs.remove( 'new' )
alert( qs );

//remove multiple keys
qs.remove( ['x', 'bogus'] )
alert( qs );

لقد تجاوزت طريقة toString لذا ليس هناك حاجة للاتصال بـ QS :: getQueryString ، يمكنك استخدام QS :: toString أو ، كما فعلت في الأمثلة فقط اعتمد على الكائن الذي يتم إكراهه في سلسلة.





query-string