I made my first jQuery plugin attempt, but I have this problem/bug which I don't know how to work around it in a plugin.
Here is the link to see the problem - my first plugin.
Here is how you can get the bug out:
Click on the the first 'DELETE' link, then you see a popup, click 'OK', then you see a form is loaded, then click 'No'.
You can repeat the process no.1 as many times as you want.
Then you see the bug when you click on the second 'DELETE' - you will get a repeated popups depends on how many times you repeated the process no.1
So multiple occurrence happens when I hit the 'No' button on the loaded form.
But I don't know how to get rid of these multiple occurrences - it should only occur once (the popup should only happen once, when you click the second 'DELETE').
Here is the entire html and jQuery code,
$(document).ready(function(){
$('.delete-uploaded').pluginname({
deleteItem: '.item-uploaded',
deleteParent: '.items-uploaded',
wrapperParent: '.upload'
});
});
// You need an anonymous function to wrap around your function to avoid conflict
(function($){
// Attach this new method to jQuery
$.fn.extend({
// This is where you write your plugin's name
pluginname: function(options) {
//Set the default values, use comma to separate the settings, example:
var defaults = {
deleteItem: '.item-listed',
deleteParent: '.items-listed',
wrapperParent: '.upload',
}
var options = $.extend(defaults, options);
// return this.click(function(){ // original
// "this" is already a jQuery object:
// When you create the click function you can assign that element to a variable and reference it within:
var $cm = this.click(function(e){
var o = options;
var target_delete = $(this).parents(o.deleteItem); // The item for deletion, such as item held in li
var parent_delete = $(this).parents(o.deleteParent); // The parent that hold delete item, such as ul > li
var wrapper_parent = $(this).parents(o.wrapperParent); // The wrapper that hold the parent, such as div > ul > li
var target_loadin = $(this).parent();
var target_html = $(this).parent().html();
var path_load = $(this).attr('href');
var class_name = $(this).attr('class');
//alert(class_name);
alert($cm.selector);
// Load the delete form.
target_loadin.load( path_load, function(){
// When the yes button is triggered.
$("input[type=submit][name=yes]").click(function(){
// Get the path from attribute of action in the form.
var path_post = $(this).parent('form').attr('action');
//alert(path_post);
// Post the form.
$.post(path_post, $(this).serialize(), function(xml){
// Procees the form output.
//process_delete_uploaded(xml);
});
// Slide up the deleted target.
target_delete.slideUp('fast', function() {
// Remove its divs completely
target_delete.remove();
//alert($('li',parent_delete).length);
// Count how many items are left behind
if($('li',parent_delete).length == 0)
{
$('.binder-row',wrapper_parent).css({
borderBottom: '0px solid #999',
padding: '0px 0px 0px 0px'
});
}
});
return false;
});
// When the no/cancel button is triggered.
$("input[type=button][name=no]").click(function(){
// Return the html
target_loadin.html(target_html);
// Reload the delete function
$($cm.selector).pluginname({
deleteItem: o.deleteItem,
deleteParent: o.deleteParent,
wrapperParent: o.wrapperParent
});
return false;
});
});
return false;
});
}
});
//pass jQuery to the function,
//So that we will able to use any valid Javascript variable name
//to replace "$" SIGN. But, we'll stick to $ (I like dollar sign: ) )
})(jQuery);
Here is the html,
<!-- upload c1-->
<div class="upload upload-image">
<!-- binder-background -->
<div class="binder-background target-toggler">
<!-- binder-row -->
<div class="binder-row">
<a href="#" class="btn-upload btn-upload-image" name="image" rel="#" >Upload</a>
<div class="status-upload status-upload-image"></div>
</div>
<!-- binder-row -->
<!-- binder-row -->
<div class="binder-row">
<!-- items-uploaded -->
<ul class="sort items-uploaded items-uploaded-image">
<!-- item-uploaded -->
<li id="item_29" class="item-uploaded">
<!-- item-uploaded-info -->
<div class="item-uploaded-info">
<span><a href="form_image_delete.php?img_id=29" class="delete-uploaded">DELETE</a></span>
<h4>9419_169881528011_783228011_3657915_407804_n_20110330221805.jpg</h4>
</div>
<!-- item-uploaded-info -->
</li>
<!-- item-uploaded -->
<!-- item-uploaded -->
<li id="item_30" class="item-uploaded">
<!-- item-uploaded-info -->
<div class="item-uploaded-info">
<span><a href="form_image_delete.php?img_id=30" class="delete-uploaded">DELETE</a></span>
<h4>69285_4159_1_06789134_webphotoscopy2_20110330221817.jpg</h4>
</div>
<!-- item-uploaded-info -->
</li>
<!-- item-uploaded -->
</ul>
<!-- items-uploaded -->
</div>
<!-- binder-row -->
</div>
<!-- binder-background -->
</div>
<!-- upload c1-->
How can I fix it?
Thanks.
EDIT:
// When the no/cancel button is triggered.
$("input[type=button][name=no]",target_loadin).click(function(){
// The string will become ojects after spliting it into pieces with .split(),
// so you must turn the object into string again with .toString().
var selector_current = $cm.selector.split(' ').slice(-1).toString();
// Return the html
target_loadin.html(target_html);
// Reload the delete function
target_loadin.find(selector_current).pluginname({
deleteItem: o.deleteItem,
deleteParent: o.deleteParent,
wrapperParent: o.wrapperParent
});
return false;
});
When clicking `no'
you are reloading the plugin for all .delete-uploaded
elements (you are using $($cm.selector)
= $('.delete-uploaded')
not only the one clicked.
But, if we try to use target_loadin.find($cm.selector)
, when calling the plugin for only the clicked element, the selector changes to 'parent() .delete-uploaded'
which is not valid!!!
One solution is to build a selector that will not change for the clicked element:
Replace:
alert($cm.selector);
by
if($($cm.selector).length > 1)
curr_selector = $($cm.selector+':eq('+$($cm.selector).index($(this))+')')
.selector;
else
curr_selector = $cm.selector;
alert(curr_selector);
and in the 'no' function
use curr_selector
:
// When the no/cancel button is triggered.
$("input[type=button][name=no]").click(function(){
// Return the html
target_loadin.html(target_html);
// Reload the delete function
(curr_selector).pluginname({
deleteItem: o.deleteItem,
deleteParent: o.deleteParent,
wrapperParent: o.wrapperParent
});
return false;
});