I have this below code in a javascript file. When i run it i get error message :
"Can't find variable: addZero".
function addZero(n) {
return ( n < 0 || n > 9 ? "" : "0" ) + n;
}
Date.prototype.toISODate =
new Function("with (this)\n return " +
"getFullYear()+'-'+ addZero(getMonth()+1)+ '-'" +
"+ addZero(getDate()) + 'T' + addZero(getHours())+':' " +
"+ addZero(getMinutes()) +':'+ addZero(getSeconds()) +'.000Z'");
function addZero(n) {
return ( n < 0 || n > 9 ? "" : "0" ) + n;
}
Date.prototype.toISODate = function() {
// do what you want here
// with real code! not strings...
}
Theres a good function on the Mozilla Javascript reference page for Date that produces ISO Date strings
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference:Global_Objects:Date
/* use a function for the exact format desired... */
function ISODateString(d){
function pad(n){return n<10 ? '0'+n : n}
return d.getUTCFullYear()+'-'
+ pad(d.getUTCMonth()+1)+'-'
+ pad(d.getUTCDate())+'T'
+ pad(d.getUTCHours())+':'
+ pad(d.getUTCMinutes())+':'
+ pad(d.getUTCSeconds())+'Z'
}
var d = new Date();
console.log(ISODateString(d)); // prints something like 2009-09-28T19:03:12Z
Looks like your quotes are off. Try
return "with (this)\n return " +
getFullYear() + '-' + addZero(getMonth()+1) + '-' +
addZero(getDate()) + 'T' + addZero(getHours())+':' +
addZero(getMinutes()) +':'+ addZero(getSeconds()) +'.000Z';
Try rewriting your Date extension like this, to keep things clear and to avoid using the with keyword:
Date.prototype.toISODate =
function(){
function padLeft(nr,base,padStr){
base = base || 10;
padStr = padStr || '0';
var len = (String(base).length - String(nr).length)+1;
return len > 0? new Array(len).join(padStr)+nr : nr;
}
return [this.getFullYear(),
'-',
padLeft(this.getMonth()+1),
'-',
padLeft(this.getDate()),
'T',
padLeft(this.getHours()),
':',
padLeft(this.getMinutes()),
':',
padLeft(this.getSeconds()),
'.',
padLeft(this.getMilliseconds(),100),
'Z'].join('');
};
The padLeftZero function now exists within the scope of the Date.toISODate method. The use of an array literal to build the return string is for clarity. It isn't necessary and even can be called bad practice to use new Function ... to assign a function to Date.prototype.toISODate. BTW, milliseconds are added to the result (padded with zero's).
Related
The following is my element id and I want to update it dynamically.
invoice[46][ap_details][4][ap_header_id]
I want to update only second number, i.e. [4], like this:
invoice[46][ap_details][5][ap_header_id]
I am using below code which is updating both the values.
var strNewName = $(this).attr('name').replace(/\[\d+\]/g, function(strName) {
strName = strName.replace(/[\[\]']+/g, '');
var intNumber = parseInt(strName) + 1;
return '[' + intNumber + ']';
});
Any help would be appreciated.
var strName = "invoice[46][ap_details][4][ap_header_id]";
var parts = strName.split('[');
parts[3] = parts[3].replace(/^\d+/, n => +n + 1);
var strNewName = parts.join('[');
console.log(strNewName);
If you don't want to use arrow functions replace this line:
parts[3] = parts[3].replace(/^\d+/, n => +n + 1);
with this:
parts[3] = parts[3].replace(/^\d+/, function(n) { return +n + 1; });
Explanation:
split will return an array like this:
[
"invoice",
"46]", // parts[1] to change this
"ap_details]",
"4]", // parts[3] to change this (and so on, you do the math)
"ap_header_id]"
]
The /^\d+/ will match any number at the begining (no need for the g modifier).
Replace with +n + 1 not n + 1 because n is a string, you have to force the interpretter to use it as a number or otherwise this "4" + 1 will result to this "41".
Then after you change what you want, join the parts using join with the same character you used for splitting ([).
Using this regex /((\w)+)(\[\d+\])(\[(\w)+\])(\[\d+\])(\[(\w)+\])/gi you can construct the string back and change your integer.
var match = /((\w)+)(\[\d+\])(\[(\w)+\])(\[\d+\])(\[(\w)+\])/gi.exec(youString);
//group 6 is your digit.
var newId = parseInt(match[6].replace("\[\]", "")) + 1;
var newString = match[1] + match[3] + match[4] + "[" + newId + "]" + match[7];
Here is a fiddle with the answer https://jsfiddle.net/gzfud9vc/
Maybe dont use regex to build your element id. You can do its as follows as well:
var id = 5
var name = "invoice[46][ap_details][";
name += id;
name += "][ap_header_id]";
var toReplace = "invoice[46][ap_details][~~id~~][ap_header_id]"
var replaced = toReplace.replace(/~~id~~/g, id);
console.log(name);
console.log(replaced);
The following code is working properly, however I would assume there is a more efficient way to have the logic flow. Currently I am writing out the same function twice with a subtle change in the output string. Does anyone know of way to make this logic work with less code?
if (result <= 1) {
document.getElementById('output').innerText = Math.ceil(result) + " roll of wallpaper";
}
else {
document.getElementById('output').innerText = Math.ceil(result) + " rolls of wallpaper";
}
document.getElementById('output').innerText = [
Math.ceil(result),
' roll',
result > 1 ? 's' : '',
' of wallpaper'].join('')
You can build the difference beforehand and add it in manually:
var s = ( result <= 1 ? 's' : '' );
document.getElementById('output').innerText =
Math.ceil(result) + " roll" +s+ " of wallpaper";
Edit: Cutting-edge JS bonus, using template strings is extra fun (need babel):
var displayResult = Math.ceil(result);
var s = ( result <= 1 ? 's' : '' );
document.getElementByid('output').innerText =
`${displayResult} roll${s} of wallpaper`;
Can be:
var s = (result <= 1) ? 's' : '';
document.getElementById('output').innerText = Math.ceil(result) + ' roll'+s+' of wallpaper';
I have an HTML input object of type="datetime-local" to which I would like to set a custom value which is now() + 3 hours everytime its value is changed.
Basing on the fact that alert(object.value) returns a string of type YYYY-MM-DDTHH:MM, I've thought I would need (apart for calculating the date) also to format the string properly. So I have:
Added the onchange attribute to the HTML
<input .... onchange="datesReactions()"/>
Extended the JS Date prototype to add the hours
Date.prototype.addHours = function(h) {
this.setTime(this.getTime() + (h*60*60*1000));
return this;
}
Created the datesReactions() function as follows
function datesReaction(){
var adesso = new Date;
document.getElementById('ExecutionDate').value = parseDateToInput(adesso.addHours(3));
}
where the parsing to string is performed by the following simple function:
function parseDateToInput(jsDate){
var jsDay = jsDate.getDate();
if (jsDay < 10){jsDay = '0' + jsDay;}
var jsMonth = jsDate.getMonth();
if (jsMonth < 10){jsMonth = '0' + jsMonth;}
var jsYear = jsDate.getFullYear();
if (jsYear < 10){jsYear = '0' + jsYear;}
var jsHour = jsDate.getHours();
if (jsHour < 10){jsHour = '0' + jsHour;}
var jsMinute = jsDate.getMinutes();
if (jsMinute < 10){jsMinute = '0' + jsMinute;}
return jsYear + '-' + jsMonth + '-' + jsDay + 'T' + jsHour + ':' + jsMinute;
}
However, although the single pieces of code work themselves, the above does nothing when I change the value of my input.
Could anyone please help me understanding what I do wrong? I have prepared the following fiddle in order to help you helping a beginner debugging :) Thanks in advance.
Have mechanism that replaces strings like .NET string.Format in javascript ("{0} - {1}",'a','b') would result "a - b".
I am looking for mechanism that would Replace everything between two strings with {0}{1}...
Example :
var str = "([OrderDate] >= Func:{TheApplication().GetProfileAttr('TestDate')} ) and [OrderDate] < 1/1/2013 AND [Name] = Func:{TheApplication().GetProfileAttr('Name')}"
stringFormatProducer(str,"Func:{","}");
would give result
"([OrderDate] >= {0} ) and [OrderDate] < 1/1/2013 AND [Name] = {1}"
I have this mechanism done in horrid way where I am splitting it on Func:{ then } then iterating over it, I am sure someone already has a better solution.
var i = 0;
str.replace(/Func:{[^}]+}/g, function(c) {
return '{' + i++ + '}';
});
Or more flexible way:
var i = 0,
func = 'Func:';
str.replace(new RegExp(func + '{[^}]+}', 'g'), function(c) {
return '{' + i++ + '}';
});
A complete method for you:
String.prototype.createFormattingString = function(prefix, open, close) {
var re = new RegExp(prefix + open + '[^' + close + ']+' + close, 'g'),
i = 0;
return this.replace(re, function(c) {
return '{' + i++ + '}';
});
};
'(VAR > Func:{ some text })'.createFormattingString('Func:', '{', '}');
'(VAR > Func:[ some text ])'.createFormattingString('Func:', '\\[', '\\]');
I want to number each item in an Array, like this:
["hello", "hi", "hey"].number()
> ["1. hello", "2. hi", "3. hey"]
Here's my code:
Array.prototype.number = function () {
var tempNum = this;
for (i in this) {
tempNum[i] = tempNum[(i + 1)] + ". " + tempNum[i]
}
return tempNum;
}
But this is the output:
["hello", "hi", "hey"].number()
> ["undefined. hello", "undefined. hi", "undefined. hey"]
Why? How should I implement this and why is my code not working?
I think you want something like this:
for(var i=0, len = this.length; i<len; i++){
tempNum[i] = (i + 1) + ". " + tempNum[i];
}
you're using tempNum when you shouldn't be in the right side of your equation. The reason you're getting "undefined" is because at some point in your current equation you're getting an index outside of the length of your array.
The ES5 way:
Array.prototype.number = function () {
return this.map( function ( value, i ) {
return ( i + 1 ) + '. ' + value;
});
};
Live demo: http://jsfiddle.net/XSYTK/1/
You'll need to shim .map() for IE8.
Inside your for loop, you're doing:
tempNum[i] = tempNum[(i + 1)] + ". " + tempNum[i]
If you just want to add numbers before each value, why are you getting tempNum[(i + 1)]?
It should look like:
Array.prototype.number = function () {
var tempNum = this;
for (var i in this) {
tempNum[i] = (parseInt(i,10) + 1) + ". " + tempNum[i];
}
return tempNum;
}
Note the parseInt(i,10)+1. This adds one to the index (after converting it to an int), and then prepends that to the string.
tempNum[(i + 1)] is not what you want to do, you want something like (i + 1). This also don't work, because keys are always strings. To type cast them to a float you can use (parseFloat(i) + 1) or, what is nicer, (~~(i) + 1). The total code become:
Array.prototype.number = function () {
var tempNum = this;
for (i in this) {
tempNum[i] = (~~(i) + 1) + ". " + tempNum[i]
}
return tempNum;
};
console.log(["hello", "hi", "hey"].number());
// > ["1. hello", "2. hi", "3. hey"]
I would not try to modify the array values itself when invoking the number() function, because if you invoke the function again on the same array the numbering gets doubled. Instead better make a new array and return it like this:
Array.prototype.number = function () {
var ret=[];
var len=this.length;
for(var i=0;i<len;i++){
ret.push((i+1)+'. '+this[i]);
}
return ret;
}
console.log(["hello", "hi", "hey"].number());
Demo: http://jsfiddle.net/LcHsY/
The problem with your current solution is that in each iteration, i holds the value of the element, instead of the index.
So, when you do things like
tempNum[(i + 1)]
you are trying to add "hello" and 1, and this gives an undefined result.
So, in order to get your code working you could change your code as follows:
Array.prototype.number = function () {
var tempNum = this;
for (var i = 0; i < tempNum.length; ++i) {
tempNum[i] = (i + 1) + ". " + tempNum[i]
}
return tempNum;
}