user1032531
user1032531

Reputation: 26281

Extending an abstract jQuery plugin

I created a jQuery plugin which queries the server via ajax and displays a popup. I then wanted another one on a different page which returns some different data and displays it. The way I implemented it, the plugin would send data indicating what page it was on to the server, the server would get the data and send back the type of data, and the client would display it as appropriate for the given type of data.

My approach obviously has a lot to be desired. Instead, is it possible to make an abstract version of the plugin, and then extend it to for each particular application so it displays it correctly (i.e. get rid of the switch statement)? Also, how can I get away from using an id on the popup (i.e. #screenshot) so each can be styled individually? Thanks

ayb={};
$("a.screenshot").screenshotPreview();

function contact(data)
{
    return '<dl><dt>Name:</dt><dd>'+data.firstname+' '+data.lastname+'</dd>'
    +'<dt>Account:</dt><dd>'+data.account_name+'</dd>'
    +'<dt>Name:</dt><dd>'+data.firstname+' '+data.lastname+'</dd>'
    +((data.title)?'<dt>Title:</dt><dd>'+data.title+'</dd>':'')
    +'<dt>User Name:</dt><dd>'+data.username+'</dd>'
    +'<dt>Password:</dt><dd>'+data.password+'</dd>'
    +'<dt>Communication Method:</dt><dd>'+data.communication_method+'</dd>'
    +((data.email)?'<dt>Email:</dt><dd>'+data.email+'</dd>':'')
    +((data.account_phone)?'<dt>Account Phone:</dt><dd>'+display_phone(data.account_phone)+'</dd>':'')
    +((data.phone)?'<dt>Direct Phone:</dt><dd>'+display_phone(data.phone)+'</dd>':'')
    +((data.mobile_phone)?'<dt>Mobile Phone:</dt><dd>'+display_phone(data.mobile_phone)+'</dd>':'')
    +((data.account_fax)?'<dt>Account Fax:</dt><dd>'+display_phone(data.account_fax)+'</dd>':'')
    +((data.fax)?'<dt>Direct Fax:</dt><dd>'+display_phone(data.fax)+'</dd>':'')
    +((data.address || data.location)?'<dt>Address:</dt><dd>'+data.address+((data.address && data.location)?'<br>':'')+data.location+'</dd>':'')
    +((data.email)?'<dt>Email:</dt><dd>'+data.email+'</dd>':'')
    +'</dl>';
}
function account(data)
{
    return '<dl><dt>Name:</dt><dd>'+data.name+'</dd>'
    +((data.phone)?'<dt>Account Phone:</dt><dd>'+display_phone(data.phone)+'</dd>':'')
    +((data.fax)?'<dt>Account Fax:</dt><dd>'+display_phone(data.fax)+'</dd>':'')
    +((data.address || data.location)?'<dt>Address:</dt><dd>'+data.address+((data.address && data.location)?'<br>':'')+data.location+'</dd>':'')
    +((data.vertical_markets)?'<dt>Primary Market:</dt><dd>'+data.vertical_markets+'</dd>':'')
    +((data.priority)?'<dt>Priority:</dt><dd>'+data.priority+'</dd>':'')
    +'</dl>';
}
function user(data)
{
    return '<dl><dt>Name:</dt><dd>'+data.firstname+' '+data.lastname+'</dd>'
    +'<dt>User Name:</dt><dd>'+data.username+'</dd>'
    +((data.phone)?'<dt>Direct Phone:</dt><dd>'+display_phone(data.phone)+'</dd>':'')
    +((data.mobile_phone)?'<dt>Mobile Phone:</dt><dd>'+display_phone(data.mobile_phone)+'</dd>':'')
    +((data.fax)?'<dt>Direct Fax:</dt><dd>'+display_phone(data.fax)+'</dd>':'')
    +((data.email)?'<dt>Email:</dt><dd>'+data.email+'</dd>':'')
    +'</dl>';
}
function getUrlVars(href)
{
    //Returns object based on variables in url.  Used to send data to GET
    var vars = {}, hash, hashes = href.slice(href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
        hash = hashes[i].split('=');
        vars[hash[0]] = hash[1];
    }
    return vars;
}


(function( $ ){
    $.fn.screenshotPreview = function() {
        //Apply to links to get a preview of the link

        //Config - Set popup's distance from the cursor
        ayb.screenshot={};
        ayb.screenshot.xOffset = 20;
        ayb.screenshot.yOffset = 10;
        ayb.screenshot.showing=false;

        this.hover(function(e)
        {
            if(!ayb.screenshot.showing){
                ayb.screenshot.title = this.title;this.title = "";//Prevent title from being displayed,and save for later to put back    
                var url=getUrlVars(this.href);
                ayb.screenshot.timeoutID=window.setTimeout(function() {
                    ayb.screenshot.showing = true;
                    url.task="getPopup";   //specify task
                    ayb.screenshot.ajax=$.ajax({
                        url:    'index.php',
                        data: url,
                        success: function(data)
                        {
                            //Determine how to display returned data
                            switch (data.type)
                            {
                                case 'contact':var string=contact(data);break;
                                case 'account':var string=account(data);break;
                                case 'user':var string=user(data);break;
                                case 'project':var string=project(data);break;
                                default:var string='Error';
                            }
                            $("body").append('<div id="screenshot">'+((ayb.screenshot.title != '')?'<h3>'+ayb.screenshot.title+'</h3>':null)+string+"</div>");                                 
                            $("#screenshot")
                            .css("top",(e.pageY - ayb.screenshot.yOffset) + "px")
                            .css("left",(e.pageX + ayb.screenshot.xOffset) + "px")
                            .fadeIn("fast");                    
                        },
                    dataType: 'json'
                    });
                },250); //Wait 1/4 of a second before requesting data from server
            }
        },
        function()
        {
            //When not hover
            if (typeof ayb.screenshot.ajax == 'object') {ayb.screenshot.ajax.abort();}
            window.clearTimeout(ayb.screenshot.timeoutID);
            this.title = ayb.screenshot.title;    
            $("#screenshot").remove();
            ayb.screenshot.showing = false;
        });    
        this.mousemove(function(e)
        {
            $("#screenshot").css("top",(e.pageY - ayb.screenshot.yOffset) + "px").css("left",(e.pageX + ayb.screenshot.xOffset) + "px");
        });
    };
})( jQuery );

Upvotes: 0

Views: 135

Answers (1)

charlietfl
charlietfl

Reputation: 171679

Several ideas that might help. First is using data- attributes in the markup:

<a href="#" class="screenshot" data-type="user">User Link</a>

Next is creating a more generic template method. The use type can be taken from the html data-type and by adding the class of same type ( or some other protocol related to type) you can have different css for different use cases

DEMO JS:

(function ($) {

    var shotTemplate = function (data, type) {
        this.shot = {
            start: '<div id="screenshot" class="' + type + '">',
            end: '</div>},'
        };
        this.user = function () { 
            /* not suggesting "data.type" protocol, was just simple for my demo*/
            return '<div class="user_class">' + data.user + '</div>';
        };
        this.contact = function () {
            return '<div class="contact_class">' + data.contact + '</div>';
        };
        this.account= function () {
            return '<div class="account_class">' + data.account + '</div>';
        };

        return this.shot.start + this[type]() + this.shot.end;

    };  



    $.fn.screenshotPreview = function () {
        return this.each(function () {
            var $el = $(this);
            /* isolate screenshot to this instance*/
            var $screenshot;
            $el.hover(function () {
                $.post(url,data,function( response){
                        $screenshot = $(shotTemplate(response, $el.data('type')));
                        $('body').append($screenshot);
                });
            }, function () {
                $screenshot.remove();
            })

        });

    };
})(jQuery);

CSS:

#screenshot.user{background:navy;color:white}
#screenshot.contact{background:#444;color:white}

DEMO: http://jsfiddle.net/wceDc/

I kept demo simple to allow focusing on concepts and not clutter code with positioning

Upvotes: 1

Related Questions