i'm having a problem with a bit of jquery right now. I've got a navigation code (EG pressing the up arrow and down arrow alters a $_GET variable in the URL). It's working fine in the positive numbers but the moment I try to go past -1 it unsets the variable and causes the page to reset.
Below is the Jquery Function in question.
function arrowbuttons()
{
$(document).keydown(function(e){
var full_url = document.URL; // Get current url
var split = location.search.replace('?, &');
var y = split[7];
var x = split[3];
var down = +split[7]-1;
var up = +split[7]+1;
var left = +split[3]+1;
var right = +split[3]-1;
if (e.keyCode == 37) {
window.location = 'index.php?X='+left+'&Y='+y+'&Z=0';
return false;
}
if(e.keyCode == 38) {
window.location = 'index.php?X='+x+'&Y='+up+'&Z=0';
return false;
}
if(e.keyCode == 39) {
window.location = 'index.php?X='+right+'&Y='+y+'&Z=0';
return false;}
if(e.keyCode == 40) {
window.location = 'index.php?X='+x+'&Y='+down+'&Z=0';
return false;}
});
}
If either of the effected URL variables (X or Y) are attempting to go below -1, like i said before, everything is redirected back to the start (X=0&Y=0&Z=0) by my php redirect code. This is strictly a Jquery issue, as the links that i've hardcoded into my site i'm fully capable of going as low as -16. Furthermore, I've noticed that I cannot go above +10 on any of the directions; when i go above +10 i resets me to (X=2 or Y=2 depending on which variable has been affected)
You've got a couple of issues happening here:
1st: replace takes 2 parameters. It looks for the first string and replaces it with the 2nd. You're call won't replace anything because it doesn't find the string "?,&" in your location.search string. So split will be X=1&Y=0&Z=0 (for example) after your replace.
2nd: you are hard coding the exact locations in the string that you are expecting the values. If any of the values are 2 digits or a negative number, it doesn't work because the values are no longer at split[7] and split[3]. Since the string is now X=-1&Y=10&Z=0 (for example)
This is a good discussion on getting query params in javascript How can I get query string values in JavaScript?,
But I generally just have php set the variables in my javascript for me.
Adding a fiddle, for you to play with: http://jsfiddle.net/bhlaird/M3Ub7/
function getParameterByName(name,location_search) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location_search);
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
var location_search = '?X=-1&Y=10&Z=0' // replace this string with location.search
var y = getParameterByName('X',location_search);
var x = getParameterByName('Y',location_search);
var down = +y - 1;
var up = +y + 1;
var left = +x + 1;
var right = +x - 1;
Related
My goal is to edit the string (which has an email) to mask the first part, like say the email is johndoe#abc.com then I should output j*****e#abc.com.
var maskPII = function(S) {
var ans = "";
if(S.includes("#")){
S = S.toLowerCase();
var parts = S.split("#");
var first = parts[0];
for(var i=0;i<parts[0].length;i++){
if(i!=0 && i!=parts[0].length - 1)
first[i] = '*';
}
ans = first +"#" +parts[1];
}else{
}
return ans;
};
However in my loop I can't change the characters to asterisks.
After execution I see value of first still same as parts[0] and has no asterisks, can some one explain why? Also, what would I need to do to modify the variable inside loop?
To answer your question... javascript allows you access values of a string using [] indexing.. but that is read only access... you cannot insert/replace values using that operator.
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
When using bracket notation for character access,
attempting to delete or assign a value to these properties will not succeed.
The properties involved are neither writable nor configurable.
(See Object.defineProperty() for more information.)
You need to extract the values you want to keep from the existing string and build up a new string as noted in other answers...
Well, this's what you're looking for, and this will be the output j*****e#abc.com.
var ans = "";
var S = "johndoe#abc.com"; //example
S = S.toLowerCase();
var parts = S.split("#");
var first = "";
for(var i = 0; i < parts[0].length; i++){
if(i != 0 && i != parts[0].length - 1){
first += '*';
}else{
first += parts[0][i];
}
}
ans = first +"#"+ parts[1];
console.log(ans);
Here is the code with your approach:
var maskPII = function(S) {
var ans = "";
if(S.includes("#")){
S = S.toLowerCase();
var parts = S.split("#");
var first = parts[0][0];
for(var i=0;i<parts[0].length;i++){
if(i!=0 && i!=parts[0].length - 1)
first += '*';
}
ans = first + parts[0][parts[0].length - 1] +"#" +parts[1];
}else{
}
return ans;
};
But if i were you i would use:
var mail = "johndoe#abc.com";
mail = mail.replace(/(?<=.)(.+?)(?=.#)/gi, '*'.repeat(mail.split('#')[0].length - 2));
console.log(mail);
You can use the bracket notation on a string (like an array) to get the character at a specific index, but you can't use this to change characters. So first[i] = '*' in your code wont do anything.
Strings in JavaScript are immutable. This means that if you want to change a string, a new string instance will be created. This also means that when you change a string in a for-loop, it can impact performance. (Although in this case the difference wont be noticeable.
)
I would use this code:
function maskPII(str) {
const indexOfAt = str.indexOf('#');
if (indexOfAt <= 2) {
return str;
}
return str[0] + '*'.repeat(indexOfAt - 2) + str.substring(indexOfAt - 1);
}
const email = 'johndoe#abc.com';
console.log(email);
console.log(maskPII(email));
It will look for the index of the # sign. If the index is less or equal than 2, (when not found the index will be -1) it will return the original string.
Otherwise it will get the first character, calculate the amount of asterisks needed (index of the # sign -2) and repeat those and then add the rest of the original string.
I built an app that I then built with PhoneGap Build.THe purpose is for it to run a code (starts at var Quotes once per day when the app is loaded).
When debugging why it wasn't working I noticed that in console I was getting back my message "Local storage didn't work". This means that my initial localstorage.getItem which is supposed to make sure the local storage can be read is returning null. So my code never gets executed.
What am I doing wrong?
function onDeviceReady() { //Do something when the app on device is loaded
var localVal = localStorage.getItem('DateOpened');
if(localVal == null){
console.log("LocalStorage did not work...")}
else
{
var tempd = new Date(); //Get today's date
var str = tempd.getDay() + tempd.getMonth() + tempd.getFullYear();
if(localVal.localeCompare(str) == -1)
{
var Quotes = [];
var ID = [];
var Tag = [];
var seen = [];
localStorage.setItem('DateOpened',str);
console.log("The App Ran, you can get a new fat tomorrow");
console.log("Todays date:" + str);
}
}
}
Initially, there will be no DateOpened item in local storage, so your code will follow the "did not work" branch, because getItem returns null for things that don't exist. That branch never sets anything in DateOpened, so...you'll always follow that branch.
The fix is not to skip over your code setting DateOpened if the device has local storage.
There's also an unrelated problem: Your var str = tempd.getDay() + tempd.getMonth() + tempd.getFullYear() does not produce a string, it produces a number formed by adding those values together, since they're all numbers. Your later localeCompare will fail because it's not a string. You also have the fields in the wrong order for a meaningful textual comparison — you need year first, then month, then day.
Here's a minimal fix, see comments:
function onDeviceReady() {
var tempd = new Date();
// Note that by adding strings in there, we end up with a string instead of adding.
// Note the order: Year first, then month, then day.
// Also, since we display it, we put separators in and add 1 to month (since Jan = 0).
var str = tempd.getFullYear() + "-" + (tempd.getMonth() + 1) + "-" + tempd.getDay();
var localVal = localStorage.getItem('DateOpened');
// If we have no stored value, or it's more than a day old by your definition,
// do your stuff and store the new date
if (localVal == null || localVal.localeCompare(str) < 0) {
var Quotes = [];
var ID = [];
var Tag = [];
var seen = [];
localStorage.setItem('DateOpened', str);
console.log("The App Ran, you can get a new fat tomorrow");
console.log("Todays date:" + str);
}
}
I think this is help full for you.
function onDeviceReady() { //Do something when the app on device is loaded
var localVal = localStorage.getItem('DateOpened');
if (typeof(DateOpened) == "undefined")
console.log("LocalStorage did not work...")}
else
{
var tempd = new Date(); //Get today's date
var str = tempd.getDay() + tempd.getMonth() + tempd.getFullYear();
var allRecords=JSON.parse(localStorage.getItem("DateOpened"));
if(allRecords == -1)
{
var Quotes = [];
var ID = [];
var Tag = [];
var seen = [];
localStorage.setItem('DateOpened',str);
console.log("The App Ran, you can get a new fat tomorrow");
console.log("Todays date:" + str);
}
}
}
sorry i couldn't think of better title ! plus my english sucks
her is my first plugin (basically i repackaged some js code as a plugin )
it adds a comma , separator to value every 3 digit , when someone types something inside textfield
(function($){
$.fn.num = function(userop){
var options = $.extend( {seperator:','} , userop );
$(this).keyup(function(e) {
var num = $(this).val();
var nStr = num + '';
nStr = nStr.replace( /\,/g, "");
var x = nStr.split( '.' );
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while ( rgx.test(x1) ) {
x1 = x1.replace( rgx, '$1' + options.seperator + '$2' );
}
$(this).val( x1 + x2 );
})
}
})(jQuery);
$('.number_input').num();
but problem is if i put 123456 in my textfield
var n = $('.number_input').val();
console.log(n);
will return 123,456
which is fine but it suppose to be a numeric value and each time user has to extract commas manually
by running it trough something like
n = Number($.trim(n.replace(/\,/g,'')));
is there any way to add this line to my plugin so it gets executed when someone runs .val() on textfild ?
basically i want to write comma remover once not every single time that i get each effected textfield value
If you change the default .val() method with the combination of the .data(), you'll be able the do what you want. Note that change .val() can have undesired effect (mostly when user try to override .val() aswell...)
Anyway, the first thing to do is give a data to every element that are active number. So in you init, add this code :
this.data('__numered', true);
Now we can detect if the element as a formatting.
Then here come the tricky part : overriding.
You'll have to save the old .val() method :
$.fn.__val = $.fn.val;
Then recreate .val() but check if its a numbered item :
$.fn.val = function(set){
if(typeof set === 'undefined'){
if(this.first().data('__numered'))
return Number($.trim(this.first().__val().replace(/\,/g,'')));
else
return this.first().__val();
}else
return this.__val(set)
}
Fiddle : http://jsfiddle.net/Tw77J/1/
First of all
I think I'm suggesting a better way to do what you are asking, instead of directly answering.
If you use, my solution, your plugin gives the users the option of getting what they want. (You cant predict what users need)
My Solution:
You can add this simple code:
if (userop == 'val') {
return Number($.trim($(this).val().replace(/\,/g, '')));
}
So your plugin would become:
(function ($) {
$.fn.num = function (userop) {
if (userop == 'val') {
return Number($.trim($(this).val().replace(/\,/g, '')));
}
var options = $.extend({
seperator: ','
}, userop);
$(this).keyup(function (e) {
var num = $(this).val();
var nStr = num + '';
nStr = nStr.replace(/\,/g, "");
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + options.seperator + '$2');
}
$(this).val(x1 + x2);
});
};
})(jQuery);
Remember, you are the creator of the plugin, and you can impose some rules for the developers using your plugin.
That said, ask your users to use $('selector').num('val'); to get the value without commas, and $('selector').val(), if they want it with comma.
So to brush up:
Use $('selector').num('val'); // with comma
Use $('selector').val(); // without comma
Put that in readme file or any document file.
Live demo!
Also, don't forget me to add me as a contributor to the plugin, If my answer helped you ;)
This question already has answers here:
Adding http:// to all links without a protocol
(4 answers)
Closed 8 years ago.
I would like to detect url's that are entered in a text input. I have the following code which prepends http:// to the beginning of what has been entered:
var input = $(this);
var val = input.val();
if (val && !val.match(/^http([s]?):\/\/.*/)) {
input.val('http://' + val);
}
How would I go about adapting this to only append the http:// if it contains a string followed by a tld? At the moment if I enter a string for example:
Hello. This is a test
the http:// will get appended to hello, even though it's not a url. Any help would be greatly appreciated.
This simple function works for me. We don't care about the real existence of a TLD domain to gain speed, rather we check the syntax like example.com.
Sorry, I've forgotten that VBA trim() is not intrinsic function in js, so:
// Removes leading whitespaces
function LTrim(value)
{
var re = /\s*((\S+\s*)*)/;
return value.replace(re, "$1");
}
// Removes ending whitespaces
function RTrim(value)
{
var re = /((\s*\S+)*)\s*/;
return value.replace(re, "$1");
}
// Removes leading and ending whitespaces
function trim(value)
{
return LTrim(RTrim(value));
}
function hasDomainTld(strAddress)
{
var strUrlNow = trim(strAddress);
if(strUrlNow.match(/[,\s]/))
{
return false;
}
var i, regex = new RegExp();
regex.compile("[A-Za-z0-9\-_]+\\.[A-Za-z0-9\-_]+$");
i = regex.test(strUrlNow);
regex = null;
return i;
}
So your code, $(this) is window object, so I pass the objInput through an argument, using classical js instead of jQuery:
function checkIt(objInput)
{
var val = objInput.value;
if(val.match(/http:/i)) {
return false;
}
else if (hasDomainTld(val)) {
objInput.value = 'http://' + val;
}
}
Please test yourself: http://jsfiddle.net/SDUkZ/8/
The best solution i have found is to use the following regex:
/\.[a-zA-Z]{2,3}/
This detects the . after the url, and characters for the extension with a limit of 2/3 characters.
Does this seem ok for basic validation? Please let me know if you see any problems that could arise.
I know that it will detect email address's but this wont matter in this instance.
You need to narrow down your requirements first as URL detection with regular expressions can be very tricky. These are just a few situations where your parser can fail:
IDNs (госуслуги.рф)
Punycode cases (xn--blah)
New TLD being registered (.amazon)
SEO-friendly URLs (domain.com/Everything you need to know about RegEx.aspx)
We recently faced a similar problem and what we ended up doing was a simple check whether the URL starts with either http://, https://, or ftp:// and prepending with http:// if it doesn't start with any of the mentioned schemes. Here's the implementation in TypeScript:
public static EnsureAbsoluteUri(uri: string): string {
var ret = uri || '', m = null, i = -1;
var validSchemes = ko.utils.arrayMap(['http', 'https', 'ftp'], (i) => { return i + '://' });
if (ret && ret.length) {
m = ret.match(/[a-z]+:\/\//gi);
/* Checking against a list of valid schemes and prepending with "http://" if check fails. */
if (m == null || !m.length || (i = $.inArray(m[0].toLowerCase(), validSchemes)) < 0 ||
(i >= 0 && ret.toLowerCase().indexOf(validSchemes[i]) != 0)) {
ret = 'http://' + ret;
}
}
return ret;
}
As you can see, we're not trying to be smart here as we can't predict every possible URL form. Furthermore, this method is usually executed against field values we know are meant to be URLs so the change of misdetection is minimal.
Hope this helps.
This is the script that i am using to fetch a particular cookie lastvisit :
AFTER THE EDIT
// This document writes a cookie
// called from index.php
window.onload = makeLastVisitCookie;
function makeLastVisitCookie() {
var now = new Date();
var last = new Date();
now.setFullYear(2020);
// set the cookie
document.cookie = "lastvisit=" + last.toDateString() + ";path=/;expires=" + now.toGMTString();
var allCookies = document.cookie.split(";");
for( var i=0 ; i < allCookies.length ; i++ ) {
if(allCookies[i].split("=")[0]== "lastvisit") {
document.getElementById("last_visit").innerHTML = "You visited this site on" + allCookies[i].split("=")[1];
} else {
alert("testing..testing..");
}
}
}
From this script the if part never works though there are 5 cookies stored from my website. (including the cookie that i am saving from this script) What is the mistake that i am making while fetching the cookie named lastvisit ?
You're splitting the cookie by ; an comparing those tokens with lastvisit. You need to split such a token by = first. allCookies[i] looks like key=val and will never equal lastvisit. Een if allCookies[i] == "lastvisit" is true, the result will still not be as expected since you're showing the value of allCookies[i + 1] which would be this=the_cookie_after_lastvisit.
if(allCookies[i].split("=") == "lastvisit") { should be:
var pair = allCookies[i].split("=", 2);
if (pair[0].replace(/^ +/, "") == "lastvisit") {
"You visited this site on" + allCookies[i+1]; should be:
"You visited this site on" + pair[1];
The 2 argument of split makes cookies like sum=1+1=2 be read correctly. When splitting cookies by ;, the key may contain a leading space which much be removed before comparing. (/^ +/ is a regular expression where ^ matches the beginning of a string and + one or more spaces.)
Alternatively, compare it directly against a RE for matching the optional spaces as well (* matches zero or more occurences of a space character, $ matches the end of a string):
if (/^ *lastvisit$/.test(pair[0])) {
I've tested several ways to get a cookie including using regular expressions and the below was the most correct one with best performance:
function getCookie(name) {
var cookie = "; " + document.cookie + ";";
var search = "; " + encodeURIComponent(name) + "=";
var value_start = cookie.indexOf(search);
if (value_start == -1) return "";
value_start += search.length;
var value_end = cookie.indexOf(';', value_start);
return decodeURIComponent(cookie.substring(value_start, value_end))
}
You need to remove possible white space around the cookie key before comparing to the string "lastvisit". This is done conveniently using regular expressions. /^\s+/ matches all white space at the beginning, /\s+$/ matches all white space at the end. The matches are replaced by the empty string, i.e. removed:
for( var i = 0 ; i < allCookies.length ; i++ ) {
var c = allCookies[i].split("="); // split only once
var key = c[0].replace(/^\s+/, '').replace (/\s+$/, ''); // remove blanks around key
if (key == "lastvisit") {
document.getElementById("last_visit").innerHTML = "You visited on " + c[1];
}
//...
}