JasonDavis
JasonDavis

Reputation: 48953

Destroy a jQuery Plugin Instance so that it can be re-instantiated again as plugins destroy function is not working?

I am building a Project Management app where a Project Task opens in a Task Modal Div when a Task is clicked on.

My Task Modal is using a single Modal in the DOM for every Task on the page. Meaning that instead of loading in all the HTML for 50 Tasks that get clicked on, instead it uses the HTML for 1 Modal and simply replaces the Task data each time a Task Modal is "open" and "closed".

In addition to changing all the Task data fields in the modal which act as placeholders. Some have to be terminated and the JavaScript re-instantiated.

Majority of my Task Data fields in the Modal use a library called X-Editable which is a jQuery In-Line-Edit library. I also have other libraries like custom scrollbars, loaders, date Pickers, etc...

All this JavaScript has to be reset as well when a Task Modal is "closed" so that when a new task is clicked to be opened, it can start out fresh replacing placeholder fields.

Also because if a Task is missing a field that the previous Task had set, I don't want the value for the previous Task record to show up on the current viewed Task Modal.

Now that I explained how the bulk of my JavaScript Task Modal functions, I can ask my question about it...

I have a Task field for setting a Due Date in which I am showing the Due Date.

The library for my DatePicker is called Zebra-Datepicker and documentation is located here: http://stefangabos.ro/jquery/zebra-datepicker/

Zebra-Datepicker GitHub page is here: https://github.com/stefangabos/Zebra_Datepicker

Near the bottom of the documentation page in the "Methods" section is a destroy() method that says this:

destroy(): Removes the plugin from an element

So when I close a Task Modal in my app, I call my function below which in trun also runs this destroy() function on the DatePicker element.

The problem is, I can then open another Task Modal and all the DOM values will be set correctly however when I go to pick a value in the DatePicker, it highlights the OLD value from the Previous Task Modal!

So apparently the DatePicker instance is NOT destroyed like it says it is!

I would greatly appreciate all help in destroying this so I can start over when a new Task Modal is launched. Please help!

I also have a JSFIddle running here http://jsfiddle.net/jasondavis/Lqwfamoc/13/ which has the library setup similar to my app except it does not have the Modal open and close stuff. It just has 1 instance of the DatePicker running. It can be used to experiment with destroying and re-instantiating a new instance of the DatePicker plugin though.

Below is some code for 2 methods I made:

  1. One is to instantiate my DueDate element with the Zebra-Datepicker plugin when a Task Modal is opened.
  2. The other is to destroy it when a Task Modal is closed. So that a new one can be instantiated again next time a new Task Modal is opened.

Method to Initialize a new instance of the Zebra-Datepicker plugin on my DueDate Task field when a new Task Modal is opened.

setUpDueDatePicker: function() {

    // Get Due Date val from DOM
    var taskDueDateVal = $('#task-modal-due-date-span').text();
    var setTaskDueDateVal = '';

    // set DueDate into cached value
    projectTaskModal.cache.taskDueDate = taskDueDateVal;

    // If a real DATE value is set in DueDate in the DOM, then set it in the DatePicker
    if(taskDueDateVal != 'None' && taskDueDateVal != '0000-00-00 00:00:00'){
        // DATE value to set the DatePicker
        setTaskDueDateVal = taskDueDateVal;
    }

    // Instantiate and setup the DatePicker plugin on our DueDate element
    $('#task-modal-due-date-span').Zebra_DatePicker({
         always_visible: $('#task-modal-due-date-cal'),
         format: 'm/d/Y',
         start_date: setTaskDueDateVal,

        /*
        Callback function to be executed when a date is selected
        The callback function takes 4 parameters:
        – the date in the format specified by the “format” attribute;
        – the date in YYYY-MM-DD format
        – the date as a JavaScript Date object
        – a reference to the element the date picker is attached to, as a jQuery object
        Methods
        */
        onSelect: function(dateInFormat, dateDefaultFormat, dateObj, datePickElem) {

            var dueDate = dateInFormat;

            console.log('Pre AJAX Due Date Save: '+dueDate);

            // Make AJAX POST to save Due Date value to the server and update DOM.
            $.ajax
            ({
                type: "post",
                url: "updateTaskDueDate",
                data: "date="+dueDate,
                success: function(result)
                {
                    console.log('SUCCESS AJAX Due Date Save: '+dueDate);

                    // UPDATE DOM with new DueDate value
                    // (Task list if it exists, Modal DueDate field, Modal DueDate Header field)
                    if(projectTaskModal.cache.isTaskListInDom){
                        projectTaskModal.updateDom.updateTaskField('list', 'dueDate', dueDate);
                    }
                    projectTaskModal.updateDom.updateTaskField('modal', 'dueDate', dueDate);

                    // Update Project-wide cached DueDate var
                    projectTaskModal.cache.taskDueDate = dueDate;

                    // Close/Hide Date Picker Calendar, until it is clicked to show and change DueDate again
                    $('#task-modal-due-date-cal').hide();
                }
            });
        },

        // Reset Due Date in DOM and save empty DueDate value on server
        onClear: function(datePickElem) {

            // Set Due Date to "None" in DOM
            var dueDate = 'None';

            // AJAX Update Due Date to remove any due dates in DB
            // set to "0000-00-00 00:00:00" or else "null"
            $.ajax
            ({
                type: "post",
                url: "updateTaskDueDate",
                data: "date=0000-00-00 00:00:00",
                success: function(result)
                {
                    console.log('SUCCESS AJAX Due Date Save: '+dueDate);

                    // UPDATE DOM Due Date fields
                    if(projectTaskModal.cache.isTaskListInDom){
                        projectTaskModal.updateDom.updateTaskField('list', 'dueDate', dueDate);
                    }
                    projectTaskModal.updateDom.updateTaskField('modal', 'dueDate', dueDate);

                    // Update Project-wide cached DueDate var
                    projectTaskModal.cache.taskDueDate = dueDate;

                    // Close/Hide Date Picker Calendar, until it is clicked to show and change DueDate again
                    $('#task-modal-due-date-cal').hide();
                }
            });
        }
     });

    // Show Date Picker Calendar when "Due Date" SPAN text is clicked on:
    $('#task-modal-due-date-span').on('click', function(){
        $('#task-modal-due-date-cal').show();
    });
},

Destroy Method to kill the DatePicker plugin instance

// When Task Modal window is CLOSED, Destroy and reset the DueDate so that when a New Task is opened in the Modal, we can setup a new DueDate DatePicker instance
destroyDueDatePicker: function() {
    alert('DESTROY Due Date picker');

     // remove the "selected" class from all cells that have it
    $('td.dp_selected', '#task-modal-due-date-cal').removeClass('dp_selected');

    // Find our DueDate DatePicker Instance
    var dueDatePicker = $('#task-modal-due-date-span');

    // Run the destroy() Method on it that is shown in the Documentation for Zebra-Datepicker library here:
    // http://stefangabos.ro/jquery/zebra-datepicker/
    // Near the bottom of page in the "Methods" section.
    // destroy(): Removes the plugin from an element
    dueDatePicker.destroy();
},

The sourcecode of the actual Zebra-Datepicker lIbrary's destroy() method:
Located here https://github.com/stefangabos/Zebra_Datepicker/blob/master/public/javascript/zebra_datepicker.src.js#L1372

/**
 *  Destroys the date picker.
 *
 *  @return void
 */
plugin.destroy = function() {

    // remove the attached icon (if it exists)...
    if (undefined !== plugin.icon) plugin.icon.remove();

    // ...and the calendar
    plugin.datepicker.remove();

    // remove associated event handlers from the document
    $(document).unbind('keyup.Zebra_DatePicker_' + uniqueid);
    $(document).unbind('mousedown.Zebra_DatePicker_' + uniqueid);
    $(window).unbind('resize.Zebra_DatePicker_' + uniqueid);

    // remove association with the element
    $element.removeData('Zebra_DatePicker');

};

Upvotes: 0

Views: 8442

Answers (1)

Lucky
Lucky

Reputation: 17345

I've tried the following code and the destroy method works fine for me,

//plugin initialization
$('#task-modal-due-date-span').Zebra_DatePicker({
....
....
});

$('#task-modal-due-date-span').on('click', function(){
    $('#task-modal-due-date-cal').show();
});

//get the Zebra-datepicker element
var datepicker = $('#task-modal-due-date-span').data('Zebra_DatePicker');
//destroys the plugin from an element
datepicker.destroy();

Check out in the Fiddle Clicking on set due date will not open the calendar since I'm calling destroy just after initialization of the plugin.

Upvotes: 4

Related Questions