我创建了一个在同一页面内多次调用的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'> </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
});
答案 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;
};
演示
(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;