jQuery plugin structure
I've been working on my jQuery Modal plugin for a while now and I finally got it working great - however, I was wondering if my plugin structure and jQuery code is well coded. I'm the kind of guy who has problems sleeping at night if I'm not sure my code is completely optimal :)
Any kind of improvements / feedback is much appreciated!
(function($) {
var methods = {
init: function(options) {
return this.each(function() {
if (options) $.extend({}, settings, options);
var $this = $(this),
$title = $this.attr('title'),
$href = $($this.attr('href'));
$this.bind('click', function() {
openWindow();
return false;
});
$this.bind('open.iModal', function() { settings.onOpen() });
$this.bind('loaded.iModal', function() { settings.onLoaded() });
$this.bind('closed.iModal', function() { settings.onClose() });
var openWindow = function() {
$('body').append('<div id="iModalOverlay"></div><div id="iModalWrapper"><div id="iModalWindow"><div id="iModalLoading"></div><div id="iModalContent"><h4 class="inputBox">' + $title + '</h4></div></div><div id="iModalClose">X</div></div>');
$this.trigger('open.iModal');
$(this).iModal('resize');
if (settings.closeOnClick) {
$('#iModalOverlay').click(function() {
$(this).iModal('close');
return false;
});
}
$('#iModalClose').click(function() {
$(this).iModal('close');
return false;
});
$(window).resize(function() {
$(this).iModal('resize');
});
addContent();
}
var addContent = function() {
$('#iModalContent').hide();
$('#iModalLoading').show();
var type = /\.(gif|png|jpg|jpeg|bmp)(?:\?([^#]*))?(?:#(\.*))?$/i.test($this.attr('href')) ? 'image' : ($this.attr('href').indexOf('#') === 0) ? 'html' : 'ajax';
switch(type) {
case 'html':
$('#iModalContent').append($href);
break;
case 'ajax':
$.get("/Testing/ajax/getfile.php", { file: $href }, function(data){
$('#iModalContent').html(data);
});
break;
case 'image':
$('#iModalContent').css('padding', 0);
$('#iModalWrapper').css('padding-bottom', '2px');
var img = new Image();
$(img).load(function() {
$('#iModalContent').append(this);
}).attr('src', $this.attr('href'));
break;
}
$('#iModalContent').show();
$('#iModalLoading').hide();
$(this).iModal('resize');
if ($('#iModalContent input').length != 0) $('#iModalContent input').focus();
$this.trigger('open.iModal');
}
});
},
close: function() {
return this.each(function() {
var $this = $(this),
$href = $($this.attr('href'));
$('#modalBoxes').append($href);
$('#iModalOverlay, #iModalWrapper').remove();
$this.trigger('closed.iModal');
$this.unbind('.iModal');
});
},
resize: function() {
$('#iModalOverlay').css({
height: $(window).height() + $(window).scrollTop(),
width: $(window).width() + $(window).scrollLeft()
});
$('#iModalWrapper').css({
top: ($(window).height() - $('#iModalWrapper').outerHeight()) / 2 + $(window).scrollTop(),
left: ($(window).width() - $('#iModalWrapper').outerWidth()) / 2 + $(window).scrollLeft()
});
}
}
$.fn.iModal = function(method, options) {
settings = {
onOpen: function() {},
onLoaded: function() {},
onClose: function() {},
closeOnClick: true,
title: false
}
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else i开发者_Python百科f (typeof method === 'object' || ! method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist');
}
}
})(jQuery);
I know it's long (well, its around 1/10th the size of other modal plugins) - so I added a TL;DR code as well below:
(function($) {
var methods = {
// PUBLIC FUNCTIONS
init: function(options) {
return this.each(function() {
if (options) $.extend({}, settings, options);
var $this = $(this),
$title = $this.attr('title'),
$href = $($this.attr('href'));
// PRIVATE FUNCTIONS
var openWindow = function() {
$this.trigger('open.iModal');
addContent();
}
var addContent = function() {
$this.trigger('loaded.iModal');
}
});
},
close: function() {
return this.each(function() {
var $this = $(this),
$href = $($this.attr('href'));
$this.trigger('closed.iModal');
$this.unbind('.iModal');
});
},
resize: function() {
}
}
$.fn.iModal = function(method, options) {
settings = {
onOpen: function() {},
onLoaded: function() {},
onClose: function() {},
closeOnClick: true,
title: false
}
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || ! method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist');
}
}
})(jQuery);
Also, as you can see I have to define $this and $href in both my init() and my close() functions, is there anywhere I could define my private variables once and access them from anywhere? I've heard something about using the data() tag, but not sure how it works.
Thanks in advance :)
It looks quite good, but I would avoid hard coding any ids in a plugin. You may choose to set a default value in a settings object, and let users override that, or for example use a prefix for all ids.
Literature:
- http://addyosmani.com/blog/essentialjsdesignpatterns/
- jQuery Standards and Best Practice
- http://docs.jquery.com/JQuery_Core_Style_Guidelines
精彩评论