Jquery插件。每个实例的选项

时间:2016-06-06 12:21:24

标签: javascript jquery jquery-plugins

我创建了一个在同一页面内多次调用的jquery插件。每次我调用插件时,我都会传递不同的参数和一个返回元素ID的回调函数,它会作为参数传递,但我总是会收到已经应用插件的最后一个元素的ID。

我一直认为每次调用插件时都会生成一个新实例。

这是我的插件代码:

    (function ($) {
$.audioRecorder = {
    constants: {

    },
    options: {
        domain: "http://example.com",
        storageUrl: "/services/uploader/uploadtoazure",
        storageUrlIOSDevice: "/services/uploader/uploadaudiofromiosdevice",
        storageAudioContainer: null,
        storageAudioPath: null,
        storageMimeType: "audio/mpeg",
        storageExtension: "mp3",
        container: null,
        handlerInterval: null,
        callbackAudioSaved: null,
        callbackPlay: null,
        callbackStop: null,
        id: null
    },
    methods: {
        init: function (options) {
            $.extend(true, $.audioRecorder.options, options);
            window.microm = new Microm();

            $.audioRecorder.options.container = $(this);
            $.audioRecorder.methods.build();
            $.audioRecorder.methods.bind();
        },
        build: function () {
            var template = $.audioRecorder.templates.recorder.replace(/##domain##/g, $.audioRecorder.options.domain.replace('https','http'));

            $.audioRecorder.options.container.html(template);
            $.audioRecorder.methods.showRecordButton();

            if ($.audioRecorder.methods.isIOSDevice()) {
                $.audioRecorder.options.container.find(".audio-recorder-timer").hide();
            }
        },
        bind: function () {
            $.audioRecorder.options.container.find(".audio-recorder-record").click($.audioRecorder.methods.record);
            $.audioRecorder.options.container.find(".audio-recorder-stop").click($.audioRecorder.methods.stop);
            $.audioRecorder.options.container.find(".audio-recorder-uploader").change($.audioRecorder.methods.saveAudioFromFileUpload);
        },
        record: function () {
            if ($.audioRecorder.methods.isIOSDevice()) {
                $.audioRecorder.options.container.find(".audio-recorder-uploader").click();
            }
            else {
            microm.record().then(function () {
                $.audioRecorder.methods.initTimer();
                $.audioRecorder.methods.showStopButton();
                console.log('Recording...');
            }).catch(function (error) {
                console.log('error recording', error);
                });
            }
        },
        stop: function () {
            $.audioRecorder.methods.stopTimer();
            $.audioRecorder.methods.showLoading();
            microm.stop().then(function (mp3) {
                $.audioRecorder.methods.saveAudio(mp3);
                console.log('Stop record');
            });
        },
        saveAudio: function (mp3) {
            var fd = new FormData();
            fd.append('data', mp3.blob);
            fd.append('container', $.audioRecorder.options.storageAudioContainer);
            fd.append('path', $.audioRecorder.options.storageAudioPath);
            fd.append('extension', $.audioRecorder.options.storageExtension);
            fd.append('mimeType', $.audioRecorder.options.storageMimeType);

            $.ajax({
                url: $.audioRecorder.options.domain + $.audioRecorder.options.storageUrl,
                type: 'post',
                data: fd,
                processData: false,
                contentType: false,
                success: function (url) {
                    $.audioRecorder.methods.audioSaved(url);
                },
                error: function () {
                    $.audioRecorder.methods.showRecordButton();
                }
            });
        },
        saveAudioFromFileUpload: function () {
            if ($.audioRecorder.options.container.find(".audio-recorder-uploader")[0].files == null || $.audioRecorder.options.container.find(".audio-recorder-uploader")[0].files.length == 0) {
                return;
            }

            $.audioRecorder.methods.showLoading();

            var file = $.audioRecorder.options.container.find(".audio-recorder-uploader")[0].files[0];
            var fd = new FormData();
            fd.append('data', file);
            fd.append('container', $.audioRecorder.options.storageAudioContainer);
            fd.append('path', $.audioRecorder.options.storageAudioPath);
            fd.append('mimeType', $.audioRecorder.options.storageMimeType);

            $.ajax({
                url: $.audioRecorder.options.domain + $.audioRecorder.options.storageUrlIOSDevice,
                type: 'post',
                data: fd,
                processData: false,
                contentType: false,
                success: function (data) {
                    $.audioRecorder.methods.audioSaved(data.url, data.duration);
                },
                error: function () {
                    $.audioRecorder.methods.showRecordButton();
                }
            });
        },
        audioSaved: function (url, duration) {
            $.audioRecorder.methods.showRecordButton();

                    var timer = $.audioRecorder.methods.getTimer();
                    $.audioRecorder.methods.resetTimer();

            if (duration != null) {
                var seconds = duration % 60;
                var minutes = Math.floor(duration / 60);
                timer = minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
            }

                    var template = $.audioRecorder.templates.player;
                    template = template.replace(/##link##/g, url);
                    template = template.replace(/##length##/g, timer);
                    template = template.replace(/##domain##/g, $.audioRecorder.options.domain.replace('https','http'));
                    if ($.audioRecorder.options.callbackPlay != null) {
                        template = template.replace(/##callbackPlay##/g, $.audioRecorder.options.callbackPlay.name + "(event)");
                    }
                    else {
                        template = template.replace(/##callbackPlay##/g, "");
                    }
                    if ($.audioRecorder.options.callbackStop != null) {
                        template = template.replace(/##callbackStop##/g, $.audioRecorder.options.callbackStop.name + "(event)");
                    }
                    else {
                        template = template.replace(/##callbackStop##/g, "");
                    }

                    if ($.audioRecorder.options.callbackAudioSaved != null) {
                $.audioRecorder.options.callbackAudioSaved(url, template, $.audioRecorder.options.container);
                    }
                    else {
                        $.audioRecorder.options.container.append(template);
                    }
                },
        initTimer: function () {
            $.audioRecorder.methods.resetTimer();
            $.audioRecorder.options.handlerInterval = setInterval($.audioRecorder.methods.addSecondToTimer, 1000);
        },
        resetTimer: function () {
            $.audioRecorder.options.container.find(".audio-recorder-timer").text("0:00");
        },
        addSecondToTimer: function () {
            var timerText = $.audioRecorder.options.container.find(".audio-recorder-timer").text().split(":");
            var minutes = parseInt(timerText[0]);
            var seconds = parseInt(timerText[1]);
            seconds++;
            if (seconds >= 60) {
                minutes++;
                seconds = 0;
            }

            timerText = minutes + ":" + (seconds < 10 ? "0" + seconds : seconds);
            $.audioRecorder.options.container.find(".audio-recorder-timer").text(timerText);
        },
        stopTimer: function () {
            clearInterval($.audioRecorder.options.handlerInterval);
        },
        getTimer: function () {
            return $.audioRecorder.options.container.find(".audio-recorder-timer").text();
        },
        getSecondsTimer: function () {
            var timerText = $.audioRecorder.options.container.find(".audio-recorder-timer").text().split(":");
            var minutes = parseInt(timerText[0]);
            var seconds = parseInt(timerText[1]);

            return minutes * 60 + seconds;
        },
        showRecordButton: function () {
            $.audioRecorder.options.container.find(".audio-recorder-record").show();
            $.audioRecorder.options.container.find(".audio-recorder-stop").hide();
            $.audioRecorder.options.container.find(".audio-recorder-loading").hide();
        },
        showStopButton: function () {
            $.audioRecorder.options.container.find(".audio-recorder-record").hide();
            $.audioRecorder.options.container.find(".audio-recorder-stop").show();
            $.audioRecorder.options.container.find(".audio-recorder-loading").hide();
        },
        showLoading: function () {
            $.audioRecorder.options.container.find(".audio-recorder-record").hide();
            $.audioRecorder.options.container.find(".audio-recorder-stop").hide();
            $.audioRecorder.options.container.find(".audio-recorder-loading").show();
        },
        playerPlay: function (event) {
            event.stopPropagation();
            event.preventDefault();

            var player = $(event.target).closest('.audio-recorder-player');
            player.find('audio')[0].play();
            $.audioRecorder.methods.stopPlayerTimer(player);
            $.audioRecorder.methods.initPlayerTimer(player);
            $.audioRecorder.methods.showPlayerStopButton(player);
        },
        playerStop: function (event) {
            event.stopPropagation();
            event.preventDefault();

            var player = $(event.target).closest('.audio-recorder-player');
            player.find('audio')[0].pause();
            player.find('audio')[0].currentTime = 0;
            $.audioRecorder.methods.stopPlayerTimer(player);
            $.audioRecorder.methods.resetPlayerTimer(player);
            $.audioRecorder.methods.showPlayerPlayButton(player);
        },
        initPlayerTimer: function (player) {
            $.audioRecorder.methods.resetPlayerTimer(player);
            player.prop("interval", setInterval(function () { $.audioRecorder.methods.addSecondToPlayerTimer(player); }, 1000));
        },
        resetPlayerTimer: function (player) {
            player.find(".audio-recorder-player-current-seek").text("0:00");
            player.find(".audio-recorder-player-progress-bar").width(0);
        },
        addSecondToPlayerTimer: function (player) {
            if (player.find(".audio-recorder-player-current-seek").text() == player.find(".audio-recorder-player-total-time").text()) {
                $.audioRecorder.methods.stopPlayerTimer(player);
                $.audioRecorder.methods.showPlayerPlayButton(player);
                return;
            }

            var timerText = player.find(".audio-recorder-player-current-seek").text().split(":");
            var minutes = parseInt(timerText[0]);
            var seconds = parseInt(timerText[1]);
            seconds++;
            if (seconds >= 60) {
                minutes++;
                seconds = 0;
            }

            timerText = minutes + ":" + (seconds < 10 ? "0" + seconds : seconds);
            player.find(".audio-recorder-player-current-seek").text(timerText);

            // Progress bar
            var currentSecons = $.audioRecorder.methods.getSecondsPlayerTimer(player);
            var totalSecons = $.audioRecorder.methods.getSecondsTotalPlayerTimer(player);
            var progress = parseFloat(currentSecons) / parseFloat(totalSecons);
            var totalWidth = player.find(".audio-recorder-player-progress-bar-parent").width();
            player.find(".audio-recorder-player-progress-bar").width(progress * totalWidth);
        },
        stopPlayerTimer: function (player) {
            clearInterval(player.prop("interval"));
        },
        getSecondsPlayerTimer: function (player) {
            var timerText = player.find(".audio-recorder-player-current-seek").text().split(":");
            var minutes = parseInt(timerText[0]);
            var seconds = parseInt(timerText[1]);

            return minutes * 60 + seconds;
        },
        getSecondsTotalPlayerTimer: function (player) {
            var timerText = player.find(".audio-recorder-player-total-time").text().split(":");
            var minutes = parseInt(timerText[0]);
            var seconds = parseInt(timerText[1]);

            return minutes * 60 + seconds;
        },
        showPlayerPlayButton: function (player) {
            player.find(".audio-recorder-player-play").show();
            player.find(".audio-recorder-player-stop").hide();
        },
        showPlayerStopButton: function (player) {
            player.find(".audio-recorder-player-play").hide();
            player.find(".audio-recorder-player-stop").show();
        },
        isIOSDevice() {
            return navigator.platform != null && ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
        }
    },
    templates: {
        recorder: "<img src='##domain##/images/audiorecorder/audio-recorder-record.png' class='audio-recorder-record' style='float: left;' title='Grabar archivo de sonido' />" +
                "<img src='##domain##/images/audiorecorder/audio-recorder-stop.png' class='audio-recorder-stop' style='float: left;' title='Detener grabacion' />" +
                //"<img src='##domain##/images/audiorecorder/audio-recorder-loading.gif' class='audio-recorder-loading' style='float: left;' />" +
                "<span class='audio-recorder-loading' style='float: left; font-size: 12px; width: 48px; overflow: hidden; margin-top: 18px;'>Cargando...</span>" +
                "<span class='audio-recorder-timer' style='float: left; margin-top: 12px; font-size: 25px; margin-left: 10px;'>0:00</span>" + 
                "<input type='file' class='audio-recorder-uploader' style='display: none;' accept='audio/*;capture=microphone' />",
        player: "<div class='audio-recorder-player'>" +
                    "<a href='##link##' target='_blank' style='float: left;'>" +
                        "<img src='##domain##/images/audiorecorder/audio-recorder-play.png' class='audio-recorder-player-play' style='float: left;' onclick='$.audioRecorder.methods.playerPlay(event); ##callbackPlay##' title='Reproducir audio' />" +
                        "<img src='##domain##/images/audiorecorder/audio-recorder-stop.png' class='audio-recorder-player-stop' style='display: none; float: left;' onclick='$.audioRecorder.methods.playerStop(event); ##callbackStop##' title='Detener audio' />" +
                    "</a>" +
                    "<audio src='##link##'></audio>" +
                    "<span class='audio-recorder-player-current-seek' style='float: left; margin-top: 17px; margin-left: 10px;'>0:00</span>" +
                    "<div class='audio-recorder-player-progress-bar-parent' style='float: left; margin-top: 14px; margin-left: 3px; width: 204px; height: 22px; box-sizing: border-box; border: 1px solid #AAA; padding: 1px; background-color: #FFF;'>" +
                        "<div class='audio-recorder-player-progress-bar' style='float: left; height: 18px; background-color: #BCD100;font-size:1px'>&nbsp;</div>" +
                    "</div>" +
                    "<span class='audio-recorder-player-total-time' style='float: left; margin-top: 17px; margin-left: 3px;'>##length##</span>" +
                "</div>"
    }
}

// Privates

//

$.fn.audioRecorder = function (method) {
    if ($.audioRecorder.methods[method]) {
        return $.audioRecorder.methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
        return $.audioRecorder.methods.init.apply(this, arguments);
    } else {
        $.error(method + ' no definido en noteges.audio-recorder.js');
    }
};

})(jQuery的);

我以这种方式调用插件;

$("#" + ID1).audioRecorder({
            domain: 'https://example.com',
            storageUrl: "/services/uploader/uploadtoazure",
            storageAudioContainer: self.azureContainer,
            storageAudioPath: self.azureContainerAudio,
            callbackAudioSaved: audioSaved,
            callbackPlay: null,
            id: audioID
        });

$("#" + ID2).audioRecorder({
            domain: 'https://example.com',
            storageUrl: "/services/uploader/uploadtoazure",
            storageAudioContainer: self.azureContainer,
            storageAudioPath: self.azureContainerAudio,
            callbackAudioSaved: audioSaved,
            callbackPlay: null,
            id: audioID
        });

1 个答案:

答案 0 :(得分:1)

  

我一直认为每次调用插件时都会有一个新实例   生成。

您的插件函数具有新jQuery对象实例的上下文,但$.audioOptions不是其中的一部分。它是jQuery全局对象的属性,因此每次调用插件函数时都不会创建新的对象。您可以告诉这一点,因为您不得不使用$.audioOptions.methods来调用方法而不是this.record()等方法调用

每次调用插件时,您都可以重构代码以创建新对象或新实例(如果将其更改为构造函数)。然后,您可以将选项保存在新对象/实例上,从中调用方法等。

请注意,您可以将方法放在jQuery对象实例上,但这会污染它并可能覆盖jQuery方法。

$.audioRecorder = {
    /* other code */
    methods: {
       init:function(options,$element){
           this.options = $.extend(true,{},$.audioRecorder.options,options);
           this.options.container = $element;
           this.bind();
       },
       bind: function () {
           //uses arrow function to help maintain context and for less code, 
           //change if supporting older browsers
           this.options.container.find(".audio-recorder-record").click(e=>this.record());
       }
    }
};
$.fn.audioRecorder = function(options){
   //if only supposed to use a single element
   //otherwise use code in a this.each() callback
   var $element = this.first();
   var arInstance = Object.create($.audioRecorder.methods);
   arInstance.init(options,$element);
   $element.data("audioRecorder",arInstance);
   return this;
};

演示

&#13;
&#13;
(function($){

$.audioRecorder = {
        options:{},
        methods: {
           init:function(options,$element){
               this.options = $.extend(true,{},$.audioRecorder.options,options);
               this.options.container = $element;
               this.build();
               this.bind();
           },
           build:function(){
               this.options.container.append( $.audioRecorder.templates.aTemplate );
           },
           bind: function () {
               this.options.container.find("button").click(e=>this.record());
           },
           record:function(){
               console.log("Record called for id: "+this.options.id); 
           }
        },
        templates:{
           aTemplate:"<button>Hit to record</button>"
        }
    };
    $.fn.audioRecorder = function(options){
       var $element = this.first();
       var arInstance = Object.create($.audioRecorder.methods);
       arInstance.init(options,$element);
       $element.data("audioRecorder",arInstance);
       return this;
    };
})(jQuery);
          
jQuery("#container").audioRecorder({
   id:"firstRecorder"
});
jQuery("#container1").audioRecorder({
   id:"secondRecorder"
});
jQuery("#container2").audioRecorder({
   id:"thirdRecorder"
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container"></div>
<div id="container1"></div>
<div id="container2"></div>
&#13;
&#13;
&#13;