I've been staring at this for hours and could really use some help. I'm working with some existing code for a movie theater website and the following should fill a select list with dates ranging from today to a max date from an xml file.
function populateSelect(xmlDoc, elSel) {
var dmindate = new Date();
var showings = xmlDoc.getElementsByTagName('Session');
fmaxdate = "";
for (var showing = 0; showing < showings.length; showing++) {
if (retText(showings[showing].getElementsByTagName('Date_time')[0]) > fmaxdate) {
fmaxdate=retText(showings[showing].getElementsByTagName('Date_time')[0]);//get the Max Date
}
}
var dmaxdate = new Date.parseString(fmaxdate, "yyyyMMddHHmmss");
while(dmindate <= dmaxdate){ //Fill in the Select List
var elOptNew = document.createElement('option');
elOptNew.text = dmindate.format("EE NNN d, yyyy");
elOptNew.value = dmindate.format("MM/dd/yyyy");
dmindate.setDate(dmindate.getDate()+1);
try {
elSel.add(elOptNew, null); // standards compliant doesn't work in IE
}
catch(ex) {
elSel.add(elOptNew); // IE only
}
}
}
This works perfectly fine in FF, Chrome and Safari but IE8 doesn't display the dropdown with dates and it showed the Invalid Argument as being the same line as the closing bracket for try.
Any help would be greatly appreciated!
I don't know where Date.prototype.parseString or format methods come from, presumably you are adding some date library. They aren't part of ECMAScript ed 3 or 5.
You can replace these lines:
> var elOptNew = document.createElement('option');
> elOptNew.text =dmindate.format("EE NNN d, yyyy");
> elOptNew.value = dmindate.format("MM/dd/yyyy");
with:
var elOptNew = new Option(dmindate.format("EE NNN d, yyyy"), // option text
dmindate.format("MM/dd/yyyy")); // option value
then add it to the select:
elSel.appendChild(elOptNew);
The above will work in all versions of IE and other browsers. See http://dev.w3.org/html5/spec/single-page.html#the-option-element for details of the Option constructor.
Edit
In the DOM 2 HTML specification for the add method it says:
This method is the equivalent of the appendChild method of the Node
interface if the before parameter is null.
That doesn't mean to pass the ECMAScript null object, it means "if there is no second parameter". The specification is language neutral, it isn't javascript specific. The HTML5 OptionsCollection add method is the same (i.e. "null" means no parameter, not the javascript null object).
From the documentation I could find, having a null parameter doesn't make any sense. However, it is clear that the JavaScript engines in the different browsers handle this method differently, and that IE doesn't like null as the second parameter.
So, as per the mantra, you should use jQuery. It is good and does all things. It does actually help protect you from differences between browser implementations of the DOM, because it has a fairly broad compatibility. It fixed this guy's issue anyway.
You will probably want to use append() instead of the add(). For example:
var elOptNew = $('<option></option>');
...
elSel.append(elOptNew);
There is also an alternative way to add new options in to a select, i.e
var opts = elSel.options;
opts[opts.length] = new Option(dmindate.format("EE NNN d, yyyy"), dmindate.format("MM/dd/yyyy"));
Example that works in all mejor browsers.
Try to use
elSel.options.add(elOptNew)
This must work in all browsers. See example.
Related
I'm trying to set the calendar and numberingSystem options for an Intl.DateTimeFormat object. When I set them via the locale argument as below it works:
var dateFormat = new Intl.DateTimeFormat('en-US-u-ca-chinese-nu-arab');
var usedOptions = dateFormat.resolvedOptions();
console.log("resolved calendar: " + usedOptions.calendar);
console.log("resolved numbering: " + usedOptions.numberingSystem);
But when I try to set them via options argument as below, it doesn't work. Mozilla MDN specifically mentions that this should work:
But when you try it, it doesn't:
var options = {calendar: 'chinese', numberingSystem: 'arab'};
var dateFormat = new Intl.DateTimeFormat('default', options);
var usedOptions = dateFormat.resolvedOptions();
console.log("resolved calendar: " + usedOptions.calendar);
console.log("resolved numbering: " + usedOptions.numberingSystem);
I have tested this on node.js and Firefox with the same results. Online javascript emulators also give the same result.
I could still set them via the locale string but it's rather ugly. I prefer to use the options argument if possible.
I think Mozilla MDN may be wrong about this. If I am reading the ECMA-402 spec for constructing a DateTimeFormat correctly, in step 8 of §13.1.1 the calendar option is considered, but then in step 17 we go to ResolveLocale where in step 9.i.iv of §9.2.7 the calendar option only overrides the default if it is already a possible choice for the calendar in that locale.
That said, I cannot seem to come up with a case where it works as I expect it would from reading the spec, so maybe I am reading it wrong. I would expect that the second line here would return 'japanese', because the Japanese and Gregorian calendars would be valid choices in the Japanese locale:
> new Intl.DateTimeFormat('ja').resolvedOptions().calendar
'gregory'
> new Intl.DateTimeFormat('ja', { calendar: 'japanese' }).resolvedOptions().calendar
'gregory'
My page was working fine and displaying dates and times as expected until I had to add new Date() to avoid the momentjs deprecation warning. Now my date is 5 hours off what it should be.
How can I fix this? vd and v should both be 12:14:26 and, in this instance, fn should be "Seconds ago".
Here is the full code:
var k = key;
var v = obj[key];
var vd = Date.parse(obj[key]));
if (moment(vd).isValid()) {
var fn = moment(vd).fromNow();
v = fn;
}
return {
name: k,
value: v
};
I tried the following based on this post, but it brought back the momentjs deprecation warning:
var vd = new Date(Date.parse(obj[key])).toUTCString();
(and still didn't work)
__________________________________________________________________________________
Threaded comments would be cool
What happens if you just run moment(v)? Should work. – Maggie Pint
It does work, but I get the deprecation warning.
I just looked closer. The format of V is ISO8601 with offset, so you shouldn't be getting a deprecation if you just call moment(v). If you are, try moment(v, moment.ISO_8601) – Maggie Pint
Again, works, but I still get the deprecation warning.
instead of var vd = new Date(Date.parse(obj[key])).toUTCString(); did you try var vd = new Date(Date.parse(obj[key])).toISOString(); ? or even simplier var vd = Date.parse(obj[key]) – user3
With .toISOString() it outputs "Invalid Date". var vd = Date.parse(obj[key]) Is what I had originally, it works as expected but I get the warning.
Your v string appears to use ISO8601 format already? Maybe append the Z, or ask moment to recognise it automatically as UTC when timezone info is missing – Bergi
I just tried var vd = new Date(Date.parse(obj[key] + "Z")); and it works!
In your example, you're passing a value for v as an ISO8601 string without any offset specified. It is ambiguous as to what point in time you are actually talking about.
Because of changes in the ECMAScript specification, the value will be interpreted as UTC by some browsers, and as local time by others.
The way to avoid this ambiguity is to not use the date constructor. Anywhere you have new Date or Date.parse, you're introducing potential differences in behavior. Just use moment's own parser, and be specific as to your intent.
// your input
var v = "2016-09-14T12:14:26.149";
// pick only one of these:
var m = moment(v); // input is local time
var m = moment.utc(v) // input is UTC
// then proceed as normal
if (m.isValid()) {
var fn = m.fromNow();
// etc.
}
If the input is in some other time zone, or has some other specific fixed offset from UTC, then you have various other options for constructing the moment object. But really, don't rely on the Date object to do the parsing. That's the whole point of the deprecation message.
If the input is not always in the expected format (you're looking for invalid inputs, etc.), then you should specify the expected format such that you don't get the deprecation warning. For example:
var m = moment.utc(v, "YYYY-MM-DD[T]HH:mm:ss.SSS");
This particular format is also available as a constant:
var m = moment.utc(v, moment.ISO_8601);
This, and much more are spelled out in the Moment documentation.
It looks like the problem is when you create the date that recovered from the database... because it does not have the timezone... but you know it is "-0500", might be you can add that part hard coded... not ideal but it works
Look at this example:
function getMoment(v){
var vd = moment(v+"-0500");
var result = "?";
if (vd.isValid()){
result = vd.fromNow();
}
return result;
}
Check the getMoment() function, you can just copy and paste and use it in your code.
I'm having difficulty setting a time (duration) value in a datebox. A simple demonstration of the problem is if I do something like:
function initDuration() {
this.d['header Text'] = "Set";
this.d['headerText'] = "Set Duration";
var element = 'input#'+this.element[0].id;
var currentDt = $(element).datebox('getTheDate');
// ***************
var dt = $(element).datebox('parseDate', '%H:%M', this.element[0].value); // Where this.element[0].value = "01:00:00"
// ***************
$(element).datebox('setTheDate', this.element[0].value);
$(element).trigger('datebox', { 'method': 'doset' });
}
dt just contains the current date/time; i.e. jtsage didn't like it. The element is defined (in jade) as:
input.Duration(type="text" name="duration" form="form#{i}"
id="duration#{i}" value="#{map[i].duration}" data-role="datebox"
data-options=
'{"mode":"durationflipbox", "overrideDurationOrder":["h","i"],'
+' "overrideTimeFormat": "%l:%M", "minuteStep":15, "beforeOpenCallback": "initDuration"}')
Also I'm not sure how to change the flipbox title. The 2nd line in initDuration() sets the text for the button but the title still says 'Set Time'.
Because of the first problem the last 2 lines in initDuration() don't do what I want. i.e. they just use the current time, whatever that happens to be.
My apologies that this is going to be an incomplete answer, but it was going to be too long for a comment.
For the title - give "overrideHeaderText" a shot instead. It is entirely possible that I screwed this up at some point, it's not a feature I use in any of my own projects.
Next...
var dt = $(element).datebox('parseDate', '%H:%M', this.element[0].value); // Where this.element[0].value = "01:00:00"
I think I am reading you correctly that "dt" isn't containing what you are expecting. It's because 01:00:00 != %H:%M - to read this "format", you'd need to either use "%H:%M:%S" or "%H:%M:00" (the later ignoring the seconds field).
That said, I think what you are trying to do is set a duration, which, is a little different. There are a few ways to do it - and I'm noticing that there isn't a lot of support to do it functionally. The simplest method, is the set the value of the input, and let datebox handle the math - just be aware that the format you drop into the input must be exactly the same as the output format - it will read it when the control opens (or is initialized if the control is being shown inline - if you are doing it inline, and set the value "later", you can use the 'refresh' method to update it).
For what it's worth, if you really, really, really want to use the setTheDate method, duration modes work by comparing "theDate" (the publicly available date, i.e. setTheDate, getTheDate) with an internal initDate - which is not exposed to the API, but can be found here:
$(element).data('jtsage-datebox').initDate
So, in pseudo-code, for a duration of an hour
myNewDate = $(element).data( 'jtsage-datebox' ).initDate;
myNewDate.setHour( myNewDate.getHour() + 1 );
$(element).datebox( 'setTheDate', myNewDate );
Using jQuery 1.9.1 and creating XML similar to below. It gets built from items in an array of checkboxes on the page that are checked. The XML structure is:
<MyXML>
<Msg>This is a test message.</Msg>
<MsgTime>2013-10-15 08:30:00.000</MsgTime>
<Locations>
<Location>Panel1</Location>
<Location>Panel2</Location>
<Location>Panel3</Location>
</Locations>
</MyXML>
When a submit button is clicked, all the checked checkboxes are pushed into an array, which I then loop through to create the <Location> XML nodes. Right before I loop through that array, I find & remove any existing Location in the XML.
zXML.find("Location").remove();
for (var d=0; d < msgArr.length; d= d+ 1) {
var tmpLocNode = "<Location>" + msgArr[d].locID + "</Location>";
zXML.find("Locations").append( tmpLocNode );
}
In FF, the above code works great.
However, in IE8, the last line in the for loop:
zXML.find("Locations").append( tmpLocNode );
throws an error, "Object doesn't support this property or method" and stops at line 6470 in the jquery.js module. That line is:
tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
and is in the ELSE part of // Convert html into DOM nodes in the jquery module.
Any idea what the issue might be? I suspect it is IE8 not liking XML, but not sure how to resolve this issue. Would appreciate any feedback or thoughts on a better way to do what I am doing.
Thanks!
I'm not certain this will work, but all I can suggest is an alternate method of creating the new node, as it appears the error is in creating the node from the provided string.
for (var d = 0; d < msgArr.length; d = d+ 1) {
var $tmpLocNode = $("<Location />", { text: msgArr[d].locID });
zXML.find("Locations").append($tmpLocNode);
}
Im facing a problem with jQuery in the Internet Explorer 7 and 8, while trying to add a option to a existing select:
var s = document.getElementById("category");
s.options.add(select_option);
But IE just says:
Object doesn't support this property or method
and points to s.options.add(select_option);
Assuming the element with id "category" is actually a <select>, the easiest way is the the following time-honoured code for adding an option to a select list in any browser:
var s = document.getElementById("category");
s.options[s.options.length] = new Option("Option text", "optionValue");
try
$('#category').append('<option value="foo" selected="selected">Foo</option>');
or
var options = $('#category').attr('options');
options[options.length] = new Option('Foo', 'foo', true, true);
This soulution is working fine under IE8 - copied from MIcrosoft forum -
"I assume you already got the answer you needed, but for anyone else who finds this post when searching this problem (like I did), here's the solution that worked for me. All it took was setting the properties on opt AFTER adding it to the options collection. I also found that MSDN's page on the add function (for the options collection) explicitly states that for IE, the properties must be set after the option is added, but most of the examples I found online don't do it that way. I think your way may have worked in older versions of IE."
var opt = document.createElement('option');
select.options.add(opt);
opt.innerHTML = 'Foo';
opt.value = 'Bar';
Should the add() call not be on the select element, rather than the collection of options? I.e.:
s.add(select_option);