提问人:Alexander Farber 提问时间:10/14/2023 最后编辑:Alexander Farber 更新时间:10/15/2023 访问量:49
$(this) 未在 jQuery UI 对话框的“打开”选项中设置
$(this) not set in the jQuery UI dialog "open" option
问:
在文字游戏的底部有 4 个按钮,用于打开带有游戏字典中某些单词的 jQuery UI 对话框:
我正在尝试通过创建以下函数来简化游戏代码:
// select word using the filterFunc and then concat them all to a string
function filterWords(filterFunc) {
// the words already filtered and assigned to the dialog's innerHTML
if ($(this).html().length > 1000) {
return (ev, ui) => {};
}
// filter the keys of HASHED dictionary by calling the filterFunc on each
const filtered = Object.keys(HASHED)
.filter(word => filterFunc(word))
.reduce((result, word) => {
return result +
'<p><span class="tile">' + word + '</span> ' + HASHED[word] + '</p>'
}, '');
// return the closure expected by the dialog's "open" option
return (ev, ui) => {
$(this).html(filtered);
const title = $(this).dialog('option', 'title');
console.log(title + ': ' + filtered.length + ' chars');
};
}
我希望jQuery UI对话框“打开”选项需要一个,这就是我试图通过我的新函数给它的东西:function (ev, ui) {}
const twoDlg = $('#twoDlg').dialog({
modal: true,
appendTo: '#fullDiv',
autoOpen: false,
open: filterWords(word => word.length == 2),
buttons: {
'Close': function() {
$(this).dialog('close');
}
}
});
这是另一个对话框:
const rare2Dlg = $('#rare2Dlg').dialog({
modal: true,
appendTo: '#fullDiv',
autoOpen: false,
open: filterWords(word => word.indexOf('X') >= 0),
buttons: {
'Close': function() {
$(this).dialog('close');
}
}
});
不幸的是,现在我收到错误消息:
jquery.js:4095 Uncaught TypeError: Cannot read properties of undefined (reading 'length')
at filterWords (test?player=abcde:833:594)
at HTMLDocument.<anonymous> (test?player=abcde:835:139)
at mightThrow (jquery.js:3802:29)
at process (jquery.js:3870:12)
这向我表明这在我的关闭中是无效的。$(this).html()
有没有办法让它工作?
更新:
我准备了一个带有 3 个对话框和 3 个按钮的 jsFiddle 可以打开。该方法有效,但重复代码过多。注释掉的方法失败。filterWordsWorks()
open: filterWordsBroken(word => word.length == 2),
在相同的演示代码下面,内联到 Stackoverflow 中:
'use strict';
const HASHED = {
"one": "Word description 1",
"two": "Word description 2",
"three": "Word description 3",
"four": "Word description 4",
"five": "Word description 5",
"six": "Word description 6",
"seven": "Word description 7"
};
// select word using the filterFunc and then concat them all to a string
function filterWordsBroken(filterFunc) {
// the words already filtered and assigned to the dialog's innerHTML
if ($(this).html().length > 1000) {
return (ev, ui) => {};
}
// filter the keys of HASHED dictionary by calling the filterFunc on each
const filtered = Object.keys(HASHED)
.filter(word => filterFunc(word))
.reduce((result, word) => {
return result +
'<p>' + word + ': ' + HASHED[word] + '</p>'
}, '');
// return the closure expected by the dialog's "open" option
return (ev, ui) => {
$(this).html(filtered);
const title = $(this).dialog('option', 'title');
console.log(title + ': ' + filtered.length + ' chars');
};
}
// select word using the filterFunc and then concat them all to a string
function filterWordsWorks(filterFunc) {
return Object.keys(HASHED)
.filter(word => filterFunc(word))
.reduce((result, word) => {
return result +
'<p>' + word + ': ' + HASHED[word] + '</p>'
}, '');
}
jQuery(document).ready(function($) {
const twoDlg = $('#twoDlg').dialog({
modal: true,
autoOpen: false,
//open: filterWordsBroken(word => word.length == 2),
open: function(ev, ui) {
// prevent this code from running twice
if ($(this).html().length < 1000) {
const filtered = filterWordsWorks(word => word.length == 2);
$(this).html(filtered);
const title = $(this).dialog('option', 'title');
console.log(title + ': ' + filtered.length);
}
}
});
const threeDlg = $('#threeDlg').dialog({
modal: true,
autoOpen: false,
//open: filterWordsBroken(word => word.length == 3),
open: function(ev, ui) {
// prevent this code from running twice
if ($(this).html().length < 1000) {
const filtered = filterWordsWorks(word => word.length == 3);
$(this).html(filtered);
const title = $(this).dialog('option', 'title');
console.log(title + ': ' + filtered.length);
}
}
});
const fourDlg = $('#fourDlg').dialog({
modal: true,
autoOpen: false,
//open: filterWordsBroken(word => word.length == 3),
open: function(ev, ui) {
// prevent this code from running twice
if ($(this).html().length < 1000) {
const filtered = filterWordsWorks(word => word.length == 4);
$(this).html(filtered);
const title = $(this).dialog('option', 'title');
console.log(title + ': ' + filtered.length);
}
}
});
$('#twoBtn').button().click(function(ev) {
ev.preventDefault();
twoDlg.dialog('open');
});
$('#threeBtn').button().click(function(ev) {
ev.preventDefault();
threeDlg.dialog('open');
});
$('#fourBtn').button().click(function(ev) {
ev.preventDefault();
fourDlg.dialog('open');
});
});
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-ui@1/dist/themes/redmond/jquery-ui.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-ui@1/dist/jquery-ui.min.js"></script>
<!-- beware: the twoDlg will be empty -->
<DIV ID="twoDlg" TITLE="2 letters"></DIV>
<DIV ID="threeDlg" TITLE="3 letters"></DIV>
<DIV ID="fourDlg" TITLE="4 letters"></DIV>
<BUTTON ID="twoBtn">2 letters</BUTTON>
<BUTTON ID="threeBtn">3 letters</BUTTON>
<BUTTON ID="fourBtn">4 letters</BUTTON>
答:
这很粗糙,但在这里我创建了一个 UI 小部件方法,并将其添加到其中,然后展示了如何使用按钮调用它。filterWords
ui.dialog
或者,我添加了一个在打开对话框时调用的方法。
笔记:
- 对话框还会触发打开
filterWords
- 注释掉了你在这个演示中的很多代码,因为我没有可用的代码。
HASHED
- 添加了一个开放处理程序,如果你想朝那个方向发展
- 注意小部件代码如何使用
this.element
- 小部件文档:https://jqueryui.com/widget/
- 注意该对话框是如何可用的,正如我在带有 html 元素日志的 RAW 函数中所示
$(this)
$(this).find('.words')
- 我添加了一些额外的代码来展示您的字数统计如何成为一个选项
wordcount:2,
可能还有其他方法可以使其更有效率,但在这里,我只是在这里展示了许多可用的选项。
$.widget("ui.dialog", $.ui.dialog, {
filterWords: function(event) {
let count = this.options.wordcount;
console.log(count);
console.log('we are here!');
//console.log(this.element);
let myWords = this.element.find('.words');
console.log('words:', myWords.length, myWords.html());
$(this).trigger('open');
/*
// the words already filtered and assigned to the dialog's innerHTML
if ($(this).find('.words').html().length > 1000) {
return (ev, ui) => {};
}
// filter the keys of HASHED dictionary by calling the filterFunc on each
const filtered = Object.keys(HASHED)
.filter(word => filterFunc(word))
.reduce((result, word) => {
return result +
'<p><span class="tile">' + word + '</span> ' + HASHED[word] + '</p>'
}, '');
// return the closure expected by the dialog's "open" option
return (ev, ui) => {
$(this).html(filtered);
const title = $(this).dialog('option', 'title');
console.log(title + ': ' + filtered.length + ' chars');
};
*/
}
});
function filterWordsRaw(event, ui) {
console.log('in RAW form');
console.log($(this).find('.words').html());
// the words already filtered and assigned to the dialog's innerHTML
if ($(this).html().length > 1000) {
return (ev, ui) => {};
}
/* commented out as I do not have HASHED defined
// filter the keys of HASHED dictionary by calling the filterFunc on each
const filtered = Object.keys(HASHED)
.filter(word => filterFunc(word))
.reduce((result, word) => {
return result +
'<p><span class="tile">' + word + '</span> ' + HASHED[word] + '</p>'
}, '');
// return the closure expected by the dialog's "open" option
return (ev, ui) => {
$(this).html(filtered);
const title = $(this).dialog('option', 'title');
console.log(title + ': ' + filtered.length + ' chars');
};
*/
}
/* just to show we did this */
function handleOpen(event) {
console.log('opened');
console.log(event.target === this);
}
$(".selector").dialog({
modal: true,
appendTo: '#fullDiv',
autoOpen: false,
open: handleOpen,
wordcount: 2,
buttons: {
'Close': function() {
$(this).dialog('close');
}
}
});
$(".selector").on("dialogopen", filterWordsRaw);
$('.go-do-it').on('click', function(event) {
console.log('hi');
$(".selector").dialog("filterWords");
});
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/redmond/jquery-ui.css">
<div class="container">
<button type="button" class="go-do-it">Click</button>
</div>
<div class="selector" title="Dialog Title">
<span class="words">one fish two fish red fish blue fish</span>
</div>
<div id="fullDiv"></div>
评论
$(this).html(filtered);
this.element.html(filtered);
filterWordsWorks()
open: filterWordsBroken(word => word.length == 2),
尽可能多地使用。
这不是对问题的直接回答,而更像是您既定目标的 x/y 示例:更少的代码
由于您表示您的愿望是更少的代码,因此这里有一个更简单的示例。
在按钮和对话框中使用一些数据属性
- 请注意,对话框 3 没有,并且使用代码默认值
wordLength: 3,
- 请注意,对话框 3 没有,并且使用代码默认值
对所有按钮使用一个类,以便在代码中将它们作为目标
对所有对话框使用类,以便在代码中将它们作为目标
按钮上的 Data 属性,用于说明它指向哪个对话框。
例如,使用了一些文字(带有反引号)
`${myvar}text more text${anothervar} fun`;
从按钮单击中删除了 ,而是使用了 on 元素
preventDefault
type="button"
链接 和 - 顺序很重要,因为它不返回 jQuery,但事件处理程序会返回。
$('.my-letter-dialog') .on("dialogopen"
.dialog(
.dialog(
您可以从一个对话框创建一个对话框 - 为此添加了一个“5”字母示例,但它可能是所有对话框。
'use strict';
const HASHED = {
"one": "Word description 1",
"two": "Word description 2",
"three": "Word description 3",
"four": "Word description 4",
"five": "Word description 5",
"six": "Word description 6",
"seven": "Word description 7"
};
jQuery(function($) {
function filterFunc(word, len) {
//console.log(word, len, word.length == len);
return word.length == len;
}
$('.my-letter-dialog')
.on("dialogopen", function(event, ui) {
let elWLen = $(this).data('wordlength');
let wordLen = !!elWLen ? elWLen : $(this).dialog("option", "wordLength");
console.log(wordLen);
if ($(this).html().length > 1000) {
return (ev, ui) => {};
}
const filtered = Object.keys(HASHED)
.filter(word => filterFunc(word, wordLen))
.reduce((result, word) => {
return `${result}<p>${word}:${HASHED[word]}</p>`
}, '');
//console.log('filtered:', filtered)
$(this).html(filtered);
const title = $(this).dialog('option', 'title');
const newTitle = `${title}:${filtered.length} chars`;
$(this).dialog('option', 'title', newTitle);
})
.dialog({
modal: true,
autoOpen: false,
wordLength: 3,
filterFunc: filterFunc
});
$('.my-letter-button').button()
.on("click", function(ev) {
const targ = $(this).data('targetselector');
$(targ).dialog('open');
});
});
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-ui@1/dist/themes/redmond/jquery-ui.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-ui@1/dist/jquery-ui.min.js"></script>
<!-- beware: the twoDlg will be empty -->
<div class="my-letter-dialog" id="twoDlg" data-wordlength="2" title="2 letters"></div>
<div class="my-letter-dialog" id="threeDlg" title="3 letters"></div>
<div class="my-letter-dialog" id="fourDlg" data-wordlength="4" title="4 letters"></div>
<button class="my-letter-button" type="button" id="twoBtn" data-targetselector="#twoDlg">2 letters</button>
<button class="my-letter-button" type="button" id="threeBtn" data-targetselector="#threeDlg">3 letters</button>
<button class="my-letter-button" type="button" id="fourBtn" data-targetselector="#fourDlg">4 letters</button>
评论
$(this).data
word=>word.indexOf('Q')>=0
word=>word.indexOf('X')>=0
this
上一个:JQuery 拆分 div 问题
评论
open: filterWords(word => word.indexOf('X') >= 0),
将结果返回到选项 - 您可能想要(不要太仔细查看)filterWords(word => word.indexOf('X') >= 0)
open:
open: () => filterWords(word => word.indexOf('X') >= 0),
filterWords
open: function( event, ui ) {}
ui
this
filterWords
function( event, ui ) {}