Reputation: 152
I've been struggling with a custom jQuery plugin. The entire point of it is the following: you click the trigger, a toolbox comes up. In that specific toolbox you have one input field in which you paste and submit a Youtube or Vimeo URL. Based on that URL I'm changing the video that's currently on the page.
The issue I'm having is that when I click the trigger, I get not one, three toolboxes ( if I have 3 videos on the page and I click the first one ), two toolboxes ( if I have 3 videos on the page and I click the second one ), one if I click the last one ( same condition ) - I'm pretty sure you know where this is going.
Here's the code:
(function($) {
$.fn.videowidget = function() {
return this.each(function(){
// declare variables
var parent = $(this);
var thisPos = $(this).offset();
var widgetHtml = jQuery('<div class="tool-video"><ul><li><a href="#tool-video1">Video</a></li></ul>' +
'<div id="tool-video1">' +
'<form id="tool-video-form" action="#" method="post">' +
'<label for="tool-video-url">Please enter the URL of your video ( only Youtube or Vimeo accepted )</label>' +
'<input type="text" id="tool-video-url" name="tool-video-url" value="" class="marginFive">' +
'<a href="#submitVideo" class="videowidget-submit btn btn-success">Submit</a>' +
'<div class="tool-video-error"></div>' +
'</form>' +
'</div>' +
'<a href="#close" class="closeImageBox">Close</a>' +
'<a href="#drag" class="dragHandler" title="Drag me !!!">Draggable</a>' +
'</div>');
// check if the containing div has the class 'w-video'
if($(this).hasClass('w-video')) {
$(this).append('<a href="#video" class="videoPlaceholder">Video placeholder</a>');
$('.videoPlaceholder').bind('click', function() {
// insert the video widget and apply the required settings ( positioning, drag, tabs )
widgetHtml.appendTo('body').css(thisPos).fadeIn().draggable({handle: 'a.dragHandler', cursor: 'move'}).tabs();
$('.videowidget-submit').click(function(){
// value of the submitted url
var url = $(this).prev('input').val();
// regex to match provider
var provider = url.match(/(?:http:\/\/)?(:?www.)?(\w*)/)[2], id;
if(provider == "youtube") {
id = url.match(/(?:http:\/\/)?(?:www.)?(\w*).com\/.*v=(\w*)/)[2];
// remove the curent iframe and replace it with the one bellow using the ID of the submitted URL
var youtubeTemplate = '<iframe width="460" height="259" src="http://www.youtube.com/embed/'+ id +'?wmode=opaque" frameborder="0" allowfullscreen></iframe>';
parent.find('iframe').remove();
parent.append(youtubeTemplate);
$('.tool-video-error, .tool-video').fadeOut();
return false;
} else if (provider == "vimeo") {
id = url.match(/(?:http:\/\/)?(?:www.)?(\w*).com\/(\d*)/)[2];
// remove the curent iframe and replace it with the one bellow using the ID of the submitted URL
var vimeoTemplate = '<iframe src="http://player.vimeo.com/video/'+ id +'?wmode=opaque" width="460" height="259" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>';
parent.find('iframe').remove();
parent.append(vimeoTemplate);
$('.tool-video-error, .tool-video').fadeOut();
return false;
} else if (provider == "youtu") {
id = url.match(/(?:http:\/\/)?(?:www.)?(\w*).be\/*(\w*)/)[2];
// remove the curent iframe and replace it with the one bellow using the ID of the submitted URL
var youtubeTemplate = '<iframe width="460" height="259" src="http://www.youtube.com/embed/'+ id +'?wmode=opaque" frameborder="0" allowfullscreen></iframe>';
parent.find('iframe').remove();
parent.append(youtubeTemplate);
$('.tool-video-error, .tool-video').fadeOut();
return false;
} else {
// throw error if the submitted URL doesn't match youtube or vimeo
$('.tool-video-error').html('Error: The URL you submitted doesn\'t appear to be valid ').fadeIn();
}
return false;
});
// close the toolbox
$('.closeImageBox').click(function(){
$(this).parent().fadeOut();
return false;
});
return false;
});
} else {
// do nothing
}
});
};
})(jQuery);
Upvotes: 2
Views: 122
Reputation: 2078
From a very quick look at the code it seems that
$('.videoPlaceholder')
and
$('.videowidget-submit')
are not limited to the context of the $(this) object so they are registering the events on each of the instances on the page. im not sure if there are more locations where this is happening as well.
I have used the JqueryUI toolkit to write my own JQuery Plugins and its quite nice and easy to set up. A nice place to start with this is http://wiki.jqueryui.com/w/page/12138135/Widget-factory
Upvotes: 1
Reputation: 30666
The problem is that you don't provide a context for your selectors when you select by class to do the bindings.
$('.videowidget-submit').click(...)
So when you have several elements in the page onto you apply your plugin, it binds to all elements with class "videowidget-submit" instead of just the current instance.
Add a context to the followin selectors, like this (I may have forgotten some, check you code).
For the <a>
link to open the popup:
$(this).find('.videoPlaceholder').bind('click', ...)
For the elements inside the popup:
widgetHtml.find('.videowidget-submit').click(...)
widgetHtml.find('.tool-video-error, .tool-video').fadeOut()
widgetHtml.find('.closeImageBox').click(...)
Upvotes: 1