I have the following problem:
I have a string and I need to replace for different regex parts.
therefore I want to loop over it:
In my case its a URL and I want to empty for specific parameters:
cleanURL(url, params) {
params.forEach((param) => {
url = this.updateUrlParameter(url, param, '');
});
Whereas I have:
updateUrlParameter(url, param, value) {
const regex = new RegExp(`(${param}=)[^&]+`);
const newURL = url.replace(regex, `$1${value}`);
return newURL;
}
This is the only way I got it to work, but now I am reassigning a function parameter.
this is not what I want.
My problem is, that
cleanURL(url, params) {
params.forEach((param) => {
this.updateUrlParameter(url, param, '');
});
}
Would always for each iteration pass the SAME url into the loop. And I end up with just the last replacement.
I somehow would have to pass a changed string into the next loop iteration.
How could I achieve this?
Maybe into this direction?
With somehow nesting and calling the function again?
while(outerI--){
(function(i){
i+=1;//doesn't affect outerI and you wanted 1-length so we add one.
//crap inside your forEach loop but without the i++
})(outerI)
}
which I found here:
.forEach loop: use variable
Woudl be very glad for a hint here.
thank you
Cheers
Reassigning the function parameter would be perfectly fine in this use-case.
If you really don't want to reassign a function parameter for whatever reason, you can introduce a new variable to store the updated URL for you.
cleanURL(url, params) {
let newUrl = url;
params.forEach((param) => {
newUrl = this.updateUrlParameter(newUrl, param, '');
});
return newUrl;
}
If you don't want to mutate parameter, use a temporary variable to hold the result.
function updateUrlParameter(url, param, value) {
const newURL = url + param;
return newURL;
}
function cleanURL(url, params) {
let temp = url;
params.forEach((param) => {
temp = updateUrlParameter(temp, param, '');
});
return temp;
}
const params = [1, 2, 3, 4, 5];
const url = 'string';
console.log(cleanURL(url, params));
The String.prototype.replace does not modify the original string, rather it creates a new string.
If you update your clearUrl method to reassign url in each iteration you should get replacements for all the parameters
cleanURL(url, params) {
params.forEach((param) => {
url = this.updateUrlParameter(url, param, '');
});
}
I also found a way in the meantime:
cleanURL(url, params) {
const paramsLength = params.length;
const cleanURL = url;
const recursive = (i, originalURL) => {
this.log('i: ', i);
this.log('originalURL: ', originalURL);
if (i > 0) {
const changedURL = this.updateUrlParameter(originalURL, params[i - 1], '');
return recursive(i - 1, changedURL);
}
return originalURL;
};
// this.log('url: ', url);
return recursive(paramsLength, cleanURL);
}
updateUrlParameter(url, param, value) {
const regex = new RegExp(`(${param}=)[^&]+`);
// this.log('regex: ', regex);
const newURL = url.replace(regex, `$1${value}`);
// this.log('newURL: ', newURL);
return newURL;
}
Thoughts on that?
Related
I want to check if there is a hash in the url :
This should return true:
domain.com/balbla#hash
This should return false:
domain.com/balbla
So I use URI.js to grab the hash
var uriFragment = new URI(window.location.href).fragment();
if (uriFragment.length) {
console.log('yep')
} else {
console.log('nope')
}
But that never returns nope even if there is no hash in the url.
Why not using directly location.hash
if(location.hash.length > 0) {
console.log('yep')
}else {
console.log('nop')
}
Below code will give the list of hash tags in array format.
var hash = window.location.hash;
return result = hash.split('#').reduce(function (result, item) {
var parts = item.split('=');
result[parts[0]] = parts[1];
return result;
}, {});
I'm writing this function to use in my angular app to evaluate ng-src in an ng-repeat list. I need to make the calls synchronous so that the value is correct each time the function is called. The problem is:
Why does this code return a value:
var storage = firebase.storage();
var returnVal; //causes sync issues
var getImageUrl = function (time) {
storage.ref('images/' + time + '.jpg').getDownloadURL().then(function (url) {
returnVal = url;
});
return returnVal;
};
But this doesn't work:
var storage = firebase.storage();
var getImageUrl = function (time) {
var returnVal; //so that this is specific to the function
storage.ref('images/' + time + '.jpg').getDownloadURL().then(function (url) {
returnVal = url; //I simply want to return the value of 'url'
});
return returnVal;
};
Any ideas how I can make the getImageUrl() function return the url from the .then?
This is the documentation link: https://firebase.google.com/docs/storage/web/download-files
Eventually I'll turn this into a $scope function to use similar to this:
<div ng-repeat="message in messages">
<img ng-src="{{ getImageUrl(message.time) }}">
</div>
Neither variation of your function will ever return a value that isn't null or undefined. You are performing an asynchronous call that will not wait for the result before continuing to execute the code below it. For example:
var storage = firebase.storage();
// Execute (1)
var getImageUrl = function (time) {
// Execute (2)
var returnVal;
// Execute (3)
storage.ref('images/' + time + '.jpg').getDownloadURL().then(function (url) {
// Execute (unknown)
returnVal = url;
});
// Execute (4)
return returnVal;
};
// Execute (unknown times)
You have no idea when the async call will return the data, but it will always be after return returnVal; therefore returnVal is null.
I recommend this:
$scope.images = [];
$scope.messages = { // whatever };
for (m in $scope.messages) {
storage.ref('images/' + time + '.jpg').getDownloadURL().then(function (url) {
// Might need $scope.$apply(function() {} ) surrounding
$scope.images.push(url);
});
}
Then in your view:
<div ng-repeat="image in images">
<img ng-src="{{ image }}">
</div>
The time for all this to load is dependent on the size of $scope.messages. If there are a large amount I would recommend changing your data structure so you do not have to make multiple calls to the database.
theblindprophet's answer contains a great explanation of why your current code doesn't work and a working solution.
As an alternative, you can simply return the so-called promise that getDownloadURL() returns. I haven't tested, but expect Angular to pick the promise up automatically.
var storage = firebase.storage();
var getImageUrl = function (time) {
return storage.ref('images/' + time + '.jpg').getDownloadURL();
};
And in your HTML you just keep:
<div ng-repeat="message in messages">
<img ng-src="{{ getImageUrl(message.time) }}">
</div>
You can use ajax for downlead file in firebase-storage
const link = linkYourFirebaseImage + folderStoreImage + '2F' + fileName;
// example: const link = https://firebasestorage.googleapis.com/v0/b/myApp.appspot.com/o/myDir%2F1608378322792.PNG;
function downloadImage(fileName, defaultImage) {
if (fileName.length == 0) return defaultImage;
let imageUrl;
$.ajax({
type: "GET",
async: false,
url: link ,
success: function (response) {
imageUrl = `${link}alt=media&token=${response.downloadTokens}`;
},
});
return imageUrl;
}
How to use ?
const myImage = downloadImage('myPath.png', '../default.png');
I know this question have been asked many times, but I can't make it work.
Here is my situation. I had a string called data, and I want to unshorten all the link inside that string.
Code:
var Bypasser = require('node-bypasser');
var URI = require('urijs');
var data = 'multiple urls : http://example.com/foo http://example.com/bar';
var result = URI.withinString(data, function(url) {
var unshortenedUrl = null;
var w = new Bypasser(url);
w.decrypt(function(err, res) {
// How can I return res ?
unshortenedUrl = res;
});
// I know the w.descrypt function is a asynchronous function
// so unshortenedUrl = null
return unshortenedUrl;
});
Let's me walk you through the code.
URI.withinString will match all the URLs in data, manipulate it and return the result.
You can view an example from URI.js docs
What I want to with these URLs is to unshorten all of them using node-passer.
This is from node-bypasser document:
var Bypasser = require('node-bypasser');
var w = new Bypasser('http://example.com/shortlink');
w.decrypt(function(err, result) {
console.log('Decrypted: ' + result);
});
This is the result that I want multiple urls : http://example.com/foo_processed http://example.com/bar_processed
I created a notebook at tonicdev.com
Solution
var getUrlRegEx = new RegExp(
"(^|[ \t\r\n])((ftp|http|https|gopher|mailto|news|nntp|telnet|wais|file|prospero|aim|webcal):(([A-Za-z0-9$_.+!*(),;/?:#&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*(),;/?:#&~=%-]*))?([A-Za-z0-9$_+!*();/?:~-]))"
, "g"
);
var urls = data.match(getUrlRegEx);
async.forEachLimit(urls, 5, function (url, callback) {
let w = new Bypasser(url);
w.decrypt(function (err, res) {
if (err == null && res != undefined) {
data = data.replace(url, res);
callback();
}
});
}, function(err) {
res.send(data);
});
You don't really understand what callback is. The callback serves to allow asynchronous code to run without Javascript waiting for it. If you were less lazy and added some debug in your code:
console.log("Started parsing");
var result = URI.withinString(data, function(url) {
console.log("URL parsed (or whatever)");
var unshortenedUrl = null;
var w = new Bypasser(url);
w.decrypt(function(err, res) {
// How can I return res ?
unshortenedUrl = res;
});
// I know the w.descrypt function is a asynchronous function
// so unshortenedUrl = null
return unshortenedUrl;
});
console.log("Call to library over");
You would (most likely) see messages in this order:
Started parsing
Call to library over
URL parsed (or whatever)
The answer: Callback is not guaranteed to run before any code you execute after assigning it. You can't put data in your result variable because the data might not be fetched yet.
i have a code like this and i get "Uncaught TypeError: Cannot call method 'replace' of undefined" in console, im not so good at javascript
<script>
parse_tag = function (str) {
var create_link = function (url, text) {
var link = $("<a>", {
text: text,
href: url,
target: "_blank"
});
return link.prop('outerHTML');
};
// parse username
str = str.replace(/[#]+[A-Za-z0-9_]+/g, function (s) {
return create_link("http://twitter.com/" + s.replace('#', ''), s);
});
// parse hashtags
str = str.replace(/[#]+[A-Za-z0-9_]+/g, function (s) {
return create_link("http://search.twitter.com/search?q=" + s.replace('#', ''), s);
});
return str;
};
$(document).ready(function() {
var text = $('.desc');
parse_tag(text);
});
</script>
You are calling the function like
var text = $('.desc');
parse_tag(text);
And the function is
parse_tag = function (str) { // <-- str suppose to be a string
var create_link = function(url, text){
// ...
return link.prop('outerHTML');
}
//...
str = str.replace(/[#]+[A-Za-z0-9_]+/g, function (s) {
return create_link("http://twitter.com/" + s.replace('#', ''), s);
});
}
In this case, str should be string but according to var text = $('.desc'); it's a jQuery object so you can change either var text = $('.desc'); to var text = $('.desc').text(); or make changes in your parse_tag function, otherwise, you'll get error something like object doesn't support this property or method.
Also, you are using two regex as /[#]+[A-Za-z0-9_]+/g, and /[#]+[A-Za-z0-9_]+/g but both are being used on a link, something like
#me`
Because you are returning an a tag using
return link.prop('outerHTML');
So, make changes in your regex too or maybe it's better to use the replace on link's text/href, so make sure you make the changes.
I've got a dropdown menu on my form, which when something is selected I need to reload the current page, but with an appended querystring.
How would I go about doing this?
This is an old question but it came up first in google search results.
The solution I went with is similar to jAndy's.
window.location.pathname gives me the page's url without the query string.
I'm then able to build the query string with "?"+$.param({'foo':'bar','base':'ball'}) which I then append to the pathname and set to window.location.href.
window.location.href = window.location.pathname+"?"+$.param({'foo':'bar','base':'ball'})
var params = [
"foo=bar",
"base=ball"
];
window.location.href =
"http://" +
window.location.host +
window.location.pathname +
'?' + params.join('&');
That code within your change event handler will do the trick.
For instance:
$('#my_dropdown_id').bind('change', function(){
var params = [
"foo=bar",
"base=" + $(this).val()
];
window.location.href = "http://" + window.location.host + window.location.pathname + '?' + params.join('&');
});
If you go with the top rated answer, you may want to replace
http://
in the code with
window.location.protocol
so that it works for other protocols, like https or file. So
window.location.href = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + params.join('&');
Actually, there a built-in function of location that you can use, the name of the function is assign.
For appending or modifying there is another built-in function of the URL class that you can use too. the name of the function is searchParams.
So for your case you just need below example:
const url = new URL(location.href);
url.searchParams.set('key', 'value');
location.assign(url.search);
Update 2022
I create a TypeScript function to apply redirect with params more easier:
const isClient = (): boolean => typeof window !== 'undefined';
type ParamsType = { [key: string]: string | number };
const redirectUrl = (url: string, params?: ParamsType): void => {
if (isClient()) {
try {
const _url = new URL(url);
if (params) {
const keyList = Object.keys(params);
for (let i = 0; i < keyList.length; i += 1) {
const key = keyList[i];
_url.searchParams.set(keyList[i], params[key]?.toString());
}
}
window.location.assign(_url.href);
} catch (e) {
throw new Error('The URL is not valid');
}
}
};
export default redirectUrl;
If you want a simple way to preserve the query string and possibly append to it, use window.location.search; here's a snippet:
var search = window.location.search + (window.location.search ? "&" : "?");
search += "param1=foo¶m2=bar";
window.location.href = window.location.protocol + "//" + window.location.host + window.location.pathname + search;
You can, of course, use a more sophisticated way of building the rest of your query string, as found in the other examples, but the key is to leverage Location.search.
If you have an existing querystring that you'd like to keep then this version does that and adds your new params to any existing ones. The keys are converted to lowercase so that duplicates are not added. Maintaining the quersytring does make the solution more complicated, so I'd only do this if you need to.
$("#sortby").change(function () {
var queryString = getQueryStrings();
// Add new params to the querystring dictionary
queryString["sortby"] = $("#sortby").val();
window.location.href =
window.location.protocol + "//" +
window.location.host +
window.location.pathname +
createQueryString(queryString);
});
// http://stackoverflow.com/questions/2907482
// Gets Querystring from window.location and converts all keys to lowercase
function getQueryStrings() {
var assoc = {};
var decode = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); };
var queryString = location.search.substring(1);
var keyValues = queryString.split('&');
for (var i in keyValues) {
var key = keyValues[i].split('=');
if (key.length > 1) {
assoc[decode(key[0]).toLowerCase()] = decode(key[1]);
}
}
return assoc;
}
function createQueryString(queryDict) {
var queryStringBits = [];
for (var key in queryDict) {
if (queryDict.hasOwnProperty(key)) {
queryStringBits.push(key + "=" + queryDict[key]);
}
}
return queryStringBits.length > 0
? "?" + queryStringBits.join("&")
: "";
}
I was having a requirement to open a particular tab after reloading. So I just needed to append the #tabs-4 to the current url. I know its irrelevant to current post but it could help others who come to this just like I did.
Using the code
window.location = window.location.pathname
+ window.location.search + '#tabs-4';
did'nt work for me but below code did.
location = "#tabs-4";
location.reload(true);