selectmenu('refresh') 与 "Uncaught TypeError" 崩溃
selectmenu('refresh') crashes with "Uncaught TypeError"
在 Wordpress 网站上,我使用 jQuery 3.1.0 和 jQuery UI 1.11.4 来自 Google CDN:
function my_enqueue_scripts()
{
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
wp_deregister_script ( 'jquery' );
wp_deregister_script ( 'jquery-ui' );
wp_deregister_script ( 'jquery-migrate' );
wp_enqueue_style( 'jquery-ui-smoothness', '//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.min.css' );
wp_enqueue_script( 'jquery', '//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js' );
wp_enqueue_script( 'jquery-ui', '//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js' );
wp_enqueue_script( 'pixi-script', '//cdnjs.cloudflare.com/ajax/libs/pixi.js/3.0.11/pixi.min.js' );
wp_enqueue_script( 'utils-script', '/words/Utils.js' );
wp_enqueue_script( 'small-tile-script', '/words/SmallTile.js' );
wp_enqueue_script( 'big-tile-script', '/words/BigTile.js' );
wp_enqueue_script( 'words-script', '/words/Words.js' );
}
当我使用以下测试代码创建 jQuery UI selectmenu and then try to refresh 它时 -
HTML:
<select id="gamesMenu">
JavaScript:
"use strict";
jQuery(document).ready(function($) {
console.log('selectmenu 1');
$('#gamesMenu').selectmenu({ disabled: true });
console.log('selectmenu 2');
$('#gamesMenu').selectmenu('refresh'); // THIS CRASHES
console.log('selectmenu 3');
});
然后不幸的是它失败了:
jQuery.Deferred exception: Cannot read property 'eq' of undefined TypeError: Cannot read property 'eq' of undefined
at _getSelectedItem (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:12513:24)
at ._getSelectedItem (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:415:25)
at refresh (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:12362:40)
at .refresh (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:415:25)
at HTMLSelectElement.<anonymous> (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:508:39)
at Function.each (http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js?ver=4.5.3:368:19)
at jQuery.each (http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js?ver=4.5.3:157:17)
at jQuery.$.fn.(anonymous function) [as selectmenu] (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:494:9)
at HTMLDocument.<anonymous> (http://slova.de/words/Words.js?ver=4.5.3:400:25)
at mightThrow (http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js?ver=4.5.3:3508:29) undefined
其中指的是1.11.4/jquery-ui.js中的如下代码:
_getSelectedItem: function() {
return this.menuItems.eq( this.element[ 0 ].selectedIndex );
},
这里是 Google Chrome 浏览器中 Mac 的屏幕截图:
请问如何修复或解决这个问题?
为了在我的真实 JavaScript 代码中提供更多上下文,我通过 WebSocket 连接反复获取 JSON 数据并且必须更新 HTML select 菜单(因此呼叫 selectmenu('refresh')
:
function updateMenu() {
var yourGroup = ['<optgroup label="YOUR TURN">'];
var hisGroup = ['<optgroup label="HIS TURN">'];
for (var game in games) {
var myturn = (game.played1 < game.played2);
if (myturn) {
yourGroup.push(
'<option value="' +
game.gid +
'">Game #' +
game.gid +
'</option>'
);
} else {
hisGroup.push(
'<option value="' +
game.gid +
'">Game #' +
game.gid +
'</option>'
);
}
}
yourGroup.push('</optgroup>');
hisGroup.push('</optgroup>');
$('#gamesMenu')
.empty()
.append(yourGroup.length > 2 ? yourGroup.join('') : '')
.append(hisGroup.length > 2 ? hisGroup.join('') : '')
.selectmenu('refresh') // THIS CRASHES
.selectmenu('option', 'disabled',
yourGroup.length <= 2 && hisGroup.length <= 2);
}
$('#gamesMenu').selectmenu({
disabled: true });
select: function(e, ui) {
updateButtons();
updateBoard();
});
好的,好像是jQuery bug #10662。
我已经通过添加 <option>No games found</option>
并禁用 select 菜单来解决它,当没有其他选项时:
var noGames = (yourGroup.length <= 2 && hisGroup.length <= 2);
$('#gamesMenu')
.empty()
.append(yourGroup.length > 2 ? yourGroup.join('') : '')
.append(hisGroup.length > 2 ? hisGroup.join('') : '')
.append(noGames ? '<option>No games found</option>' : '')
.selectmenu('refresh')
.selectmenu('option', 'disabled', noGames);
我想另一个解决方法是在本地下载 1.11.4/jquery-ui.js 并添加检查:
if ( !this.menuItems || this.menuItems.length == 0) {
或等待 1.12.x 版本。
在 Wordpress 网站上,我使用 jQuery 3.1.0 和 jQuery UI 1.11.4 来自 Google CDN:
function my_enqueue_scripts()
{
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
wp_deregister_script ( 'jquery' );
wp_deregister_script ( 'jquery-ui' );
wp_deregister_script ( 'jquery-migrate' );
wp_enqueue_style( 'jquery-ui-smoothness', '//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.min.css' );
wp_enqueue_script( 'jquery', '//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js' );
wp_enqueue_script( 'jquery-ui', '//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js' );
wp_enqueue_script( 'pixi-script', '//cdnjs.cloudflare.com/ajax/libs/pixi.js/3.0.11/pixi.min.js' );
wp_enqueue_script( 'utils-script', '/words/Utils.js' );
wp_enqueue_script( 'small-tile-script', '/words/SmallTile.js' );
wp_enqueue_script( 'big-tile-script', '/words/BigTile.js' );
wp_enqueue_script( 'words-script', '/words/Words.js' );
}
当我使用以下测试代码创建 jQuery UI selectmenu and then try to refresh 它时 -
HTML:
<select id="gamesMenu">
JavaScript:
"use strict";
jQuery(document).ready(function($) {
console.log('selectmenu 1');
$('#gamesMenu').selectmenu({ disabled: true });
console.log('selectmenu 2');
$('#gamesMenu').selectmenu('refresh'); // THIS CRASHES
console.log('selectmenu 3');
});
然后不幸的是它失败了:
jQuery.Deferred exception: Cannot read property 'eq' of undefined TypeError: Cannot read property 'eq' of undefined
at _getSelectedItem (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:12513:24)
at ._getSelectedItem (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:415:25)
at refresh (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:12362:40)
at .refresh (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:415:25)
at HTMLSelectElement.<anonymous> (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:508:39)
at Function.each (http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js?ver=4.5.3:368:19)
at jQuery.each (http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js?ver=4.5.3:157:17)
at jQuery.$.fn.(anonymous function) [as selectmenu] (http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js?ver=4.5.3:494:9)
at HTMLDocument.<anonymous> (http://slova.de/words/Words.js?ver=4.5.3:400:25)
at mightThrow (http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js?ver=4.5.3:3508:29) undefined
其中指的是1.11.4/jquery-ui.js中的如下代码:
_getSelectedItem: function() {
return this.menuItems.eq( this.element[ 0 ].selectedIndex );
},
这里是 Google Chrome 浏览器中 Mac 的屏幕截图:
请问如何修复或解决这个问题?
为了在我的真实 JavaScript 代码中提供更多上下文,我通过 WebSocket 连接反复获取 JSON 数据并且必须更新 HTML select 菜单(因此呼叫 selectmenu('refresh')
:
function updateMenu() {
var yourGroup = ['<optgroup label="YOUR TURN">'];
var hisGroup = ['<optgroup label="HIS TURN">'];
for (var game in games) {
var myturn = (game.played1 < game.played2);
if (myturn) {
yourGroup.push(
'<option value="' +
game.gid +
'">Game #' +
game.gid +
'</option>'
);
} else {
hisGroup.push(
'<option value="' +
game.gid +
'">Game #' +
game.gid +
'</option>'
);
}
}
yourGroup.push('</optgroup>');
hisGroup.push('</optgroup>');
$('#gamesMenu')
.empty()
.append(yourGroup.length > 2 ? yourGroup.join('') : '')
.append(hisGroup.length > 2 ? hisGroup.join('') : '')
.selectmenu('refresh') // THIS CRASHES
.selectmenu('option', 'disabled',
yourGroup.length <= 2 && hisGroup.length <= 2);
}
$('#gamesMenu').selectmenu({
disabled: true });
select: function(e, ui) {
updateButtons();
updateBoard();
});
好的,好像是jQuery bug #10662。
我已经通过添加 <option>No games found</option>
并禁用 select 菜单来解决它,当没有其他选项时:
var noGames = (yourGroup.length <= 2 && hisGroup.length <= 2);
$('#gamesMenu')
.empty()
.append(yourGroup.length > 2 ? yourGroup.join('') : '')
.append(hisGroup.length > 2 ? hisGroup.join('') : '')
.append(noGames ? '<option>No games found</option>' : '')
.selectmenu('refresh')
.selectmenu('option', 'disabled', noGames);
我想另一个解决方法是在本地下载 1.11.4/jquery-ui.js 并添加检查:
if ( !this.menuItems || this.menuItems.length == 0) {
或等待 1.12.x 版本。