JohnnyYen
JohnnyYen

Reputation: 333

using jQuery in object-oriented way

Is it possible to achieve the following, using jQuery: I'd like to create two different objects that have different functions with the same name.

var item = new foo();
item.doSomething();
var item2 = new bar();
item2.doSomething();

Furthermore, I'd like to be able to use the created items as "regular" jQuery objects - for example, to drag&drop the items and execute the correct doSomething() function when dragging has stopped.

Upvotes: 13

Views: 33081

Answers (7)

PHearst
PHearst

Reputation: 771

This is from Building Object-Oriented jQuery Plugins

(function($){
  var MyPlugin = function(element, options){
    var elem = $(element);
    var obj = this;
    var settings = $.extend({
      param: 'defaultValue'
    }, options || {});

    // Public method - can be called from client code
    this.publicMethod = function(){
      console.log('public method called!');
    };

    // Private method - can only be called from within this object
    var privateMethod = function(){
      console.log('private method called!');
    };
  };

  $.fn.myplugin = function(options){
    return this.each(function(){
      var element = $(this);

      // Return early if this element already has a plugin instance
      if (element.data('myplugin')) return;

      // pass options to plugin constructor
      var myplugin = new MyPlugin(this, options);

      // Store plugin object in this element's data
      element.data('myplugin', myplugin);
    });
  };
})(jQuery);

Test usage

$('#test').myplugin();
var myplugin = $('#test').data('myplugin');
myplugin.publicMethod(); // prints "publicMethod() called!" to console

There's also a plugin based on this pattern, Tagger based on this pattern.

Upvotes: 3

Robert Harvey
Robert Harvey

Reputation: 180788

Not sure about the Object Orientation part, but jQuery has baked-in support for the kind of drag-and-drop capability you are describing.

Using JQuery to Add Drag and Drop Support http://geekswithblogs.net/AzamSharp/archive/2008/02/21/119882.aspx

Upvotes: 1

Koding Sykosis
Koding Sykosis

Reputation: 1

I know this question is old, but this is how I build my client side code.

I use my own oop framework to build out my controllers/apps. If I set a class as a singleton, it's executed on doc ready and serves as my entry point for the client app.

https://github.com/KodingSykosis/jOOP

Any code that needs to be globally accessible, I extend jQuery using the $.extend or $.fn.extend.

api.jquery.com/jQuery.extend

View or presentation style code, I use the jQueryUI widget factory. My controller classes are tasked with creating any elements required for a widget to instantiate. Any communication is facilitated through the use of events or callbacks.

http://api.jqueryui.com/jQuery.widget

Upvotes: 0

Dima
Dima

Reputation: 1065

<script type="text/javascript">// <![CDATA[
//Lets consider it as our class wrapper
(function( $ ) {

    $.fn.testClass = function( initvar ) {

        this.testMethod = function(status) {
            this.test = status;

            //lets call a method of a class
            this.anotherMethod();
        };

        this.anotherMethod = function() {
            alert("anotherMethod is called by object " + this.test);
        };

        this.getVars = function() {
            alert("Class var set in testMethod: I am object " + this.test + "\nClass var set in constractor: " + this.class_var);
        };

        //lets init some variables here, consider it as a class constractor
        this.class_var = initvar;

        //THIS IS VERY IMPORTANT TO KEEP AT THE END
        return this;
    };

})( jQuery );


$(function() {

    //Now lets create objects
    var object1 = $(document.body).testClass("1");
    var object2 = $(document.body).testClass("2");

    //lets call method testMethod
    object1.testMethod("1");
    object2.testMethod("2");

    //lets lets see what we have at the end
    object1.getVars();
    object2.getVars();

});
// ]]></script>

Reference: http://ajax911.com/jquery-object-oriented-plugins/

Upvotes: 2

AVProgrammer
AVProgrammer

Reputation: 1350

I prefer a simpler method than posited by JohnnyYen et al.

Basically, I create a class and assign the DOM element to a property.

eg.

/* CONSTRUCTOR: Tile */
function Tile(type, id){
    this.type = type;
    this.id = id;
    this.DOM = $('#' + id);
}

/* METHOD: nudge */
Tile.prototype.nudge = function(direction){
    var pos = this.DOM.offset();
    var css_top = this.DOM.css("top");
    var top = css_top.substring(0 , css_top.indexOf('px'));
    var css_left = this.DOM.css("left");
    var left = css_left.substring(0 , css_left.indexOf('px'));
    var width = this.DOM.width();
    var height = this.DOM.height();

    switch(direction){
    case 'up':
        this.DOM.css({ "top": (+top - 75) + "px" });
    break;
    case 'left':
        this.DOM.css({ "left": (+left - 75) + "px" });
    break;
    case 'right':
        this.DOM.css({ "left": (+left + 75) + "px" });
    break;
    case 'down':
        this.DOM.css({ "top": (+top + 75) + "px" });
    break;
    }
}

Note: this is untested code, but it illustrates my point.

Upvotes: 1

ericsoco
ericsoco

Reputation: 26253

i'm still pretty new to JS and jQuery, so feel free to shoot me down (aka 'provide constructive criticism'), but i've found that this works well for building JS objects meant to have an on-screen representation:

function SomeClass (params) {
    // other properties and functions...

    this.view = function () {
        var e = $('<div />', {
            'class': 'someClass'
        });
        return e;
    }();
}

var someClassInstance = new SomeClass(params);
$('#someClassContainer').append(someClassInstance.view);

coming from a more traditional OOP background, and being used to using the MVC pattern, this is friendly for me. any suggestions welcome...

Upvotes: 5

JohnnyYen
JohnnyYen

Reputation: 333

We've come up with a solution to the problem. It consists of 3 separate steps: first, the initial jQuery item must be created:

var item = $.create("div");

then create an instance of the javascript object you want to create and copy all of it's functions and properties to the jQuery item:

$.extend( item, new foo.bar() );

Finally, initialize the object. Note that the constructor in previous step cannot be used for this since the "this" object is different.

item.initialize();

After this, the object $(item) can be used like a regular jQuery object, plus it has functions and local variables like a regular javascript object.

item.doSomething();
var offset = $(item).offset();

So you can make DOM objects that have a "class" that can be used by jQuery. BTW, we used DUI to create namespaces.

Hopefully someone will find the solution helpful. It made our code much nicer.

Upvotes: 17

Related Questions