17

I have two divs in my app and I want them to have custom functions with the same signature, but with different actions, so that I could store the "current" div in a variable, and just call something like:

myCurrentDiv.theFunction(someEventData);
and have the corresponding methods fired up.

How can I do that using jQuery?

I tried doing something like:

$("#myFirstDiv").theFunction = function() {
    alert("theFunction on firstDiv");
}
$("#mySecondDiv").theFunction = function() {
    alert("theFunction on secondDiv");
}

6 Answers 6

47

jQuery's philosophy is opposite to what you want: jQuery doesn't extends any existent types/objects with new attributes or methods; it implements all inside itself.

But if you want to do it with jQuery, you have few different ways:

  1. JavaScript way:

    $("#mySecondDiv")[0].theFunction = function(a, b) { /* ... */ }
    
  2. jQuery.data:

    $("#mySecondDiv").data({ theFunction: function(a, b) { /* ... */ } });
    $("#mySecondDiv").data("theFunction")(1, 2)
    
  3. Custom event:

    $("#mySecondDiv").bind('my-event', function(event, a ,b) { /* ... */ });
    $("#mySecondDiv").trigger('my-event', [1, 2]);
    
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the reply. But is there a way to do what i want to do (i.e. bind different logic to functions with the same signature) using the "true" jQuery philosphy? In other words, should i probably write a plugin that would introduce my own <code><pre>.myMethod()</pre><code> method, and then bind actions to my divs somehow like this: <code><pre> $("div_one").myMethod(someEventData, function(){/* */}); </pre></code>
Yes, there is true jQuery way (even 2 ways): simple plugin dev guide and ui plugin dev guide
Is 1. Javascript way considered bad practice? If so what are the reasons? Thanks.
3

You can use jQuery.data to store data associated with a specific element.

For example:

var div = $("#myFirstDiv")[0];
jQuery.data(div, "theFunction", function() {
    alert("theFunction on firstDiv");
});

Comments

3

Looks like what you want is a custom event in jquery...

$('#myFirstDiv').bind('theFunction', function(e) {
  alert('theFunction on firstDiv');
});

$('#mySecondDiv').bind('theFunction', function(e) {
  alert('theFunction on firstDiv');
});

$('#myFirstDiv').trigger('theFunction');

Here's a working fiddle to show you the example: http://jsfiddle.net/XkutP/

1 Comment

You can't return values from an event; it's not the same thing.
1

You can also try this , it's a bit ugly but it works :)

The custom object :

$.fn.epicModule = function (pMessage) {

    var object = $(this)[0];

    object.__construct = function (pMessage) {
        //TODO
        this.message = pMessage;
    }

    object.callMeDirectly = function () {
        alert(this.message);
    }

    object.__construct(pMessage);
}

Init Module :

$(".myHtmlEl").epicModule("Hallo World");

Calling the function :

$(".myHtmlEl")[0].callMeDirectly();

Comments

0

Use .bind and a custom function then .trigger to invoke the function.

1 Comment

Sorry, i forgot to mention. I did try .bind and .live, but for some reason, i fail to pass the eventdata. I.e. i want to be able to call .theFunction(eventData) and be able to access the object in the function body.
0

Build a Super-jQuery object

You can use also use $.fn.extend() to bind multiple methods (functions) at once . . . and if you really wanna get into it, you can use $.fn.extend() to recreate the jQuery elements as powerfully customized objects which can then be used to automate and manage DOM elements that are (logically/virtually) part of the same object or tool. (PS: I made up that "Super-jQuery" phrase--that's not real jargon . . . well, maybe it is now.)

The one I'm working on now is an Excel file uploader. I'll recreate/copy some of it here to give you an idea:


HTML

<div id="uploader" class="uploader">

            <div class="uploader-item-title uploader-item title">
                <span class="title-item-value title-item value">
                    Excel File Uploader
                </span>                
            </div>
            <div class="uploader-item-subtitle uploader-item subtitle">
                <span class="subtitle-item-value subtitle-item value">
                    Uploads Excel files
                </span>
            </div>

            <div id="formatError" style="width:100%;">
                <div class="error-message">
                    <!-- General-purpose error-message container (registered on server-side) -->
                </div>
            </div>

            <div id="messagebox" class="uploader-item-messagebox uploader-item messagebox hidden" style="width:100%;">
                <span class="messagebox-item-value messagebox-item value">
                    <!-- Enter any messages/alerts here that you would like to display to the user -->
                </span>
            </div>

            <div id="dropzone" dropzone="copy f:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" class="uploader-item-dropzone uploader-item dropzone">
                <span class="dropzone-item-notes dropzone-item notes">
                    Drag and drop your Excel file(s) here to begin the upload process.
                </span>

                <div id="fileSummaryTable" class="dropzone-item-filesummary dropzone-item filesummary hidden">
                    <table class="filesummary-item-table filesummary-item table">
                        <!-- Display excel file information here. -->
                    </table>
                </div>

                <div id="pbar" class="dropzone-item-pbar dropzone-item pbar hidden">
                    <div class="pbar-item-filler pbar-item filler">
                    </div>
                </div>
            </div>
    <div id="fallbackUploader" class="uploader-item-fallbackuploader uploader-item fallbackuploader invisible">
                <!-- some asp code you don't need to see :) -->
            </div>
</div>

Javascript

var oUploader = (function () {

    function oUploader(opts) { // primary object constructor

            var primaryOpts = opts || {}; // Optional arguments
            var superObj_primary = $('#uploader'); // primary super object
            var that = this;

            var superObj_secondary = (function () { 
                function superObj_secondary(secondaryOpts) { // secondary object constructor

                    // =================================================================================
                    // step 10 = get the default options' values
                    // =================================================================================
                    var self = this,
                        o = secondaryOpts || {},
                        title_val = o.title || 'Excel File Uploader',
                        subtitle_val = o.subtitle || 'Uploads Excel files',
                        notes_val = o.notes || 'Drag and drop your Excel file(s) here to begin the upload process.';

                    // =================================================================================
                    // step 20 = create your public properties and children here.
                    // =================================================================================
                    self.dropzone = $('.uploader-item-dropzone');
                    self.dropzone.pbar = $('.dropzone-item-pbar');
                    self.dropzone.fileSummaryTable = $('#fileSummaryTable');
                    self.fallbackUploader = $('#fallbackUploader');
                    self.messagebox = $('.uploader-item-messagebox');


                    // =================================================================================
                    // step 30 = create your private properties and children here.
                    // =================================================================================
                    var progress_ele = self.dropzone.pbar.children('.pbar-item-filler'), // inner-progressbar element
                        fileSummaryTable_table_ele = self.dropzone.fileSummaryTable.children('table.filesummary-item-table'), // inner table for the file summary table
                        title_ele = $('.uploader-item-title'), // title container for the main uploader object
                        title_value_ele = title_ele.children('.title-item-value'), // inner value object for the title
                        subtitle_ele = $('.uploader-item-subtitle'), // subtitle container for the main uploader object
                        subtitle_value_ele = subtitle_ele.children('subtitle-item-value'), // inner value object for the subtitle
                        notes_value_ele = self.dropzone.children('.dropzone-item-notes'), // element containing the notes text
                        messagebox_ele = $('.uploader-item-messagebox'), // element containing the message/alert container
                        messagebox_value_ele = messagebox_ele.children('.messagebox-item-value'); // element containing the message/alert text

                    // =================================================================================
                    // step 30 = create your public get/set functions for private properties
                    // =================================================================================
                    // ------------------------------------------------------------
                    // get/set function for private properties of uploader
                    // ------------------------------------------------------------
                    Object.defineProperties(superObj_primary,
                        {
                            // gets or sets the title of the uploader
                            'title': {  
                                'get': function () { return title_value_ele.text(); },
                                'set': function (val) { title_value_ele.text(val); }
                            },
                            // gets or sets the sub-title of the uploader
                            'subtitle': { 
                                'get': function () { return subtitle_value_ele.text(); },
                                'set': function (val) { subtitle_value_ele.text(val); }
                            },
                            // either (1) gets the msg value, (2) sets the msg and grows 
                            //      in the container, or (3) clears the msg value and 
                            //      shrinks out the container.
                            'msg': {
                                'get': function () { return messagebox_value_ele.text(); },
                                'set': function (val) {
                                    if (val.length) {
                                        messagebox_value_ele.text(val);
                                        messagebox_ele.xGrowIn(null,null,function () { // fadeObj = custom jQuery plugin created elsewhere
                                            messagebox_value_ele.fadeObj('show',100); // fadeObj = custom jQuery plugin created elsewhere
                                        });
                                    } else {
                                        messagebox_value_ele.fadeObj('invisible',100, function () {
                                            messagebox_ele.xShrinkOut(null,function () {
                                                messagebox_value_ele.text('.');
                                            });
                                        });
                                    }
                                }
                            }
                        });


                    // ------------------------------------------------------------
                    // get/set function for progressbar object
                    // ------------------------------------------------------------
                    Object.defineProperties(self.dropzone.pbar,
                        {
                            // gets or sets the width and data-progress attribute of the inner progress bar.
                            'progress': { 
                                'get': function () { return (parseInt(Math.round(progress_ele.attr('aria-valuenow'))) || 0); },
                                'set': function (val) { progress_ele.progressbar({ value: Math.round(val) }); }
                            }
                        });


                    // =================================================================================
                    // step 40 = create your public methods here.
                    // =================================================================================
                    // ------------------------------------------------------------
                    // hide all of the primary uploader elements and show the fallback elements.
                    // ------------------------------------------------------------
                    self.switchToFallback = function () {
                        // hide the primary uploader elements
                        self.dropzone.addClass('hidden');
                        self.dropzone.fileSummaryTable.addClass('hidden');
                        self.dropzone.pbar.addClass('hidden');
                        // show the fallback uploader elements
                        self.fallbackUploader.removeClass('invisible');
                    };

                    // ------------------------------------------------------------
                    // show the primary dropzone and add the necessary event listeners
                    // ------------------------------------------------------------
                    self.enableDropzone = function () {
                        self.dropzone.removeClass('hidden');
                        // init event handlers
                        self.dropzone.addEventListener("dragenter", dragEnter, false);
                        self.dropzone.addEventListener("dragexit", dragExit, false);
                        self.dropzone.addEventListener("dragleave", dragExit, false);
                        self.dropzone.addEventListener("dragover", dragOver, false);
                        self.dropzone.addEventListener("drop", drop, false);

                        // define drag and drop events
                        function dragEnter(evt) {
                            evt.stopPropagation();
                            evt.preventDefault();
                        }
                        function dragExit(evt) {
                            evt.stopPropagation();
                            evt.preventDefault();
                            self.dropzone.removeClass("active-dropzone");
                        }
                        function dragOver(evt) {
                            evt.stopPropagation();
                            evt.preventDefault();
                            self.dropzone.addClass("active-dropzone");
                        };
                        function drop(evt) {
                            evt.stopPropagation();
                            evt.preventDefault();

                            self.dropzone.removeClass("active-dropzone");
                            superObj_primary.msg = ''; // hide any messages.
                            var files = evt.dataTransfer.files;
                            var count = files.length;

                            // Only call the handler if 1 file was dropped.
                            if (count == 1) {
                                handleFiles(files);
                            }
                            else if (count > 1) {
                                // still working on this part :-/
                            }
                        }

                    };

                    // ------------------------------------------------------------
                    // Method to fill the pbar to the max value (i.e., 100%)
                    // ------------------------------------------------------------
                    self.dropzone.pbar.complete = function () {
                        progress_ele.progressbar({ value: 100 });
                    };

                    // ------------------------------------------------------------
                    // Check if FileAPI and XmlHttpRequest.upload are supported.
                    // ------------------------------------------------------------
                    self.hasDndSupport = function () {
                        return (window.File && window.FileReader && window.FileList && window.Blob && new XMLHttpRequest().upload);
                    };
                };

                return superObj_secondary;
            })();

            return $.fn.extend(superObj_primary, new superObj_secondary());


        };

        return oUploader;
    })();

    var uploader = new oUploader(); // now we just init the new object and there we go. You can go to your console and try out the commands.
// **Note: If you are doing this in JsFiddle, you'll have to change the scope of the browser console from "<top frame>" to "result( fiddle.jshell.net/)". 

Additional Automation

This object works as long as I build the corresponding HTML objects, but usually when I'm done building these, I'll add an additional section to them wherein I create all the HTML components via javascript during the object's construction. The purpose for that, of course, is to make the tool more easily deploy-able.

2 Comments

What happens if you have a few of these in same page? if you want to use an external trigger (button click) to access an specific instance of uUploader and manipulate its data?
Oh boy. I haven't looked at this in a while. There are probably better methods to accomplish a file loader these days, but to answer your question I would say you would need to encapsulate the references somehow. Perhaps by padding in a selector or container object to define a scope of elements in the DOM.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.