How to center google maps on users ip address using javascript? - javascript

//Using the Google Maps API to create the map.
var myLatlngCenter = new google.maps.LatLng(54.080743,-2.482910);
var mapOptions = {
center: myLatlngCenter,
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var myMap = new google.maps.Map(document.getElementById("map_canvas"),mapOptions);
At the minute, this how my javascript looks and it centers the map on the new google.maps.LatLng(54.080743,-2.482910);
Is there something I can put inside () to center the map on the users ip address.

You need to identify the lon, lat from the IP so you have a few options
http://ipinfodb.com/ip_location_api_json.php is a useful resource for this
A javascript example of using that is here (from there site)
function geolocate(timezone, cityPrecision, objectVar) {
var api = (cityPrecision) ? "ip-city" : "ip-country";
var domain = 'api.ipinfodb.com';
var url = "http://" + domain + "/v3/" + api + "/?key=<your_api_key>&format=json" + "&callback=" + objectVar + ".setGeoCookie";
var geodata;
var callbackFunc;
var JSON = JSON || {};
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string") obj = '"'+obj+'"';
return String(obj);
} else {
// recurse array or object
var n, v, json = [], arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n]; t = typeof(v);
if (t == "string") v = '"'+v+'"';
else if (t == "object" && v !== null) v = JSON.stringify(v);
json.push((arr ? "" : '"' + n + '":') + String(v));
}
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
};
// implement JSON.parse de-serialization
JSON.parse = JSON.parse || function (str) {
if (str === "") str = '""';
eval("var p=" + str + ";");
return p;
};
//Check if cookie already exist. If not, query IPInfoDB
this.checkcookie = function(callback) {
geolocationCookie = getCookie('geolocation');
callbackFunc = callback;
if (!geolocationCookie) {
getGeolocation();
} else {
geodata = JSON.parse(geolocationCookie);
callbackFunc();
}
}
//API callback function that sets the cookie with the serialized JSON answer
this.setGeoCookie = function(answer) {
if (answer['statusCode'] == 'OK') {
JSONString = JSON.stringify(answer);
setCookie('geolocation', JSONString, 365);
geodata = answer;
callbackFunc();
}
}
//Return a geolocation field
this.getField = function(field) {
try {
return geodata[field];
} catch(err) {}
}
//Request to IPInfoDB
function getGeolocation() {
try {
script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
} catch(err) {}
}
//Set the cookie
function setCookie(c_name, value, expire) {
var exdate=new Date();
exdate.setDate(exdate.getDate()+expire);
document.cookie = c_name+ "=" +escape(value) + ((expire==null) ? "" : ";expires="+exdate.toGMTString());
}
//Get the cookie content
function getCookie(c_name) {
if (document.cookie.length > 0 ) {
c_start=document.cookie.indexOf(c_name + "=");
if (c_start != -1){
c_start=c_start + c_name.length+1;
c_end=document.cookie.indexOf(";",c_start);
if (c_end == -1) {
c_end=document.cookie.length;
}
return unescape(document.cookie.substring(c_start,c_end));
}
}
return '';
}
}
You will need an api key but then good to go
You could also consider using HTML5 geolocation much easier https://developers.google.com/maps/articles/geolocation

Related

Uncaught TypeError: u(...).getServerUrl is not a function in HTML Web Resource

I'm guessing this code would work fine on a form. I always seem to have problems with Xrm.Page.Context and methods like getServerUrl when I am working on javascript within an HTML web resource.
Here is the function I am trying to run:
function getAttributeOptions(entityLogicalName, attributeLogicalName, dictionaryObject, onComplete) {
///<summary>
/// <para>Retrieves the picklist attribute options and appends them to a dictionary object.</para>
/// <para>It then executes the function assigned to the onComplete parameter.</para>
///</summary>
///<param name="entityLogicalName" type="String">
/// The logical name of the entity
///</param>
///<param name="attributeLogicalName" type="String">
/// The logical name of the Picklist attribute
///</param>
///<param name="dictionaryObject" type="Object">
/// An empty object that will become a dictionary for the option values.
///</param>
///<param name="onComplete" type="Function">
/// A function to perform when the options are assigned to the dictionaryObject;
///</param>
if (!(typeof entityLogicalName == "string")) {
throw new Error("getAttributeOptions entityLogicalName parameter is required and must be a string.");
}
if (!(typeof attributeLogicalName == "string")) {
throw new Error("getAttributeOptions attributeLogicalName parameter is required and must be a string.");
}
if (!(typeof dictionaryObject == "object")) {
throw new Error("getAttributeOptions dictionaryObject parameter is required and must be an object.");
}
if (!(typeof onComplete == "function")) {
throw new Error("getAttributeOptions onComplete parameter is required and must be a function.");
}
var passThroughObject = {};
passThroughObject.eln = entityLogicalName;
passThroughObject.aln = attributeLogicalName;
passThroughObject.dObj = dictionaryObject;
passThroughObject.oc = onComplete;
if ((typeof SDK == "undefined") || (typeof SDK.Metadata == "undefined") || (typeof SDK.Metadata.Query == "undefined")) {
throw new Error("getAttributeOptions function requires the SDK.Metadata.Query.min.js library and it is not present.");
}
var mdq = SDK.Metadata.Query;
var semp = mdq.SearchableEntityMetadataProperties;
var samp = mdq.SearchableAttributeMetadataProperties;
var srmp = mdq.SearchableRelationshipMetadataProperties
var emp = mdq.EntityMetadataProperties;
var amp = mdq.AttributeMetadataProperties;
var rmp = mdq.RelationshipMetadataProperties;
var ve = mdq.ValueEnums;
//EntityFilter
var ef = new mdq.MetadataFilterExpression(mdq.LogicalOperator.And);
ef.addCondition(semp.LogicalName, mdq.MetadataConditionOperator.Equals, entityLogicalName);
//Entity Properties
var ep = new mdq.MetadataPropertiesExpression(false, [emp.Attributes]);
//Attribute Filter
var af = new mdq.MetadataFilterExpression(mdq.LogicalOperator.And);
af.addCondition(samp.LogicalName, mdq.MetadataConditionOperator.Equals, attributeLogicalName);
//Attribute Properties
var ap = new mdq.MetadataPropertiesExpression(false, [amp.OptionSet, amp.AttributeType]);
// AttributeQuery
var aq = new mdq.AttributeQueryExpression(af, ap);
// LabelQuery
var lq = new mdq.LabelQueryExpression([1033]);
//EntityQueryExpression
var eqe = new mdq.EntityQueryExpression(ef, ep, aq, null, lq);
//RetrieveMetadataChangesRequest
var rmcr = new mdq.RetrieveMetadataChangesRequest(eqe, null, mdq.DeletedMetadataFilters.Default);
mdq.RetrieveMetadataChanges(
rmcr,
function(rmcResponse, pto) {
var attributeType = "unknown";
if (typeof rmcResponse.EntityMetadata[0] == "undefined" || rmcResponse.EntityMetadata[0] == null) {
throw new Error("No entity metadata found for " + pto.eln);
}
if (typeof rmcResponse.EntityMetadata[0].Attributes[0] == "undefined" || rmcResponse.EntityMetadata[0].Attributes[0] == null) {
throw new Error("No attribute metadata found for " + pto.eln + "." + pto.aln);
}
if (typeof rmcResponse.EntityMetadata[0].Attributes[0].OptionSet == "undefined" || rmcResponse.EntityMetadata[0].Attributes[0].OptionSet == null) {
throw new Error(pto.eln + "." + pto.aln + " does not have an OptionSet property.");
}
attributeType = rmcResponse.EntityMetadata[0].Attributes[0].AttributeType;
if (attributeType != "Boolean") {
if (typeof rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options == "undefined" || rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options == null) {
throw new Error(pto.eln + "." + pto.aln + "OptionSet does not have an Options property");
}
if (typeof rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options[0] == "undefined" || rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options[0] == null) {
throw new Error(pto.eln + "." + pto.aln + "OptionSet.Options does not have any options");
}
}
pto.dObj[pto.eln] = pto.dObj[pto.eln] || {};
pto.dObj[pto.eln].attributes = pto.dObj[pto.eln].attributes || {};
pto.dObj[pto.eln].attributes[pto.aln] = pto.dObj[pto.eln].attributes[pto.aln] || {};
pto.dObj[pto.eln].attributes[pto.aln].options = pto.dObj[pto.eln].attributes[pto.aln].options || {};
if (attributeType != "Boolean") {
for (var i in rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options) {
var option = rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options[i];
pto.dObj[pto.eln].attributes[pto.aln].options[option.Value] = option.Label.UserLocalizedLabel.Label;
}
} else {
pto.dObj[pto.eln].attributes[pto.aln].options[0] = rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.FalseOption.Label.UserLocalizedLabel.Label;
pto.dObj[pto.eln].attributes[pto.aln].options[1] = rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.TrueOption.Label.UserLocalizedLabel.Label;
}
pto.oc(pto.eln, pto.aln);
},
function(error) {
writeMessage(error.message);
},
passThroughObject);
}
// MetaDataDictionary
var mdd = {};
function testResults(entityLogicalName, attributeLogicalName) {
alert("Options for " + entityLogicalName + "." + attributeLogicalName + " cached.");
}
getAttributeOptions("contact", "statecode", mdd, testResults);
for (option in mdd.contact.attributes.statecode.options) {
var value = option;
var label = mdd.contact.attributes.statecode.options[option];
alert(label);
}
Here is the problematic part of the library that I am using:
function u() {
var n = "Context is not available.";
return typeof GetGlobalContext != "undefined" ? GetGlobalContext() : typeof Xrm != "undefined" ? Xrm.Page.context : new Error(n)
}
function h() {
var n = u().getServerUrl();
return n.match(/\/$/) && (n = n.substring(0, n.length - 1)), typeof u().getClientUrl != "undefined" && (n = u().getClientUrl()), n
}
Here is my error:
I'd really like for getServerUrl and getClientUrl to be available to me. What can I do to achieve this?
Verify the path & add this library in your HTML webresource to access CRM context.
<script type="text/javascript" src="ClientGlobalContext.js.aspx"></script>
When you need context information outside a form, include a reference to the ClientGlobalContext.js.aspx page in an HTML web resource.
GetGlobalContext
Also getServerUrl is deprecated, you have to use getClientUrl based on your CRM version.

Interaction in a Dynamic action between javascript and plsql tasks

I'm trying to execute several pl/sql blocks in a Dynamic Action, with feedback to the end user with a modal dialog reporting the current satus.
Something like:
Processing Step 1...
/*Run pl/sql code for step 1*/
Processing Step 2...
/*Run pl/sql code for Step 2*/
and so on...
Both, the pl/sql and javascript code, run as intended but when I combined them on a Dynamic Action in the sequence:
1 - Execute Javascript
2 - Execute PL/SQL block /* With wait for result option checked*/
3 - Execute Javascript
4 - Execute PL/SQL block
The status dialog is not been shown, however the pl/sql blocks are completed without problems.
I realize that this must be something related to javascript not been multithreaded, so I've moved the pl/sql block to application processes and run them as ajax calls like this:
function something(){
var get;
var result = 0;
updateStatus('Running Step1');
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
result = get.get();
if(result > 0){
updateStatus('Running Step 2');
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
result = get.get();
}
closeStatusDialog();
}
But still, as before, the processes run fine but the dialog doesn't appear. Finally I added a setTimeOut function to each call, like this:
function something(){
var get;
var result = 0;
updateStatus('Running Step1');
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
result = setTimeOut(get.get(),500);
if(result > 0){
updateStatus('Running Step 2');
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
result = setTimeOut(get.get(),500);
}
closeStatusDialog();
}
But still nothing. What can I do to get this running as needed?.
I've checked the browser console and no exeptions are been thrown, likewise with the pl/sql blocks.
I've solved it, although the solution doesn't rely on dynamic actions, just javascript and applicacion processes. I'm posting this for anyone with a similar problem.
The htmldb_Get Javascript object is an oracle-apex wrapper for the XMLHttpRequest AJAX object. Poorly documented though.
I've found a copy of the code (at the bottom) and it turns out it has another function called GetAsync that allows to pass a function as a parameter to asign it to the onreadystatechange attribute on the XMLHttpRequest object, which will be executed each time the attribute readyState of the underlying XMLHttpRequest changes.
The function passed as a parameter can't have parameters on its own definition.
So, instead of calling get() on the htmldb_Get object you need to call GetAsync(someFunction)
With this solution in my case:
function something(){
var get;
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
get.GetAsync(someFunctionStep1);
}
function someFunctionStep1(){
if(p.readyState == 0){ /*p is the underlying XMLHttpRequest object*/
console.log("request not initialized");
updateStatus('Running Step 1');
} else if(p.readyState == 1){
console.log("server connection established");
} else if(p.readyState == 2){
console.log("request received");
} else if(p.readyState == 3){
console.log("processing request");
} else if(p.readyState == 4){
console.log("request finished and response is ready");
callStep2();
}
}
function callStep2(){
var get;
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
get.GetAsync(someFunctionStep2);
}
function someFunctionStep2(){
if(p.readyState == 0){
console.log("request not initialized");
updateStatus('Running Step 2');
} else if(p.readyState == 1){
console.log("server connection established");
} else if(p.readyState == 2){
console.log("request received");
} else if(p.readyState == 3){
console.log("processing request");
} else if(p.readyState == 4){
console.log("request finished and response is ready");
closeDialog();
}
}
Here's the htmldb_get definition, at the end is the GetAsync function
/*
str should be in the form of a valid f?p= syntax
*/
function htmldb_Get(obj,flow,req,page,instance,proc,queryString) {
//
// setup variables
//
this.obj = $x(obj); // object to put in the partial page
this.proc = proc != null ? proc : 'wwv_flow.show'; // proc to call
this.flow = flow != null ? flow : $x('pFlowId').value; // flowid
this.request = req != null ? req : ''; // request
this.page = page; // page
this.params = ''; // holder for params
this.response = ''; // holder for the response
this.base = null; // holder fot the base url
this.queryString = queryString!= null ? queryString : null ; // holder for passing in f? syntax
this.syncMode = false;
//
// declare methods
//
this.addParam = htmldb_Get_addParam;
this.add = htmldb_Get_addItem;
this.getPartial = htmldb_Get_trimPartialPage;
this.getFull = htmldb_Get_fullReturn;
this.get = htmldb_Get_getData;
this.url = htmldb_Get_getUrl;
this.escape = htmldb_Get_escape;
this.clear = htmldb_Get_clear;
this.sync = htmldb_Get_sync;
this.setNode = setNode;
this.replaceNode = replaceNode
//
// setup the base url
//
var u = window.location.href.indexOf("?") > 0 ?
window.location.href.substring(0,window.location.href.indexOf("?"))
: window.location.href;
this.base = u.substring(0,u.lastIndexOf("/"));
if ( this.proc == null || this.proc == "" )
this.proc = u.substring(u.lastIndexOf("/")+1);
this.base = this.base +"/" + this.proc;
//
// grab the instance form the page form
//
if ( instance == null || instance == "" ) {
var pageInstance = document.getElementById("pInstance");
if ( typeof(pageInstance) == 'object' ) {
this.instance = pageInstance.value;
}
} else {
this.instance = instance;
}
//
// finish setiing up the base url and params
//
if ( ! queryString ) {
this.addParam('p_request', this.request) ;
this.addParam('p_instance', this.instance);
this.addParam('p_flow_id', this.flow);
this.addParam('p_flow_step_id',this.page);
}
function setNode(id) {
this.node = html_GetElement(id);
}
function replaceNode(newNode){
var i=0;
for(i=this.node.childNodes.length-1;i>=0;i--){
this.node.removeChild(this.node.childNodes[i]);
}
this.node.appendChild(newNode);
}
}
function htmldb_Get_sync(s){
this.syncMode=s;
}
function htmldb_Get_clear(val){
this.addParam('p_clear_cache',val);
}
//
// return the queryString
//
function htmldb_Get_getUrl(){
return this.queryString == null ? this.base +'?'+ this.params : this.queryString;
}
function htmldb_Get_escape(val){
// force to be a string
val = val + "";
val = val.replace(/\%/g, "%25");
val = val.replace(/\+/g, "%2B");
val = val.replace(/\ /g, "%20");
val = val.replace(/\./g, "%2E");
val = val.replace(/\*/g, "%2A");
val = val.replace(/\?/g, "%3F");
val = val.replace(/\\/g, "%5C");
val = val.replace(/\//g, "%2F");
val = val.replace(/\>/g, "%3E");
val = val.replace(/\</g, "%3C");
val = val.replace(/\{/g, "%7B");
val = val.replace(/\}/g, "%7D");
val = val.replace(/\~/g, "%7E");
val = val.replace(/\[/g, "%5B");
val = val.replace(/\]/g, "%5D");
val = val.replace(/\`/g, "%60");
val = val.replace(/\;/g, "%3B");
val = val.replace(/\?/g, "%3F");
val = val.replace(/\#/g, "%40");
val = val.replace(/\&/g, "%26");
val = val.replace(/\#/g, "%23");
val = val.replace(/\|/g, "%7C");
val = val.replace(/\^/g, "%5E");
val = val.replace(/\:/g, "%3A");
val = val.replace(/\=/g, "%3D");
val = val.replace(/\$/g, "%24");
//val = val.replace(/\"/g, "%22");
return val;
}
//
// Simple function to add name/value pairs to the url
//
function htmldb_Get_addParam(name,val){
if ( this.params == '' )
this.params = name + '='+ ( val != null ? this.escape(val) : '' );
else
//this.params = this.params + '&'+ name + '='+ ( val != null ? val : '' );
this.params = this.params + '&'+ name + '='+ ( val != null ? this.escape(val) : '' );
return;
}
//
// Simple function to add name/value pairs to the url
//
function htmldb_Get_addItem(name,value){
this.addParam('p_arg_names',name);
this.addParam('p_arg_values',value);
}
//
// funtion strips out the PPR sections and returns that
//
function htmldb_Get_trimPartialPage(startTag,endTag,obj) {
setTimeout(html_processing,1);
if (obj) {this.obj = $x(obj);}
if (!startTag){startTag = '<!--START-->'};
if (!endTag){endTag = '<!--END-->'};
var start = this.response.indexOf(startTag);
var part;
if ( start >0 ) {
this.response = this.response.substring(start+startTag.length);
var end = this.response.indexOf(endTag);
this.response = this.response.substring(0,end);
}
if ( this.obj ) {
if(this.obj.nodeName == 'INPUT'){
if(document.all){
gResult = this.response;
gNode = this.obj;
var ie_HACK = 'htmldb_get_WriteResult()';
setTimeout(ie_HACK,100);
}else{
this.obj.value = this.response;
}
}else{
if(document.all){
gResult = this.response;
gNode = this.obj;
var ie_HACK = 'htmldb_get_WriteResult()';
setTimeout(ie_HACK,100);
}else{
this.obj.innerHTML = this.response;
}
}
}
//window.status = 'Done'
setTimeout(html_Doneprocessing,1);
return this.response;
}
var gResult = null;
var gNode = null
function htmldb_get_WriteResult(){
if(gNode && ( gNode.nodeName == 'INPUT' || gNode.nodeName == 'TEXTAREA')){
gNode.value = gResult;
}else{
gNode.innerHTML = gResult;
}
gResult = null;
gNode = null;
return;
}
//
// function return the full response
//
function htmldb_Get_fullReturn(obj) {
setTimeout(html_processing,1);
if (obj) { this.obj = html_GetElement(obj);}
if ( this.obj ) {
if(this.obj.nodeName == 'INPUT'){
this.obj.value = this.response;
}else{
if(document.all){
gResult = this.response;
gNode = this.obj;
var ie_HACK = 'htmldb_get_WriteResult()';
setTimeout(ie_HACK,10);
}else{
this.obj.innerHTML = this.response;
}
}
}
setTimeout(html_Doneprocessing,1);
return this.response;
}
//
// Perform the actual get from the server
//
function htmldb_Get_getData(mode,startTag,endTag){
html_processing();
var p;
try {
p = new XMLHttpRequest();
} catch (e) {
p = new ActiveXObject("Msxml2.XMLHTTP");
}
try {
var startTime = new Date();
p.open("POST", this.base, this.syncMode);
p.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
p.send(this.queryString == null ? this.params : this.queryString );
this.response = p.responseText;
if ( this.node )
this.replaceNode(p.responseXML);
if ( mode == null || mode =='PPR' ) {
return this.getPartial(startTag,endTag);
} if ( mode == "XML" ) {
setTimeout(html_Doneprocessing,1);
return p.responseXML;
} else {
return this.getFull();
}
} catch (e) {
setTimeout(html_Doneprocessing,1);
return;
}
}
function html_Doneprocessing(){
document.body.style.cursor="default";
}
function html_processing(){
document.body.style.cursor="wait";
}
/*
this adds better aysnc functionality
to the htmldb_Get object
pVar is the function that you want to call when the xmlhttp state changes
in the function specified by pVar the xmlhttp object can be referenced by the variable p
*/
htmldb_Get.prototype.GetAsync = function(pVar){
try{
p = new XMLHttpRequest();
}catch(e){
p = new ActiveXObject("Msxml2.XMLHTTP");
}
try {
var startTime = new Date();
p.open("POST", this.base, true);
if(p) {
p.onreadystatechange = pVar;
p.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
p.send(this.queryString == null ? this.params : this.queryString );
return p;
}
}catch(e){
return false;
}
}
/* PDF OUTPUT */
/*Gets PDF src XML */
function htmldb_ExternalPost(pThis,pRegion,pPostUrl){
var pURL = 'f?p='+html_GetElement('pFlowId').value+':'+html_GetElement('pFlowStepId').value+':'+html_GetElement('pInstance').value+':FLOW_FOP_OUTPUT_R'+pRegion
document.body.innerHTML = document.body.innerHTML + '<div style="display:none;" id="dbaseSecondForm"><form id="xmlFormPost" action="' + pPostUrl + '?ie=.pdf" method="post" target="pdf"><textarea name="vXML" id="vXML" style="width:500px;height:500px;"></textarea></form></div>';
var l_El = html_GetElement('vXML');
var get = new htmldb_Get(l_El,null,null,null,null,'f',pURL.substring(2));
get.get();
get = null;
setTimeout('html_GetElement("xmlFormPost").submit()',10);
return;
}
function $xml_Control(pThis){
this.xsl_string = '<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="html"/><xsl:param name="xpath" /><xsl:template match="/"><xsl:copy-of select="//*[#id=$xpath]"/></xsl:template></xsl:stylesheet>';
if(document.all){
this.xsl_object = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.3.0");
this.xsl_object.async=false;
this.xsl_object.loadXML(this.xsl_string)
tmp = new ActiveXObject("Msxml2.XSLTemplate.3.0");
tmp.stylesheet = this.xsl_object;
this.xsl_processor = tmp.createProcessor();
}else{
this.xsl_object = (new DOMParser()).parseFromString(this.xsl_string, "text/xml");
this.xsl_processor = (new XSLTProcessor());
this.xsl_processor.importStylesheet(this.xsl_object);
this.ownerDocument = document.implementation.createDocument("", "test", null);
}
this.xml = pThis;
this.CloneAndPlace = _CloneAndPlace;
return
function _CloneAndPlace(pThis,pThat,pText){
var lThat = $x(pThat);
if(document.all){
this.xsl_processor.addParameter("xpath", pThis);
this.xsl_processor.input = this.xml;
this.xsl_processor.transform;
var newFragment = this.xsl_processor.output;
}else{
this.xsl_processor.setParameter(null, "xpath", pThis);
var newFragment = this.xsl_processor.transformToFragment(this.xml,this.ownerDocument);
}
if(lThat){
if(document.all){
lThat.innerHTML='';
lThat.innerHTML=newFragment;
}else{
lThat.innerHTML='';
lThat.appendChild(newFragment);
}
/*
in IE newFragment will be a string
in FF newFragment will be a dome Node (more useful)
*/
return newFragment;
}
}
}

How to load JSON feature in Javascript for IE8?

I am trying to load JSON feature in JavaScript for IE8 in a comparability mode.
I was advised to use douglascrockford/JSON-js to get JSON loaded in obsolete browsers.
Here is what I have done. I added a new file in my resources folder and called it json2.js Then from the JSON-js project I copied the json2.js file content and pasted it into my json2.js file and included the file resources/json2.js into my app.
Now, I am trying to use JSON.stringify to convert an object into json string which is giving me the following error
But when I use JSON.stringify(records) in IE8 under compatibility mode I get this error
Line: 314
Char: 21
Error: Invalid procedure call or argument
Code: 0
Here is what I have done
HTML Markup
<div id="d">Click Here</div>
<div id="s"></div>
Javascript code
var records = {};
$(function(e){
records['123'] = {};
records['456'] = {};
records['123']['rec_id'] = 4456;
records['123']['created_at'] = '';
records['123']['assigned_at'] = '';
records['123']['sys_id'] = 1745;
records['456']['rec_id'] = 4456;
records['456']['created_at'] = '';
records['456']['assigned_at'] = '';
records['456']['sys_id'] = 1745;
$.each(records, function(callID, record){
record['campaign_id'] = '1';
record['offset'] = 123;
record['attempt'] = '7';
record['phone'] = '800-123-4567';
record['identity'] = 123;
record['code'] = 'Some Code';
record['notes'] = 'Some notes';
record['completed_by'] = 'Mike A';
record['name'] = null;
record['completed_at'] = "";
});
$('#d').click(function(e){
$('#s').text( JSON.stringify(records) );
});
});
the above code can be found in the following jFiddle https://jsfiddle.net/4632wf5n/
What can I do to convert my object into json string in IE8 with comparability mode?
Although according to Mozilla Developer Network (MDN), JSON.stringify is supported in IE8, in case if it's not, then you can use the polyfill (i.e. if it's not supported by browser, then use custom implementation). If Douglas JSON.js is not working then, MDN also provides a code for the polyfill, and I have copied that here. Just insert it before any other scripts, and JSON.stringify would work in IE6+ browsers where it's not supported.
if (!window.JSON) {
window.JSON = {
parse: function(sJSON) { return eval('(' + sJSON + ')'); },
stringify: (function () {
var toString = Object.prototype.toString;
var isArray = Array.isArray || function (a) { return toString.call(a) === '[object Array]'; };
var escMap = {'"': '\\"', '\\': '\\\\', '\b': '\\b', '\f': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t'};
var escFunc = function (m) { return escMap[m] || '\\u' + (m.charCodeAt(0) + 0x10000).toString(16).substr(1); };
var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
return function stringify(value) {
if (value == null) {
return 'null';
} else if (typeof value === 'number') {
return isFinite(value) ? value.toString() : 'null';
} else if (typeof value === 'boolean') {
return value.toString();
} else if (typeof value === 'object') {
if (typeof value.toJSON === 'function') {
return stringify(value.toJSON());
} else if (isArray(value)) {
var res = '[';
for (var i = 0; i < value.length; i++)
res += (i ? ', ' : '') + stringify(value[i]);
return res + ']';
} else if (toString.call(value) === '[object Object]') {
var tmp = [];
for (var k in value) {
if (value.hasOwnProperty(k))
tmp.push(stringify(k) + ': ' + stringify(value[k]));
}
return '{' + tmp.join(', ') + '}';
}
}
return '"' + value.toString().replace(escRE, escFunc) + '"';
};
})()
};
}

How can I add or update a query string parameter?

With javascript how can I add a query string parameter to the url if not present or if it present, update the current value? I am using jquery for my client side development.
I wrote the following function which accomplishes what I want to achieve:
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
}
Update (2020): URLSearchParams is now supported by all modern browsers.
The URLSearchParams utility can be useful for this in combination with window.location.search. For example:
if ('URLSearchParams' in window) {
var searchParams = new URLSearchParams(window.location.search);
searchParams.set("foo", "bar");
window.location.search = searchParams.toString();
}
Now foo has been set to bar regardless of whether or not it already existed.
However, the above assignment to window.location.search will cause a page load, so if that's not desirable use the History API as follows:
if ('URLSearchParams' in window) {
var searchParams = new URLSearchParams(window.location.search)
searchParams.set("foo", "bar");
var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
history.pushState(null, '', newRelativePathQuery);
}
Now you don't need to write your own regex or logic to handle the possible existence of query strings.
However, browser support is poor as it's currently experimental and only in use in recent versions of Chrome, Firefox, Safari, iOS Safari, Android Browser, Android Chrome and Opera. Use with a polyfill if you do decide to use it.
I have expanded the solution and combined it with another that I found to replace/update/remove the querystring parameters based on the users input and taking the urls anchor into consideration.
Not supplying a value will remove the parameter, supplying one will add/update the parameter. If no URL is supplied, it will be grabbed from window.location
function UpdateQueryString(key, value, url) {
if (!url) url = window.location.href;
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
hash;
if (re.test(url)) {
if (typeof value !== 'undefined' && value !== null) {
return url.replace(re, '$1' + key + "=" + value + '$2$3');
}
else {
hash = url.split('#');
url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
url += '#' + hash[1];
}
return url;
}
}
else {
if (typeof value !== 'undefined' && value !== null) {
var separator = url.indexOf('?') !== -1 ? '&' : '?';
hash = url.split('#');
url = hash[0] + separator + key + '=' + value;
if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
url += '#' + hash[1];
}
return url;
}
else {
return url;
}
}
}
Update
There was a bug when removing the first parameter in the querystring, I have reworked the regex and test to include a fix.
Second Update
As suggested by #JarónBarends - Tweak value check to check against undefined and null to allow setting 0 values
Third Update
There was a bug where removing a querystring variable directly before a hashtag would lose the hashtag symbol which has been fixed
Fourth Update
Thanks #rooby for pointing out a regex optimization in the first RegExp object.
Set initial regex to ([?&]) due to issue with using (\?|&) found by #YonatanKarni
Fifth Update
Removing declaring hash var in if/else statement
Based on #amateur's answer (and now incorporating the fix from #j_walker_dev comment), but taking into account the comment about hash tags in the url I use the following:
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
} else {
var hash = '';
if( uri.indexOf('#') !== -1 ){
hash = uri.replace(/.*#/, '#');
uri = uri.replace(/#.*/, '');
}
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
return uri + separator + key + "=" + value + hash;
}
}
Edited to fix [?|&] in regex which should of course be [?&] as pointed out in the comments
Edit: Alternative version to support removing URL params as well. I have used value === undefined as the way to indicate removal. Could use value === false or even a separate input param as wanted.
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
if( value === undefined ) {
if (uri.match(re)) {
return uri.replace(re, '$1$2').replace(/[?&]$/, '').replaceAll(/([?&])&+/g, '$1').replace(/[?&]#/, '#');
} else {
return uri;
}
} else {
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
} else {
var hash = '';
if( uri.indexOf('#') !== -1 ){
hash = uri.replace(/.*#/, '#');
uri = uri.replace(/#.*/, '');
}
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
return uri + separator + key + "=" + value + hash;
}
}
}
See it in action at https://jsfiddle.net/cdt16wex/
You can use the browser's native URL API to do this in a fairly simple way, where key and value are your parameter name and parameter value respectively.
const url = new URL(location.href);
url.searchParams.set(key, value);
history.pushState(null, '', url);
This will preserve everything about the URL and only change or add the one query param. You can also use replaceState instead of pushState if you don't want it to create a new browser history entry.
Thanks to modern javascript, node.js and browsers support, we can get out of 3rd-party library whirlpool (jquery, query-string etc.) and DRY ourselves.
Here are javascript(node.js) and typescript version for a function that adds or updates query params of given url:
Javascript
const getUriWithParam = (baseUrl, params) => {
const Url = new URL(baseUrl);
const urlParams = new URLSearchParams(Url.search);
for (const key in params) {
if (params[key] !== undefined) {
urlParams.set(key, params[key]);
}
}
Url.search = urlParams.toString();
return Url.toString();
};
console.info('expected: https://example.com/?foo=bar');
console.log(getUriWithParam("https://example.com", {foo: "bar"}));
console.info('expected: https://example.com/slug?foo=bar#hash');
console.log(getUriWithParam("https://example.com/slug#hash", {foo: "bar"}));
console.info('expected: https://example.com/?bar=baz&foo=bar');
console.log(getUriWithParam("https://example.com?bar=baz", {foo: "bar"}));
console.info('expected: https://example.com/?foo=baz&bar=baz');
console.log(getUriWithParam("https://example.com?foo=bar&bar=baz", {foo: "baz"}));
Typescript
const getUriWithParam = (
baseUrl: string,
params: Record<string, any>
): string => {
const Url = new URL(baseUrl);
const urlParams: URLSearchParams = new URLSearchParams(Url.search);
for (const key in params) {
if (params[key] !== undefined) {
urlParams.set(key, params[key]);
}
}
Url.search = urlParams.toString();
return Url.toString();
};
For React Native
URL is not implemented in React Native. So you have to install react-native-url-polyfill beforehand.
For object params
See the second solution in this answer
Here is my library to do that: https://github.com/Mikhus/jsurl
var u = new Url;
u.query.param='value'; // adds or replaces the param
alert(u)
If it's not set or want to update with a new value you can use:
window.location.search = 'param=value'; // or param=new_value
This is in simple Javascript, by the way.
EDIT
You may want to try using the jquery query-object plugin
window.location.search =
jQuery.query.set("param", 5);
I realize this question is old and has been answered to death, but here's my stab at it. I'm trying to reinvent the wheel here because I was using the currently accepted answer and the mishandling of URL fragments recently bit me in a project.
The function is below. It's quite long, but it was made to be as resilient as possible. I would love suggestions for shortening/improving it. I put together a small jsFiddle test suite for it (or other similar functions). If a function can pass every one of the tests there, I say it's probably good to go.
Update: I came across a cool function for using the DOM to parse URLs, so I incorporated that technique here. It makes the function shorter and more reliable. Props to the author of that function.
/**
* Add or update a query string parameter. If no URI is given, we use the current
* window.location.href value for the URI.
*
* Based on the DOM URL parser described here:
* http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
*
* #param (string) uri Optional: The URI to add or update a parameter in
* #param (string) key The key to add or update
* #param (string) value The new value to set for key
*
* Tested on Chrome 34, Firefox 29, IE 7 and 11
*/
function update_query_string( uri, key, value ) {
// Use window URL if no query string is provided
if ( ! uri ) { uri = window.location.href; }
// Create a dummy element to parse the URI with
var a = document.createElement( 'a' ),
// match the key, optional square brackets, an equals sign or end of string, the optional value
reg_ex = new RegExp( key + '((?:\\[[^\\]]*\\])?)(=|$)(.*)' ),
// Setup some additional variables
qs,
qs_len,
key_found = false;
// Use the JS API to parse the URI
a.href = uri;
// If the URI doesn't have a query string, add it and return
if ( ! a.search ) {
a.search = '?' + key + '=' + value;
return a.href;
}
// Split the query string by ampersands
qs = a.search.replace( /^\?/, '' ).split( /&(?:amp;)?/ );
qs_len = qs.length;
// Loop through each query string part
while ( qs_len > 0 ) {
qs_len--;
// Remove empty elements to prevent double ampersands
if ( ! qs[qs_len] ) { qs.splice(qs_len, 1); continue; }
// Check if the current part matches our key
if ( reg_ex.test( qs[qs_len] ) ) {
// Replace the current value
qs[qs_len] = qs[qs_len].replace( reg_ex, key + '$1' ) + '=' + value;
key_found = true;
}
}
// If we haven't replaced any occurrences above, add the new parameter and value
if ( ! key_found ) { qs.push( key + '=' + value ); }
// Set the new query string
a.search = '?' + qs.join( '&' );
return a.href;
}
window.location.search is read/write.
However - modifying the query string will redirect the page you're on and cause a refresh from the server.
If what you're attempting to do is maintain client side state (and potentially make it bookmark-able), you'll want to modify the URL hash instead of the query string, which keeps you on the same page (window.location.hash is read/write). This is how web sites like twitter.com do this.
You'll also want the back button to work, you'll have to bind javascript events to the hash change event, a good plugin for that is http://benalman.com/projects/jquery-hashchange-plugin/
Here's my approach: The location.params() function (shown below) can be used as a getter or setter. Examples:
Given the URL is http://example.com/?foo=bar&baz#some-hash,
location.params() will return an object with all the query parameters: {foo: 'bar', baz: true}.
location.params('foo') will return 'bar'.
location.params({foo: undefined, hello: 'world', test: true}) will change the URL to http://example.com/?baz&hello=world&test#some-hash.
Here is the params() function, which can optionally be assigned to the window.location object.
location.params = function(params) {
var obj = {}, i, parts, len, key, value;
if (typeof params === 'string') {
value = location.search.match(new RegExp('[?&]' + params + '=?([^&]*)[&#$]?'));
return value ? value[1] : undefined;
}
var _params = location.search.substr(1).split('&');
for (i = 0, len = _params.length; i < len; i++) {
parts = _params[i].split('=');
if (! parts[0]) {continue;}
obj[parts[0]] = parts[1] || true;
}
if (typeof params !== 'object') {return obj;}
for (key in params) {
value = params[key];
if (typeof value === 'undefined') {
delete obj[key];
} else {
obj[key] = value;
}
}
parts = [];
for (key in obj) {
parts.push(key + (obj[key] === true ? '' : '=' + obj[key]));
}
location.search = parts.join('&');
};
I know this is quite old but i want to fires my working version in here.
function addOrUpdateUrlParam(uri, paramKey, paramVal) {
var re = new RegExp("([?&])" + paramKey + "=[^&#]*", "i");
if (re.test(uri)) {
uri = uri.replace(re, '$1' + paramKey + "=" + paramVal);
} else {
var separator = /\?/.test(uri) ? "&" : "?";
uri = uri + separator + paramKey + "=" + paramVal;
}
return uri;
}
jQuery(document).ready(function($) {
$('#paramKey,#paramValue').on('change', function() {
if ($('#paramKey').val() != "" && $('#paramValue').val() != "") {
$('#uri').val(addOrUpdateUrlParam($('#uri').val(), $('#paramKey').val(), $('#paramValue').val()));
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input style="width:100%" type="text" id="uri" value="http://www.example.com/text.php">
<label style="display:block;">paramKey
<input type="text" id="paramKey">
</label>
<label style="display:block;">paramValue
<input type="text" id="paramValue">
</label>
NOTE This is a modified version of #elreimundo
It's so simple with URLSearchParams, supported in all modern browsers (caniuse).
let p = new URLSearchParams();
p.set("foo", "bar");
p.set("name", "Jack & Jill?");
console.log("http://example.com/?" + p.toString());
If you want to modify the existing URL, construct the object like this: new URLSearchParams(window.location.search) and assign the string to window.location.search.
My take from here (compatible with "use strict"; does not really use jQuery):
function decodeURIParams(query) {
if (query == null)
query = window.location.search;
if (query[0] == '?')
query = query.substring(1);
var params = query.split('&');
var result = {};
for (var i = 0; i < params.length; i++) {
var param = params[i];
var pos = param.indexOf('=');
if (pos >= 0) {
var key = decodeURIComponent(param.substring(0, pos));
var val = decodeURIComponent(param.substring(pos + 1));
result[key] = val;
} else {
var key = decodeURIComponent(param);
result[key] = true;
}
}
return result;
}
function encodeURIParams(params, addQuestionMark) {
var pairs = [];
for (var key in params) if (params.hasOwnProperty(key)) {
var value = params[key];
if (value != null) /* matches null and undefined */ {
pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value))
}
}
if (pairs.length == 0)
return '';
return (addQuestionMark ? '?' : '') + pairs.join('&');
}
//// alternative to $.extend if not using jQuery:
// function mergeObjects(destination, source) {
// for (var key in source) if (source.hasOwnProperty(key)) {
// destination[key] = source[key];
// }
// return destination;
// }
function navigateWithURIParams(newParams) {
window.location.search = encodeURIParams($.extend(decodeURIParams(), newParams), true);
}
Example usage:
// add/update parameters
navigateWithURIParams({ foo: 'bar', boz: 42 });
// remove parameter
navigateWithURIParams({ foo: null });
// submit the given form by adding/replacing URI parameters (with jQuery)
$('.filter-form').submit(function(e) {
e.preventDefault();
navigateWithURIParams(decodeURIParams($(this).serialize()));
});
Based on the answer #ellemayo gave, I came up with the following solution that allows for disabling of the hash tag if desired:
function updateQueryString(key, value, options) {
if (!options) options = {};
var url = options.url || location.href;
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"), hash;
hash = url.split('#');
url = hash[0];
if (re.test(url)) {
if (typeof value !== 'undefined' && value !== null) {
url = url.replace(re, '$1' + key + "=" + value + '$2$3');
} else {
url = url.replace(re, '$1$3').replace(/(&|\?)$/, '');
}
} else if (typeof value !== 'undefined' && value !== null) {
var separator = url.indexOf('?') !== -1 ? '&' : '?';
url = url + separator + key + '=' + value;
}
if ((typeof options.hash === 'undefined' || options.hash) &&
typeof hash[1] !== 'undefined' && hash[1] !== null)
url += '#' + hash[1];
return url;
}
Call it like this:
updateQueryString('foo', 'bar', {
url: 'http://my.example.com#hash',
hash: false
});
Results in:
http://my.example.com?foo=bar
Here is a shorter version that takes care of
query with or without a given parameter
query with multiple parameter values
query containing hash
Code:
var setQueryParameter = function(uri, key, value) {
var re = new RegExp("([?&])("+ key + "=)[^&#]*", "g");
if (uri.match(re))
return uri.replace(re, '$1$2' + value);
// need to add parameter to URI
var paramString = (uri.indexOf('?') < 0 ? "?" : "&") + key + "=" + value;
var hashIndex = uri.indexOf('#');
if (hashIndex < 0)
return uri + paramString;
else
return uri.substring(0, hashIndex) + paramString + uri.substring(hashIndex);
}
The regex description can be found here.
NOTE: This solution is based on #amateur answer, but with many improvements.
Code that appends a list of parameters to an existing url using ES6 and jQuery:
class UrlBuilder {
static appendParametersToUrl(baseUrl, listOfParams) {
if (jQuery.isEmptyObject(listOfParams)) {
return baseUrl;
}
const newParams = jQuery.param(listOfParams);
let partsWithHash = baseUrl.split('#');
let partsWithParams = partsWithHash[0].split('?');
let previousParams = '?' + ((partsWithParams.length === 2) ? partsWithParams[1] + '&' : '');
let previousHash = (partsWithHash.length === 2) ? '#' + partsWithHash[1] : '';
return partsWithParams[0] + previousParams + newParams + previousHash;
}
}
Where listOfParams is like
const listOfParams = {
'name_1': 'value_1',
'name_2': 'value_2',
'name_N': 'value_N',
};
Example of Usage:
UrlBuilder.appendParametersToUrl(urlBase, listOfParams);
Fast tests:
url = 'http://hello.world';
console.log('=> ', UrlParameters.appendParametersToUrl(url, null));
// Output: http://hello.world
url = 'http://hello.world#h1';
console.log('=> ', UrlParameters.appendParametersToUrl(url, null));
// Output: http://hello.world#h1
url = 'http://hello.world';
params = {'p1': 'v1', 'p2': 'v2'};
console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
// Output: http://hello.world?p1=v1&p2=v2
url = 'http://hello.world?p0=v0';
params = {'p1': 'v1', 'p2': 'v2'};
console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
// Output: http://hello.world?p0=v0&p1=v1&p2=v2
url = 'http://hello.world#h1';
params = {'p1': 'v1', 'p2': 'v2'};
console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
// Output: http://hello.world?p1=v1&p2=v2#h1
url = 'http://hello.world?p0=v0#h1';
params = {'p1': 'v1', 'p2': 'v2'};
console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
// Output: http://hello.world?p0=v0&p1=v1&p2=v2#h1
To give an code example for modifying window.location.search as suggested by Gal and tradyblix:
var qs = window.location.search || "?";
var param = key + "=" + value; // remember to URI encode your parameters
if (qs.length > 1) {
// more than just the question mark, so append with ampersand
qs = qs + "&";
}
qs = qs + param;
window.location.search = qs;
A different approach without using regular expressions. Supports 'hash' anchors at the end of the url as well as multiple question mark charcters (?). Should be slightly faster than the regular expression approach.
function setUrlParameter(url, key, value) {
var parts = url.split("#", 2), anchor = parts.length > 1 ? "#" + parts[1] : '';
var query = (url = parts[0]).split("?", 2);
if (query.length === 1)
return url + "?" + key + "=" + value + anchor;
for (var params = query[query.length - 1].split("&"), i = 0; i < params.length; i++)
if (params[i].toLowerCase().startsWith(key.toLowerCase() + "="))
return params[i] = key + "=" + value, query[query.length - 1] = params.join("&"), query.join("?") + anchor;
return url + "&" + key + "=" + value + anchor
}
Use this function to add, remove and modify query string parameter from URL based on jquery
/**
#param String url
#param object param {key: value} query parameter
*/
function modifyURLQuery(url, param){
var value = {};
var query = String(url).split('?');
if (query[1]) {
var part = query[1].split('&');
for (i = 0; i < part.length; i++) {
var data = part[i].split('=');
if (data[0] && data[1]) {
value[data[0]] = data[1];
}
}
}
value = $.extend(value, param);
// Remove empty value
for (i in value){
if(!value[i]){
delete value[i];
}
}
// Return url with modified parameter
if(value){
return query[0] + '?' + $.param(value);
} else {
return query[0];
}
}
Add new and modify existing parameter to url
var new_url = modifyURLQuery("http://google.com?foo=34", {foo: 50, bar: 45});
// Result: http://google.com?foo=50&bar=45
Remove existing
var new_url = modifyURLQuery("http://google.com?foo=50&bar=45", {bar: null});
// Result: http://google.com?foo=50
Here's my slightly different approach to this, written as an excercise
function addOrChangeParameters( url, params )
{
let splitParams = {};
let splitPath = (/(.*)[?](.*)/).exec(url);
if ( splitPath && splitPath[2] )
splitPath[2].split("&").forEach( k => { let d = k.split("="); splitParams[d[0]] = d[1]; } );
let newParams = Object.assign( splitParams, params );
let finalParams = Object.keys(newParams).map( (a) => a+"="+newParams[a] ).join("&");
return splitPath ? (splitPath[1] + "?" + finalParams) : (url + "?" + finalParams);
}
usage:
const url = "http://testing.com/path?empty&value1=test&id=3";
addOrChangeParameters( url, {value1:1, empty:"empty", new:0} )
"http://testing.com/path?empty=empty&value1=1&id=3&new=0"
This answer is just a small tweak of ellemayo's answer. It will automatically update the URL instead of just returning the updated string.
function _updateQueryString(key, value, url) {
if (!url) url = window.location.href;
let updated = ''
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
hash;
if (re.test(url)) {
if (typeof value !== 'undefined' && value !== null) {
updated = url.replace(re, '$1' + key + "=" + value + '$2$3');
}
else {
hash = url.split('#');
url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
url += '#' + hash[1];
}
updated = url;
}
}
else {
if (typeof value !== 'undefined' && value !== null) {
var separator = url.indexOf('?') !== -1 ? '&' : '?';
hash = url.split('#');
url = hash[0] + separator + key + '=' + value;
if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
url += '#' + hash[1];
}
updated = url;
}
else {
updated = url;
}
}
window.history.replaceState({ path: updated }, '', updated);
}
Java script code to find a specific query string and replace its value *
('input.letter').click(function () {
//0- prepare values
var qsTargeted = 'letter=' + this.value; //"letter=A";
var windowUrl = '';
var qskey = qsTargeted.split('=')[0];
var qsvalue = qsTargeted.split('=')[1];
//1- get row url
var originalURL = window.location.href;
//2- get query string part, and url
if (originalURL.split('?').length > 1) //qs is exists
{
windowUrl = originalURL.split('?')[0];
var qs = originalURL.split('?')[1];
//3- get list of query strings
var qsArray = qs.split('&');
var flag = false;
//4- try to find query string key
for (var i = 0; i < qsArray.length; i++) {
if (qsArray[i].split('=').length > 0) {
if (qskey == qsArray[i].split('=')[0]) {
//exists key
qsArray[i] = qskey + '=' + qsvalue;
flag = true;
break;
}
}
}
if (!flag)// //5- if exists modify,else add
{
qsArray.push(qsTargeted);
}
var finalQs = qsArray.join('&');
//6- prepare final url
window.location = windowUrl + '?' + finalQs;
}
else {
//6- prepare final url
//add query string
window.location = originalURL + '?' + qsTargeted;
}
})
});
Here's an alternative method using the inbuilt properties of the anchor HTML element:
Handles multi-valued parameters.
No risk of modifying the # fragment, or anything other than the query string itself.
May be a little easier to read? But it is longer.
var a = document.createElement('a'),
getHrefWithUpdatedQueryString = function(param, value) {
return updatedQueryString(window.location.href, param, value);
},
updatedQueryString = function(url, param, value) {
/*
A function which modifies the query string
by setting one parameter to a single value.
Any other instances of parameter will be removed/replaced.
*/
var fragment = encodeURIComponent(param) +
'=' + encodeURIComponent(value);
a.href = url;
if (a.search.length === 0) {
a.search = '?' + fragment;
} else {
var didReplace = false,
// Remove leading '?'
parts = a.search.substring(1)
// Break into pieces
.split('&'),
reassemble = [],
len = parts.length;
for (var i = 0; i < len; i++) {
var pieces = parts[i].split('=');
if (pieces[0] === param) {
if (!didReplace) {
reassemble.push('&' + fragment);
didReplace = true;
}
} else {
reassemble.push(parts[i]);
}
}
if (!didReplace) {
reassemble.push('&' + fragment);
}
a.search = reassemble.join('&');
}
return a.href;
};
if you want to set multiple parameters at once:
function updateQueryStringParameters(uri, params) {
for(key in params){
var value = params[key],
re = new RegExp("([?&])" + key + "=.*?(&|$)", "i"),
separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
uri = uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
uri = uri + separator + key + "=" + value;
}
}
return uri;
}
same function as #amateur's
if jslint gives you an error add this after the for loop
if(params.hasOwnProperty(key))
There are a lot of awkward and unnecessarily complicated answers on this page. The highest rated one, #amateur's, is quite good, although it has a bit of unnecessary fluff in the RegExp. Here is a slightly more optimal solution with cleaner RegExp and a cleaner replace call:
function updateQueryStringParamsNoHash(uri, key, value) {
var re = new RegExp("([?&])" + key + "=[^&]*", "i");
return re.test(uri)
? uri.replace(re, '$1' + key + "=" + value)
: uri + separator + key + "=" + value
;
}
As an added bonus, if uri is not a string, you won't get errors for trying to call match or replace on something that may not implement those methods.
And if you want to handle the case of a hash (and you've already done a check for properly formatted HTML), you can leverage the existing function instead of writing a new function containing the same logic:
function updateQueryStringParams(url, key, value) {
var splitURL = url.split('#');
var hash = splitURL[1];
var uri = updateQueryStringParamsNoHash(splitURL[0]);
return hash == null ? uri : uri + '#' + hash;
}
Or you can make some slight changes to #Adam's otherwise excellent answer:
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=[^&#]*", "i");
if (re.test(uri)) {
return uri.replace(re, '$1' + key + "=" + value);
} else {
var matchData = uri.match(/^([^#]*)(#.*)?$/);
var separator = /\?/.test(uri) ? "&" : "?";
return matchData[0] + separator + key + "=" + value + (matchData[1] || '');
}
}
This should serve the purpose:
function updateQueryString(url, key, value) {
var arr = url.split("#");
var url = arr[0];
var fragmentId = arr[1];
var updatedQS = "";
if (url.indexOf("?") == -1) {
updatedQS = encodeURIComponent(key) + "=" + encodeURIComponent(value);
}
else {
updatedQS = addOrModifyQS(url.substring(url.indexOf("?") + 1), key, value);
}
url = url.substring(0, url.indexOf("?")) + "?" + updatedQS;
if (typeof fragmentId !== 'undefined') {
url = url + "#" + fragmentId;
}
return url;
}
function addOrModifyQS(queryStrings, key, value) {
var oldQueryStrings = queryStrings.split("&");
var newQueryStrings = new Array();
var isNewKey = true;
for (var i in oldQueryStrings) {
var currItem = oldQueryStrings[i];
var searchKey = key + "=";
if (currItem.indexOf(searchKey) != -1) {
currItem = encodeURIComponent(key) + "=" + encodeURIComponent(value);
isNewKey = false;
}
newQueryStrings.push(currItem);
}
if (isNewKey) {
newQueryStrings.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
}
return newQueryStrings.join("&");
}
By using jQuery we can do like below
var query_object = $.query_string;
query_object["KEY"] = "VALUE";
var new_url = window.location.pathname + '?'+$.param(query_object)
In variable new_url we will have new query parameters.
Reference: http://api.jquery.com/jquery.param/
I wanted something that:
Uses the browser's native URL API
Can add, update, get, or delete
Expects the query string after the hash e.g. for single page applications
function queryParam(options = {}) {
var defaults = {
method: 'set',
url: window.location.href,
key: undefined,
value: undefined,
}
for (var prop in defaults) {
options[prop] = typeof options[prop] !== 'undefined' ? options[prop] : defaults[prop]
}
const existing = (options.url.lastIndexOf('?') > options.url.lastIndexOf('#')) ? options.url.substr(options.url.lastIndexOf('?') + 1) : ''
const query = new URLSearchParams(existing)
if (options.method === 'set') {
query.set(options.key, options.value)
return `${options.url.replace(`?${existing}`, '')}?${query.toString()}`
} else if (options.method === 'get') {
const val = query.get(options.key)
let result = val === null ? val : val.toString()
return result
} else if (options.method === 'delete') {
query.delete(options.key)
let result = `${options.url.replace(`?${existing}`, '')}?${query.toString()}`
const lastChar = result.charAt(result.length - 1)
if (lastChar === '?') {
result = `${options.url.replace(`?${existing}`, '')}`
}
return result
}
}
// Usage:
let url = 'https://example.com/sandbox/#page/'
url = queryParam({
url,
method: 'set',
key: 'my-first-param',
value: 'me'
})
console.log(url)
url = queryParam({
url,
method: 'set',
key: 'my-second-param',
value: 'you'
})
console.log(url)
url = queryParam({
url,
method: 'set',
key: 'my-second-param',
value: 'whomever'
})
console.log(url)
url = queryParam({
url,
method: 'delete',
key: 'my-first-param'
})
console.log(url)
const mySecondParam = queryParam({
url,
method: 'get',
key: 'my-second-param',
})
console.log(mySecondParam)
url = queryParam({
url,
method: 'delete',
key: 'my-second-param'
})
console.log(url)
Yeah I had an issue where my querystring would overflow and duplicate, but this was due to my own sluggishness. so I played a bit and worked up some js jquery(actualy sizzle) and C# magick.
So i just realized that after the server has done with the passed values, the values doesn't matter anymore, there is no reuse, if the client wanted to do the same thing evidently it will always be a new request, even if its the same parameters being passed. And thats all clientside, so some caching/cookies etc could be cool in that regards.
JS:
$(document).ready(function () {
$('#ser').click(function () {
SerializeIT();
});
function SerializeIT() {
var baseUrl = "";
baseUrl = getBaseUrlFromBrowserUrl(window.location.toString());
var myQueryString = "";
funkyMethodChangingStuff(); //whatever else before serializing and creating the querystring
myQueryString = $('#fr2').serialize();
window.location.replace(baseUrl + "?" + myQueryString);
}
function getBaseUrlFromBrowserUrl(szurl) {
return szurl.split("?")[0];
}
function funkyMethodChangingStuff(){
//do stuff to whatever is in fr2
}
});
HTML:
<div id="fr2">
<input type="text" name="qURL" value="http://somewhere.com" />
<input type="text" name="qSPart" value="someSearchPattern" />
</div>
<button id="ser">Serialize! and go play with the server.</button>
C#:
using System.Web;
using System.Text;
using System.Collections.Specialized;
public partial class SomeCoolWebApp : System.Web.UI.Page
{
string weburl = string.Empty;
string partName = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
string loadurl = HttpContext.Current.Request.RawUrl;
string querySZ = null;
int isQuery = loadurl.IndexOf('?');
if (isQuery == -1) {
//If There Was no Query
}
else if (isQuery >= 1) {
querySZ = (isQuery < loadurl.Length - 1) ? loadurl.Substring(isQuery + 1) : string.Empty;
string[] getSingleQuery = querySZ.Split('?');
querySZ = getSingleQuery[0];
NameValueCollection qs = null;
qs = HttpUtility.ParseQueryString(querySZ);
weburl = qs["qURL"];
partName = qs["qSPart"];
//call some great method thisPageRocks(weburl,partName); or whatever.
}
}
}
Okay criticism is welcome (this was a nightly concoction so feel free to note adjustments). If this helped at all, thumb it up, Happy Coding.
No duplicates, each request as unique as you modified it, and due to how this is structured,easy to add more queries dynamicaly from wthin the dom.

Geolocations with javascript

I'm working on a script to get the Geolocations (Lat, lon) that I can use to center my instance of google maps. For now i work with 2 possible technologies. One is the google.loader.ClientLocation object. I haven't tested this one yet because it returns null for me. I think because I'm not living on a regular location (Willemstad, Curacao using a wireless internet connection. So my modem is wireless.).
Therefore I made a backup plan using navigator.geolocation. This works great in Chrome, but firefox gives a timeout and it doesn't work at all in IE.
Does anyone know a good alternative method to get the users geolocation, or does anyone have recommendation on my code how it can become more stable.
I set a timeout for navigator.geolocation because I don't want my users to wait for more as 5 seconds. Increasing the timeout does not improve the reliability of firefox.
function init_tracker_map() {
var latitude;
var longitude;
if(google.loader.ClientLocation) {
latitude = (google.loader.ClientLocation.latitude);
longitude = (google.loader.ClientLocation.longitude);
buildMap(latitude, longitude);
}
else if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
latitude = (position.coords.latitude);
longitude = (position.coords.longitude);
buildMap(latitude, longitude);
},
function errorCallback(error) {
useDefaultLatLon();
},
{
enableHighAccuracy:false,
maximumAge:Infinity,
timeout:5000
}
);
}
else {
useDefaultLatLon();
}
}
function useDefaultLatLon() {
latitude = (51.81540697949437);
longitude = (5.72113037109375);
buildMap(latitude, longitude);
}
ps. I'm aware there are more questions like this on SO but couldn't find a clear answer. I'm hoping that people made some new discovery's.
Update:
Tried google gears aswell. Succesfull in chrome again. Fails in FF and IE.
var geo = google.gears.factory.create('beta.geolocation');
if(geo) {
function updatePosition(position) {
alert('Current lat/lon is: ' + position.latitude + ',' + position.longitude);
}
function handleError(positionError) {
alert('Attempt to get location failed: ' + positionError.message);
}
geo.getCurrentPosition(updatePosition, handleError);
}
Update 2: navigator.geolocation works fine in FF from my work location.
Final Result
This works great. Get an api key from ipinfodb.org
var Geolocation = new geolocate(false, true);
Geolocation.checkcookie(function() {
alert('Visitor latitude code : ' + Geolocation.getField('Latitude'));
alert('Visitor Longitude code : ' + Geolocation.getField('Longitude'));
});
function geolocate(timezone, cityPrecision) {
alert("Using IPInfoDB");
var key = 'your api code';
var api = (cityPrecision) ? "ip_query.php" : "ip_query_country.php";
var domain = 'api.ipinfodb.com';
var version = 'v2';
var url = "http://" + domain + "/" + version + "/" + api + "?key=" + key + "&output=json" + ((timezone) ? "&timezone=true" : "&timezone=false" ) + "&callback=?";
var geodata;
var JSON = JSON || {};
var callback = function() {
alert("lol");
}
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string") obj = '"'+obj+'"';
return String(obj);
}
else {
// recurse array or object
var n, v, json = [], arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n]; t = typeof(v);
if (t == "string") v = '"'+v+'"';
else if (t == "object" && v !== null) v = JSON.stringify(v);
json.push((arr ? "" : '"' + n + '":') + String(v));
}
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
};
// implement JSON.parse de-serialization
JSON.parse = JSON.parse || function (str) {
if (str === "") str = '""';
eval("var p=" + str + ";");
return p;
};
// Check if cookie already exist. If not, query IPInfoDB
this.checkcookie = function(callback) {
geolocationCookie = getCookie('geolocation');
if (!geolocationCookie) {
getGeolocation(callback);
}
else {
geodata = JSON.parse(geolocationCookie);
callback();
}
}
// Return a geolocation field
this.getField = function(field) {
try {
return geodata[field];
} catch(err) {}
}
// Request to IPInfoDB
function getGeolocation(callback) {
try {
$.getJSON(url,
function(data){
if (data['Status'] == 'OK') {
geodata = data;
JSONString = JSON.stringify(geodata);
setCookie('geolocation', JSONString, 365);
callback();
}
});
} catch(err) {}
}
// Set the cookie
function setCookie(c_name, value, expire) {
var exdate=new Date();
exdate.setDate(exdate.getDate()+expire);
document.cookie = c_name+ "=" +escape(value) + ((expire==null) ? "" : ";expires="+exdate.toGMTString());
}
// Get the cookie content
function getCookie(c_name) {
if (document.cookie.length > 0 ) {
c_start=document.cookie.indexOf(c_name + "=");
if (c_start != -1){
c_start=c_start + c_name.length+1;
c_end=document.cookie.indexOf(";",c_start);
if (c_end == -1) {
c_end=document.cookie.length;
}
return unescape(document.cookie.substring(c_start,c_end));
}
}
return '';
}
}
geolocation using javascript will work with HTML 5 compliant browsers, so that leaves out IE completely.
Your alternative is to use the IP address to ascertain the approximate lat/long.
Using this alternative method and assuming you find a provider with an accurate and complete lat/long-to-IP mapping, you will only get the lat/long of the ISP (or the nearest point where the ISP connects to the internet).
Hope this resets your expectation (about location-accuracy)
you should read this Which Devices Support Javascript Geolocation via navigator.geolocation?
I had a similar problem and, for browsers without geolocation, went with server-side location based on the user's IP.
Two free geolocation services are:
http://www.maxmind.com/app/geolitecity
http://www.hostip.info/
I found maxmind to me much more accurate.
If it's possible within your project you could query the location before rendering the page, or perform an ajax call to query the location.

Categories

Resources