проблемы с пользовательским плагином jQuery - PullRequest
2 голосов
/ 14 февраля 2012

Я боролся с пользовательским плагином jQuery. Весь смысл в следующем: вы нажимаете на триггер, появляется набор инструментов. В этом конкретном наборе инструментов у вас есть одно поле ввода, в которое вы вставляете и отправляете URL Youtube или Vimeo. На основании этого URL я меняю видео, которое в данный момент находится на странице.

Проблема, с которой я сталкиваюсь, заключается в том, что, когда я нажимаю на триггер, я получаю не один, а три набора инструментов (если у меня есть 3 видео на странице, и я нажимаю первое), два набора инструментов (если у меня есть 3 видео на страницу, и я нажимаю второй), один, если я щелкаю последний (то же самое условие) - я почти уверен, что вы знаете, куда это идет.

Вот код:

(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);

Ответы [ 2 ]

1 голос
/ 14 февраля 2012

При очень быстром взгляде на код кажется, что

$('.videoPlaceholder')

и

$('.videowidget-submit')

не ограничены контекстом объекта $ (this), поэтому они регистрируютсясобытия в каждом из экземпляров на странице.Я не уверен, есть ли еще места, где это происходит.

Я использовал инструментарий JqueryUI для написания своих собственных плагинов JQuery, и его довольно приятно и легко настроить.Хорошее место для начала это http://wiki.jqueryui.com/w/page/12138135/Widget-factory

1 голос
/ 14 февраля 2012

Проблема в том, что вы не предоставляете контекст для своих селекторов, когда выбираете по классам для выполнения привязок.

$('.videowidget-submit').click(...)

Таким образом, когда у вас есть несколько элементов на странице, вы применяете свой плагин, он связывается со всеми элементами с классом "videowidget-submit" вместо только текущего экземпляра.

Добавьте контекст для следующих селекторов, например так (возможно, я забыл некоторые из них, проверьте ваш код).

Для ссылки <a>, чтобы открыть всплывающее окно:

$(this).find('.videoPlaceholder').bind('click', ...)

Для элементов внутри всплывающего окна:

widgetHtml.find('.videowidget-submit').click(...)

widgetHtml.find('.tool-video-error, .tool-video').fadeOut()

widgetHtml.find('.closeImageBox').click(...)

DEMO

...