开发者

$("#datePicker").datepicker("getDate").getMonth is not a function

开发者 https://www.devze.com 2023-03-03 13:18 出处:网络
Trying to help getting this to work with a link t开发者_如何学编程o a specific month http://jquerymobile.com/test/experiments/ui-datepicker/

Trying to help getting this to work with a link t开发者_如何学编程o a specific month

http://jquerymobile.com/test/experiments/ui-datepicker/

I tried this

http://jsfiddle.net/mplungjan/FQLjS/2/

  1. The default date is not the first of June
  2. I have a visible calendar and another one onclick.
  3. I get

Error: $("#datePicker").datepicker("getDate").getMonth is not a function

Source File: http://fiddle.jshell.net/mplungjan/FQLjS/2/show/

Line: 59

What are the issues here?

Please note the added resources from the mobile jquery and mobile datepicker


The problem is caused by jquery.ui.datepicker.mobile.js, whereever you got that from, it's clearly an incomplete hack.

The real problem is with this line:

//return jqm obj 
return this;

That means whatever you call, it will always return the hacked jQuery object for the new datepicker. In your case, it should return a date.

A solution, which is again just a hack, is to save the return value of the original datepicker call, and only return a jQuery object if the original return value was in fact a jQuery object:

...

//call cached datepicker plugin
var retValue = prevDp.call( this, options );

...

//return jqm obj
if(retValue){
    if(!retValue.jquery) return retValue;
}
return this;

...

Edit: Further problems with this extension of an extension is that it breaks all commands which require more than one parameter. The datepicker() can take as many as 5 parameters, so these extras must be passed through to the original extension.

Likewise, the adding of extra styles and the binding of the click event should only take place when the datepicker is being constructed, so there is an extra check that needs to be put in to see if the type of the first parameter is a string or not.

The resulting code should look something like this, I'll leave the rest up to the original developer :).

(function($, undefined ) {

    //cache previous datepicker ui method
    var prevDp = $.fn.datepicker;

    //rewrite datepicker
    $.fn.datepicker = function( options, param2, param3, param4, param5 ){

        var dp = this;

        //call cached datepicker plugin
        var retValue = prevDp.call( this, options, param2, param3, param4, param5 );

        //extend with some dom manipulation to update the markup for jQM
        //call immediately
        function updateDatepicker(){
            $( ".ui-datepicker-header", dp ).addClass("ui-body-c ui-corner-top").removeClass("ui-corner-all");
            $( ".ui-datepicker-prev, .ui-datepicker-next", dp ).attr("href", "#");
            $( ".ui-datepicker-prev", dp ).buttonMarkup({iconpos: "notext", icon: "arrow-l", shadow: true, corners: true});
            $( ".ui-datepicker-next", dp ).buttonMarkup({iconpos: "notext", icon: "arrow-r", shadow: true, corners: true});
            $( ".ui-datepicker-calendar th", dp ).addClass("ui-bar-c");
            $( ".ui-datepicker-calendar td", dp ).addClass("ui-body-c");
            $( ".ui-datepicker-calendar a", dp ).buttonMarkup({corners: false, shadow: false}); 
            $( ".ui-datepicker-calendar a.ui-state-active", dp ).addClass("ui-btn-active"); // selected date
            $( ".ui-datepicker-calendar a.ui-state-highlight", dp ).addClass("ui-btn-up-e"); // today"s date
            $( ".ui-datepicker-calendar .ui-btn", dp ).each(function(){
                var el = $(this);
                // remove extra button markup - necessary for date value to be interpreted correctly
                el.html( el.find( ".ui-btn-text" ).text() ); 
            });
        };

        if(typeof options != 'string'){
            //update now
            updateDatepicker();

            // and on click
            $( dp ).click( updateDatepicker );
        }

        //return jqm obj 
        if(retValue){
            if(!retValue.jquery) return retValue;
        }
        return this;
    };

    //bind to pagecreate to automatically enhance date inputs   
    $( ".ui-page" ).live( "pagecreate", function(){     
        $( "input[type='date'], input:jqmData(type='date')", this ).each(function(){
            $(this).after( $( "<div />" ).datepicker({ altField: "#" + $(this).attr( "id" ), showOtherMonths: true }) );
        }); 
    });
})( jQuery );


The problem starts with the binding of the datepicker:

$( "input[type='date'], input:jqmData(type='date')", this ).each(function(){
    $(this).after( $( "<div />" ).datepicker({ altField: "#" + $(this).attr( "id" ), showOtherMonths: true);
});

It's not bound to the input element itself, but to a div that is added behind the input element. This means you should call the datepicker api methods on the div and not on the input. You can do this by

  • giving it an id
  • looking for it by its class 'hasDatepicker' (which is added automatically when the datepicker gets initialized
  • keeping a reference to it, since the .datepicker() constructor returns the instance it created

This will give you the correct lookup but - as DarthJDG pointed out - is not enough. I altered the code in a similar way, but without the condition around the updateDatepicker call. This call is also needed when the calendar is changed (e.g. setDate), causing it to be regenerated in the DOM. So if you leave it out, your calendar won't get the mobile look.

(function ($, undefined) {

    //cache previous datepicker ui method
    var prevDp = $.fn.datepicker;

    //rewrite datepicker
    $.fn.datepicker = function (options) {

        var dp = this;

        //call cached datepicker plugin
        var retValue = prevDp.apply(this, arguments);

        //extend with some dom manipulation to update the markup for jQM
        //call immediately
        function updateDatepicker() {
            $(".ui-datepicker-header", dp).addClass("ui-body-c ui-corner-top").removeClass("ui-corner-all");
            $(".ui-datepicker-prev, .ui-datepicker-next", dp).attr("href", "#");
            $(".ui-datepicker-prev", dp).buttonMarkup({ iconpos: "notext", icon: "arrow-l", shadow: true, corners: true });
            $(".ui-datepicker-next", dp).buttonMarkup({ iconpos: "notext", icon: "arrow-r", shadow: true, corners: true });
            $(".ui-datepicker-calendar th", dp).addClass("ui-bar-c");
            $(".ui-datepicker-calendar td", dp).addClass("ui-body-c");
            $(".ui-datepicker-calendar a", dp).buttonMarkup({ corners: false, shadow: false });
            $(".ui-datepicker-calendar a.ui-state-active", dp).addClass("ui-btn-active"); // selected date
            $(".ui-datepicker-calendar a.ui-state-highlight", dp).addClass("ui-btn-up-e"); // today"s date
            $(".ui-datepicker-calendar .ui-btn", dp).each(function () {
                var el = $(this);
                // remove extra button markup - necessary for date value to be interpreted correctly
                // only do this if needed, sometimes clicks are received that don't require update
                // e.g. clicking in the datepicker region but not on a button.
                // e.g. clicking on a disabled date (from next month)
                var uiBtnText = el.find(".ui-btn-text");
                if (uiBtnText.length)
                    el.html(uiBtnText.text());
            });
        };

        //update after each operation
        updateDatepicker();

        // and on click
        $(dp).click(updateDatepicker);

        //return jqm obj 
        if (retValue) {
            if (!retValue.jquery) return retValue;
        }
        return this;
    };

})(jQuery);

Another change I found useful is an extra check when stripping the button content

$(".ui-datepicker-calendar .ui-btn", dp).each(function () {
    var el = $(this);
    // remove extra button markup - necessary for date value to be interpreted correctly
    // only do this if needed, sometimes clicks are received that don't require update
    // e.g. clicking in the datepicker region but not on a button.
    // e.g. clicking on a disabled date (from next month)
    var uiBtnText = el.find(".ui-btn-text");
    if (uiBtnText.length)
        el.html(uiBtnText.text());
});

I sometimes received click events that didn't change the calendar (clicking right next to it with your mouse, touching a disabled date of the next month, ...). which made all buttons empty.


I had the same problem today :)

It have no idea what kind of object the getdate returns, probably like said a hacked date object. Easiest is just to use the already stored variables in the datepicker object.

function onSelect(dateStr,dpObject)
{
    var month = dpObject.selectedMonth
    var day = dpObject.selectedDay;
    var year = dpObject.selectedYear;
    alert(year + ":" + month  + ":" + day);


};


@mplungjan

There is no element with id 'datePicker' on this site http://jquerymobile.com/test/experiments/ui-datepicker/ The id = date.

So the error you're getting is correct. However, the method seems to return just the value of the input so instead of having this

$('#date').datepicker("getDate")

you simply can have this

$('#date').val()
0

精彩评论

暂无评论...
验证码 换一张
取 消