复制一个元素及其所有属性 - 更新
Copying an element with all it’s attributes - Update
更新 4
嗨@保罗。我想我知道发生了什么,我只是不知道如何解决它。
我在 touchstart 中收到的警报导致应用程序停止,当我单击“确定”时,touchend 事件已经过去。我删除了 touchstart 警报并且 touchend 警报起作用了,istouch 值为 "true"。
我添加了更多警报以查看失败的地方,发现 math.abs(e.pageX) 不是数字 - 警报显示为 NaN。 $snd.data('tx') 也显示为 "Undefined"。因此,vx 也被报告为 NaN。 ds 的值显示一个数值。
所以,我认为问题在于 $snd 是在 .on(touchstart...) 中定义的,并且不能从 .on(touchend...) 中引用。这可能是变量的范围问题吗?至少复制到搜索结果页面的原始术语和搜索结果显示相同的症状,因此触发了 onclick 处理程序,这是一个很好的进展。下面是点击处理程序的当前版本,你能告诉我我应该改变什么吗,我在 js 方面很新,这对我来说真的很有挑战性。再次感谢。
$(".wrapper") //i'm attaching all event handlers to body, so everything with .spanish class will have them attached
.on("click", ".spanish", function(e) {
e.preventDefault();
})
.on("touchstart", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
}
})
.on("touchend", ".spanish", function(e) {
if (istouch) {
alert("touchend detected istouch val = " + istouch); // shows istouch = true
var $snd = $(this);
var snd = this;
var ds = $snd.data('tstart');
alert("ds = " + ds); // shows a numeric value
if (!ds) {
return;
}
alert("math.abs e.pagex = " + Math.abs(e.pageX)); // shows NaN
alert("$snd.data('tx') = " + $snd.data('tx')); // shows "undefined"
var vx = Math.abs(e.pageX - $snd.data('tx'));
alert("vx = " + vx); // shows NaN
var vy = Math.abs(e.pageY - $snd.data('ty'));
Math.abs(e.pageY - $snd.data('ty'));
alert("vx= "+ vx +" vy= " + vy + " ds = " + ds);
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
alert("tap detected and about to call playstop");
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}
});
});
更新 3
嗨@Paul,我对你的代码做了一个小改动,我将点击处理程序应用于 .wrapper
div 而不是 Body
因为有一个主页的链接在以下情况下停止工作我应用了您的更新,主页链接现在可以正常工作了。
每个英语短语都可以翻译成 1,2 或 3 个西班牙语短语,对于任何给定的英语 div.
,所有西班牙语短语都包含在单个 .wrapper div 中
下面的示例显示了 3 个英语 div 及其西班牙语翻译。我总共有 800 多个英语短语。当用户搜索这些短语时,完整的 'english' div,包括 wrapper
div,应该被复制到搜索结果页面,看起来它被正确复制了。
<div class="english">
How old are you?
<div class="wrapper">
<a class="formal spanish" data-ignore="true" href="ageHowOldF.mp3">F: Cuántos años tiene?</a>
<a class="informal spanish" data-ignore="true" href="ageHowOldI.mp3">I: Cuántos años tienes?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
<div class="english">
When were you born?
<div class="wrapper">
<a class="formal spanish" data-ignore="true" href="ageWhenBornF.mp3">F: Cuando nació?</a>
<a class="informal spanish" data-ignore="true" href="ageWhenBornI.mp3">I: Cuando naciste?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
<div class="english">
How old was he?
<div class="wrapper">
<a class="spanish" data-ignore="true" href="ageHowOldMale.mp3">Cuántos años tenía él?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
更新 2
@Paul,如我在您回复下方的评论中所述,请在下面查看包含您的更改的完整文档就绪脚本以及匹配/将所选元素复制到空 div.
的 searchApp 脚本
这是文档就绪脚本:
jQuery(function($){
var highlight = 'yellow', origcolor = 'transparent', curSnd = null,
istouch = !!('ontouchstart' in window) || !!('ontouchstart' in document.documentElement) || !!window.ontouchstart || (!!window.Touch && !!window.Touch.length) || !!window.onmsgesturechange || (window.DocumentTouch && window.document instanceof window.DocumentTouch);
function playstop(e){
alert("Start playstop");
e.preventDefault();
var $this = $(this);
if(curSnd && curSnd.sound){
if(this === curSnd.tag){
curSnd.sound.stop();
return;
}
curSnd.sound.stop();
}
$this.stop(true, true).css({backgroundColor: highlight});
var filename = this.href.substring(this.href.lastIndexOf('/')), myMedia = new Media(
this.href,
function() {
myMedia && myMedia.release();
curSnd = myMedia = null;
$this.stop(true, true).animate({backgroundColor: origcolor}, 500);
},
function(e) {
myMedia && myMedia.release();
curSnd = myMedia = null;
$this.stop(true, true).animate({backgroundColor: origcolor}, 500);
window.console && console.log ("Audio play error - " + filename + "\ncode: " + e.code + "\nmessage: " + e.message);
}
);
alert("Start playing sound")
curSnd = {tag: this, sound: myMedia};
curSnd.sound.play();
} // End playstop
$("body") //i'm attaching all event handlers to body, so everything with .spanish class will have them attached
.on("click", ".spanish", function(e) {
e.preventDefault();
})
.on("touchstart", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
}
})
.on("touchend", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
var snd = this;
var ds = $snd.data('tstart');
if (!ds) {
return;
}
var vx = Math.abs(e.pageX - $snd.data('tx'));
var vy = 'enter code here';
Math.abs(e.pageY - $snd.data('ty'));
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}
});
});
</script>
这是search/Copy脚本
function searchApp() {
var $searchTerm = $(".searchField").val().toLowerCase(); // Convert search term to all lower case
var $searchResults = "";
document.getElementById("searchResultsDiv").innerHTML = "";
$(".english").each(function () {
if ($(this).text().toLowerCase().match($searchTerm)) { // If this specific '.english' class
$(this).clone(true, true).appendTo("#searchResultsDiv");
}
});
}; // /searchApp
更新
我想我已经定位了导致我出现问题的区域 - 即当我将一个元素复制到搜索结果页面中的空 div 时,原始元素的事件侦听器未被触发当我点击搜索结果页面时。
下面是正在复制的示例英语/西班牙语元素:
<div class="english">
How old are you?
<div class="wrapper">
<a class="formal spanish" data-ignore="true"
href="ageHowOldF.mp3">F: Cuántos años tiene?</a>
<a class="informal spanish" data-ignore="true"
href="ageHowOldI.mp3">I: Cuántos años tienes?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
下面是在英文文本中找到匹配项时复制原始元素的代码:
if ($(this).text().toLowerCase().match($searchTerm)) {
$(this).clone(true, true).appendTo("#searchResultsDiv");
}
English/Spanish 词组正确显示在搜索结果页面上,但没有响应点击。我向事件侦听器添加了一条警告消息,当我点击搜索页面时不会显示,但当我点击原始页面时会显示。
如果您有任何建议,我将不胜感激。谢谢。
更新结束
我有一个智能手机应用程序,它是一个会说话的 English/Spanish 短语手册,当用户点击一个西班牙语短语时,jQuery
会播放一个简短的 mp3 文件并且它工作正常,jQuery 播放器在文件准备好时分配。我现在创建了一个搜索功能,它可以将所有匹配的 English/Spanish 短语复制到搜索结果页面,这也能正常工作。
我遇到的问题是,当用户点击搜索结果页面上的任何西班牙语短语时,应用会调用系统声音播放器(我认为),而不是 jQuery
声音播放器和系统声音播放器显示一个音频控制栏,我不希望我的用户看到。
我能想到的都试过了,基本上有两种方法:
- 复制元素的所有属性
- 将 onclick 事件分配给搜索结果页面中的父元素
这些方法都没有解决这个问题——至少我知道没有任何方法可以解决这个问题。
我是 js/jQuery 的新手,所以如果我遗漏了一些非常明显的内容,请原谅我。
请在下面找到:
- 一个样本English/Spanish元素,有几百个
一共这些。如果
搜索匹配英文 phrase/word
- 将点击处理程序分配给
西班牙语短语
- 查找匹配元素并将其复制到
搜索结果页
SAMPLE 英语/西班牙语元素
<div class="english">
How old are you?
<div class="wrapper">
<a class="formal spanish" data-ignore="true"
href="ageHowOldF.mp3">F: Cuántos años tiene?</a>
<a class="informal spanish" data-ignore="true"
href="ageHowOldI.mp3">I: Cuántos años tienes?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
文档就绪脚本
这还可以执行更改背景颜色、检查点击与滑动等操作。
jQuery(function($) {
var highlight = 'yellow',
origcolor = 'transparent',
curSnd = null,
istouch = !!('ontouchstart' in window) || !!('ontouchstart' in document.documentElement) || !!window.ontouchstart || (!!window.Touch && !!window.Touch.length) || !!window.onmsgesturechange || (window.DocumentTouch && window.document instanceof window.DocumentTouch);
function playstop(e) {
e.preventDefault();
var $this = $(this);
if (curSnd && curSnd.sound) {
if (this === curSnd.tag) {
curSnd.sound.stop();
return;
}
curSnd.sound.stop();
}
$this.stop(true, true).css({
backgroundColor: highlight
});
var filename = this.href.substring(this.href.lastIndexOf('/')),
myMedia = new Media(
this.href,
function() {
myMedia && myMedia.release();
curSnd = myMedia = null;
$this.stop(true, true).animate({
backgroundColor: origcolor
}, 500);
},
function(e) {
myMedia && myMedia.release();
curSnd = myMedia = null;
$this.stop(true, true).animate({
backgroundColor: origcolor
}, 500);
window.console && console.log("Audio play error - " + filename + "\ncode: " + e.code + "\nmessage: " + e.message);
}
);
curSnd = {
tag: this,
sound: myMedia
};
curSnd.sound.play();
} // End playstop
$('.spanish').click(function(e) {
e.preventDefault();
}).each(function(i, snd) {
if (istouch) {
var $snd = $(snd);
snd.addEventListener('touchstart', function(e) {
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
}, false);
snd.addEventListener('touchend', function(e) {
var ds = $snd.data('tstart');
if (!ds) {
return;
}
var vx = Math.abs(e.pageX - $snd.data('tx')),
vy = `enter code here`
Math.abs(e.pageY - $snd.data('ty'));
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}, false);
}
});
});
搜索功能
function searchApp() {
// Convert search term to all lower case
var $searchTerm = $(".searchField").val().toLowerCase();
var $searchResults = "";
document.getElementById("searchResultsDiv").innerHTML = "";
$(".english").each(function() {
// If this specific '.english' class
if ($(this).text().toLowerCase().match($searchTerm)) {
// Append all HTML contents of '.english' div into $searchResults variable
$searchResults += $(this)[0].outerHTML;
}
});
// Within searchResultsDiv tag, write $searchResults variable to HTML
$("#searchResultsDiv").html($searchResults);
}; // /searchApp
更新 5
我将警报更改为 console.log。第一个测试是点击搜索结果页面上已经存在的西班牙语短语。下面是控制台日志
touchstart $snd = [object Object] index.html:67
touchend detected istouch val = true index.html:72
touchend ds = 1427885920974 index.html:76
pageX in touchend = undefined index.html:77
touchend math.abs e.pagex = NaN index.html:82
touchend $snd.data('tx') = undefined index.html:83
touchend vx = NaN index.html:85
touchend vx= NaN vy= NaN ds = 1427885920974
第二个测试是点击创建的西班牙元素之一。这是日志
touchstart $snd = [object Object] index.html:67
touchend detected istouch val = true index.html:72
touchend ds = 1427885920974 index.html:76
pageX in touchend = undefined index.html:77
touchend math.abs e.pagex = NaN index.html:82
touchend $snd.data('tx') = undefined index.html:83
touchend vx = NaN index.html:85
touchend vx= NaN vy= NaN ds = 1427885920974
它们都没有发出声音。下面是 touchstart 和 touchend 处理程序脚本,显示了我添加 console.log 语句的位置。
.on("touchstart", ".spanish", function(e) {
if (istouch) {
$snd = $(this);
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
console.log("touchstart $snd = " + $snd);
}
})
.on("touchend", ".spanish", function(e) {
if (istouch) {
console.log("touchend detected istouch val = " + istouch);
var $snd = $(this);
var snd = this;
var ds = $snd.data('tstart');
console.log("touchend ds = " + ds);
console.log("pageX in touchend = " + $snd.data('tx'));
if (!ds) {
return;
}
console.log("touchend math.abs e.pagex = " + Math.abs(e.pageX));
console.log("touchend $snd.data('tx') = " + $snd.data('tx'));
var vx = Math.abs(e.pageX - $snd.data('tx'));
console.log("touchend vx = " + vx);
var vy = Math.abs(e.pageY - $snd.data('ty'));
Math.abs(e.pageY - $snd.data('ty'));
console.log("touchend vx= "+ vx +" vy= " + vy + " ds = " + ds);
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
console.log("touchend tap detected and about to call playstop");
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}
});
});
代码中的主要问题是您将事件处理程序添加到一组对象,而不是将它们重新添加到克隆的对象。活动委托会更适合你。将您的 ${'.spanish')
事件处理程序更改为:
$("body") //i'm attaching all event handlers to body, so everything with .spanish class will have them attached
.on("click", ".spanish", function(e) {
e.preventDefault();
})
.on("touchstart", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
}
})
.on("touchend", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
var snd = this;
var ds = $snd.data('tstart');
if (!ds) {
return;
}
var vx = Math.abs(e.pageX - $snd.data('tx'));
var vy = 'enter code here';
Math.abs(e.pageY - $snd.data('ty'));
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}
});
基本上,我只是将您的函数拆分为两个单独的 jquery 事件委托函数。所有这些处理程序都将附加到 body
容器中匹配选择器 .spanish
的所有内容。您可以修改它以进行一些优化(如果您有一些 div
作为所有这些元素的包装器)。
jQuery $.on
函数可以将一些事件(touchstart
、touchend
和 click
绑定到当前存在的元素,以及那些将在未来创建,例如在克隆元素的过程中 - 它可能是最适合您的解决方案。
在此处阅读更多相关信息:http://api.jquery.com/on/
更新 4 嗨@保罗。我想我知道发生了什么,我只是不知道如何解决它。 我在 touchstart 中收到的警报导致应用程序停止,当我单击“确定”时,touchend 事件已经过去。我删除了 touchstart 警报并且 touchend 警报起作用了,istouch 值为 "true"。 我添加了更多警报以查看失败的地方,发现 math.abs(e.pageX) 不是数字 - 警报显示为 NaN。 $snd.data('tx') 也显示为 "Undefined"。因此,vx 也被报告为 NaN。 ds 的值显示一个数值。
所以,我认为问题在于 $snd 是在 .on(touchstart...) 中定义的,并且不能从 .on(touchend...) 中引用。这可能是变量的范围问题吗?至少复制到搜索结果页面的原始术语和搜索结果显示相同的症状,因此触发了 onclick 处理程序,这是一个很好的进展。下面是点击处理程序的当前版本,你能告诉我我应该改变什么吗,我在 js 方面很新,这对我来说真的很有挑战性。再次感谢。
$(".wrapper") //i'm attaching all event handlers to body, so everything with .spanish class will have them attached
.on("click", ".spanish", function(e) {
e.preventDefault();
})
.on("touchstart", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
}
})
.on("touchend", ".spanish", function(e) {
if (istouch) {
alert("touchend detected istouch val = " + istouch); // shows istouch = true
var $snd = $(this);
var snd = this;
var ds = $snd.data('tstart');
alert("ds = " + ds); // shows a numeric value
if (!ds) {
return;
}
alert("math.abs e.pagex = " + Math.abs(e.pageX)); // shows NaN
alert("$snd.data('tx') = " + $snd.data('tx')); // shows "undefined"
var vx = Math.abs(e.pageX - $snd.data('tx'));
alert("vx = " + vx); // shows NaN
var vy = Math.abs(e.pageY - $snd.data('ty'));
Math.abs(e.pageY - $snd.data('ty'));
alert("vx= "+ vx +" vy= " + vy + " ds = " + ds);
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
alert("tap detected and about to call playstop");
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}
});
});
更新 3
嗨@Paul,我对你的代码做了一个小改动,我将点击处理程序应用于 .wrapper
div 而不是 Body
因为有一个主页的链接在以下情况下停止工作我应用了您的更新,主页链接现在可以正常工作了。
每个英语短语都可以翻译成 1,2 或 3 个西班牙语短语,对于任何给定的英语 div.
下面的示例显示了 3 个英语 div 及其西班牙语翻译。我总共有 800 多个英语短语。当用户搜索这些短语时,完整的 'english' div,包括 wrapper
div,应该被复制到搜索结果页面,看起来它被正确复制了。
<div class="english">
How old are you?
<div class="wrapper">
<a class="formal spanish" data-ignore="true" href="ageHowOldF.mp3">F: Cuántos años tiene?</a>
<a class="informal spanish" data-ignore="true" href="ageHowOldI.mp3">I: Cuántos años tienes?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
<div class="english">
When were you born?
<div class="wrapper">
<a class="formal spanish" data-ignore="true" href="ageWhenBornF.mp3">F: Cuando nació?</a>
<a class="informal spanish" data-ignore="true" href="ageWhenBornI.mp3">I: Cuando naciste?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
<div class="english">
How old was he?
<div class="wrapper">
<a class="spanish" data-ignore="true" href="ageHowOldMale.mp3">Cuántos años tenía él?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
更新 2 @Paul,如我在您回复下方的评论中所述,请在下面查看包含您的更改的完整文档就绪脚本以及匹配/将所选元素复制到空 div.
的 searchApp 脚本这是文档就绪脚本:
jQuery(function($){
var highlight = 'yellow', origcolor = 'transparent', curSnd = null,
istouch = !!('ontouchstart' in window) || !!('ontouchstart' in document.documentElement) || !!window.ontouchstart || (!!window.Touch && !!window.Touch.length) || !!window.onmsgesturechange || (window.DocumentTouch && window.document instanceof window.DocumentTouch);
function playstop(e){
alert("Start playstop");
e.preventDefault();
var $this = $(this);
if(curSnd && curSnd.sound){
if(this === curSnd.tag){
curSnd.sound.stop();
return;
}
curSnd.sound.stop();
}
$this.stop(true, true).css({backgroundColor: highlight});
var filename = this.href.substring(this.href.lastIndexOf('/')), myMedia = new Media(
this.href,
function() {
myMedia && myMedia.release();
curSnd = myMedia = null;
$this.stop(true, true).animate({backgroundColor: origcolor}, 500);
},
function(e) {
myMedia && myMedia.release();
curSnd = myMedia = null;
$this.stop(true, true).animate({backgroundColor: origcolor}, 500);
window.console && console.log ("Audio play error - " + filename + "\ncode: " + e.code + "\nmessage: " + e.message);
}
);
alert("Start playing sound")
curSnd = {tag: this, sound: myMedia};
curSnd.sound.play();
} // End playstop
$("body") //i'm attaching all event handlers to body, so everything with .spanish class will have them attached
.on("click", ".spanish", function(e) {
e.preventDefault();
})
.on("touchstart", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
}
})
.on("touchend", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
var snd = this;
var ds = $snd.data('tstart');
if (!ds) {
return;
}
var vx = Math.abs(e.pageX - $snd.data('tx'));
var vy = 'enter code here';
Math.abs(e.pageY - $snd.data('ty'));
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}
});
});
</script>
这是search/Copy脚本
function searchApp() {
var $searchTerm = $(".searchField").val().toLowerCase(); // Convert search term to all lower case
var $searchResults = "";
document.getElementById("searchResultsDiv").innerHTML = "";
$(".english").each(function () {
if ($(this).text().toLowerCase().match($searchTerm)) { // If this specific '.english' class
$(this).clone(true, true).appendTo("#searchResultsDiv");
}
});
}; // /searchApp
更新
我想我已经定位了导致我出现问题的区域 - 即当我将一个元素复制到搜索结果页面中的空 div 时,原始元素的事件侦听器未被触发当我点击搜索结果页面时。
下面是正在复制的示例英语/西班牙语元素:
<div class="english">
How old are you?
<div class="wrapper">
<a class="formal spanish" data-ignore="true"
href="ageHowOldF.mp3">F: Cuántos años tiene?</a>
<a class="informal spanish" data-ignore="true"
href="ageHowOldI.mp3">I: Cuántos años tienes?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
下面是在英文文本中找到匹配项时复制原始元素的代码:
if ($(this).text().toLowerCase().match($searchTerm)) {
$(this).clone(true, true).appendTo("#searchResultsDiv");
}
English/Spanish 词组正确显示在搜索结果页面上,但没有响应点击。我向事件侦听器添加了一条警告消息,当我点击搜索页面时不会显示,但当我点击原始页面时会显示。
如果您有任何建议,我将不胜感激。谢谢。
更新结束
我有一个智能手机应用程序,它是一个会说话的 English/Spanish 短语手册,当用户点击一个西班牙语短语时,jQuery
会播放一个简短的 mp3 文件并且它工作正常,jQuery 播放器在文件准备好时分配。我现在创建了一个搜索功能,它可以将所有匹配的 English/Spanish 短语复制到搜索结果页面,这也能正常工作。
我遇到的问题是,当用户点击搜索结果页面上的任何西班牙语短语时,应用会调用系统声音播放器(我认为),而不是 jQuery
声音播放器和系统声音播放器显示一个音频控制栏,我不希望我的用户看到。
我能想到的都试过了,基本上有两种方法:
- 复制元素的所有属性
- 将 onclick 事件分配给搜索结果页面中的父元素
这些方法都没有解决这个问题——至少我知道没有任何方法可以解决这个问题。
我是 js/jQuery 的新手,所以如果我遗漏了一些非常明显的内容,请原谅我。
请在下面找到:
- 一个样本English/Spanish元素,有几百个 一共这些。如果 搜索匹配英文 phrase/word
- 将点击处理程序分配给 西班牙语短语
- 查找匹配元素并将其复制到 搜索结果页
SAMPLE 英语/西班牙语元素
<div class="english">
How old are you?
<div class="wrapper">
<a class="formal spanish" data-ignore="true"
href="ageHowOldF.mp3">F: Cuántos años tiene?</a>
<a class="informal spanish" data-ignore="true"
href="ageHowOldI.mp3">I: Cuántos años tienes?</a>
</div> <!-- End .wrapper -->
</div> <!-- End English -->
文档就绪脚本
这还可以执行更改背景颜色、检查点击与滑动等操作。
jQuery(function($) {
var highlight = 'yellow',
origcolor = 'transparent',
curSnd = null,
istouch = !!('ontouchstart' in window) || !!('ontouchstart' in document.documentElement) || !!window.ontouchstart || (!!window.Touch && !!window.Touch.length) || !!window.onmsgesturechange || (window.DocumentTouch && window.document instanceof window.DocumentTouch);
function playstop(e) {
e.preventDefault();
var $this = $(this);
if (curSnd && curSnd.sound) {
if (this === curSnd.tag) {
curSnd.sound.stop();
return;
}
curSnd.sound.stop();
}
$this.stop(true, true).css({
backgroundColor: highlight
});
var filename = this.href.substring(this.href.lastIndexOf('/')),
myMedia = new Media(
this.href,
function() {
myMedia && myMedia.release();
curSnd = myMedia = null;
$this.stop(true, true).animate({
backgroundColor: origcolor
}, 500);
},
function(e) {
myMedia && myMedia.release();
curSnd = myMedia = null;
$this.stop(true, true).animate({
backgroundColor: origcolor
}, 500);
window.console && console.log("Audio play error - " + filename + "\ncode: " + e.code + "\nmessage: " + e.message);
}
);
curSnd = {
tag: this,
sound: myMedia
};
curSnd.sound.play();
} // End playstop
$('.spanish').click(function(e) {
e.preventDefault();
}).each(function(i, snd) {
if (istouch) {
var $snd = $(snd);
snd.addEventListener('touchstart', function(e) {
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
}, false);
snd.addEventListener('touchend', function(e) {
var ds = $snd.data('tstart');
if (!ds) {
return;
}
var vx = Math.abs(e.pageX - $snd.data('tx')),
vy = `enter code here`
Math.abs(e.pageY - $snd.data('ty'));
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}, false);
}
});
});
搜索功能
function searchApp() {
// Convert search term to all lower case
var $searchTerm = $(".searchField").val().toLowerCase();
var $searchResults = "";
document.getElementById("searchResultsDiv").innerHTML = "";
$(".english").each(function() {
// If this specific '.english' class
if ($(this).text().toLowerCase().match($searchTerm)) {
// Append all HTML contents of '.english' div into $searchResults variable
$searchResults += $(this)[0].outerHTML;
}
});
// Within searchResultsDiv tag, write $searchResults variable to HTML
$("#searchResultsDiv").html($searchResults);
}; // /searchApp
更新 5 我将警报更改为 console.log。第一个测试是点击搜索结果页面上已经存在的西班牙语短语。下面是控制台日志
touchstart $snd = [object Object] index.html:67
touchend detected istouch val = true index.html:72
touchend ds = 1427885920974 index.html:76
pageX in touchend = undefined index.html:77
touchend math.abs e.pagex = NaN index.html:82
touchend $snd.data('tx') = undefined index.html:83
touchend vx = NaN index.html:85
touchend vx= NaN vy= NaN ds = 1427885920974
第二个测试是点击创建的西班牙元素之一。这是日志
touchstart $snd = [object Object] index.html:67
touchend detected istouch val = true index.html:72
touchend ds = 1427885920974 index.html:76
pageX in touchend = undefined index.html:77
touchend math.abs e.pagex = NaN index.html:82
touchend $snd.data('tx') = undefined index.html:83
touchend vx = NaN index.html:85
touchend vx= NaN vy= NaN ds = 1427885920974
它们都没有发出声音。下面是 touchstart 和 touchend 处理程序脚本,显示了我添加 console.log 语句的位置。
.on("touchstart", ".spanish", function(e) {
if (istouch) {
$snd = $(this);
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
console.log("touchstart $snd = " + $snd);
}
})
.on("touchend", ".spanish", function(e) {
if (istouch) {
console.log("touchend detected istouch val = " + istouch);
var $snd = $(this);
var snd = this;
var ds = $snd.data('tstart');
console.log("touchend ds = " + ds);
console.log("pageX in touchend = " + $snd.data('tx'));
if (!ds) {
return;
}
console.log("touchend math.abs e.pagex = " + Math.abs(e.pageX));
console.log("touchend $snd.data('tx') = " + $snd.data('tx'));
var vx = Math.abs(e.pageX - $snd.data('tx'));
console.log("touchend vx = " + vx);
var vy = Math.abs(e.pageY - $snd.data('ty'));
Math.abs(e.pageY - $snd.data('ty'));
console.log("touchend vx= "+ vx +" vy= " + vy + " ds = " + ds);
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
console.log("touchend tap detected and about to call playstop");
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}
});
});
代码中的主要问题是您将事件处理程序添加到一组对象,而不是将它们重新添加到克隆的对象。活动委托会更适合你。将您的 ${'.spanish')
事件处理程序更改为:
$("body") //i'm attaching all event handlers to body, so everything with .spanish class will have them attached
.on("click", ".spanish", function(e) {
e.preventDefault();
})
.on("touchstart", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
$snd.data({
tstart: new Date().getTime(),
tx: e.pageX,
ty: e.pageY
});
}
})
.on("touchend", ".spanish", function(e) {
if (istouch) {
var $snd = $(this);
var snd = this;
var ds = $snd.data('tstart');
if (!ds) {
return;
}
var vx = Math.abs(e.pageX - $snd.data('tx'));
var vy = 'enter code here';
Math.abs(e.pageY - $snd.data('ty'));
if (vx < 20 && vy < 20 && new Date().getTime() - ds < 400) {
playstop.apply(snd, [e]);
$snd.data({
tstart: null,
tx: null,
ty: null
});
}
}
});
基本上,我只是将您的函数拆分为两个单独的 jquery 事件委托函数。所有这些处理程序都将附加到 body
容器中匹配选择器 .spanish
的所有内容。您可以修改它以进行一些优化(如果您有一些 div
作为所有这些元素的包装器)。
jQuery $.on
函数可以将一些事件(touchstart
、touchend
和 click
绑定到当前存在的元素,以及那些将在未来创建,例如在克隆元素的过程中 - 它可能是最适合您的解决方案。
在此处阅读更多相关信息:http://api.jquery.com/on/