我目前正在开发一个级联树状菜单。展开树项目时,会在其下方创建新的<div>
,也可以展开。我可以得到第一组<div>
来绑定并因此扩展,但我似乎无法使用“this._on”方法自动绑定新创建的div。我正在寻找类似于live(),delegate()和on()的功能。
我已在http://jsfiddle.net/vEAhq/的jsFiddle中发布了我的代码。
我在第60行的_setupEvents方法下设置了事件绑定。
回顾一下,在_create方法中调用的refresh方法中创建的元素绑定没问题。它是_expand方法中创建的元素,不像我期望的那样受到约束。
提前感谢您的时间。
$.widget( "custom.categoryMenu", {
options: {
links: null
},
_create: function() {
this.refresh();
this._on('.categoryNavigationExpandIcon', {
click: function(event) {
var $container = $(event.target).parent();
if( ($container).data('expanded') === false ) {
this._expand($container);
} else {
this._contract($container);
}
}
});
},
refresh: function() {
var $elm = this.element;
var $newElem;
var $itemTree = this.options.links;
var $itemTreeRoot = sortObj( $itemTree['1'], 'function', true );
this._setupEvents();
$.each( $itemTreeRoot, function( key, value ) {
var ID = $itemTreeRoot[key];
var label = key;
$newElem = $( '<div style="padding:8px 0;"></div>' )
.data( 'expanded', false )
.data( 'id', ID )
.data( 'level', 1 )
.addClass( 'categoryNavigationLevel1' );
$( '<div class="categoryNavigationExpandIcon"></div>' ).appendTo($newElem);
$( '<a href="index.cfm?action=products&cat=' + ID + '" rel="?cat=' + ID + '" class="categoryMenuLabel">' + label + '</a>' ).appendTo($newElem);
// Add triangle icons if there are children
if ($itemTree[ID]) {
$($newElem)
.find('.categoryNavigationExpandIcon')
.addClass('ui-icon')
.addClass('ui-icon-triangle-1-e');
}
$elm.append($newElem);
});
},
_setupEvents: function() {
var events = {
click: function( event ) {
event.preventDefault();
}
};
this._on('.categoryNavigationExpandIcon', {
click: function(event) {
var $container = $(event.target).parent();
if( ($container).data('expanded') === false ) {
this._expand($container);
} else {
this._contract($container);
}
}
});
},
_expand: function(container) {
var $elm = this.element;
var $itemTree = this.options.links;
var containerLevel = $(container).data('level');
var containerID = $(container).data('id');
var newContainerLevel = containerLevel + 1;
var $itemTreeBranch = sortObj( $itemTree[containerID], 'function', true );
$(container)
.data('expanded', true)
.find('.ui-icon-triangle-1-e')
.removeClass('ui-icon-triangle-1-e')
.addClass('ui-icon-triangle-1-se');
$.each( $itemTreeBranch, function( key, value ) {
var ID = $itemTreeBranch[key];
label = key;
$newElem = $( '<div style="padding:8px 0;"></div>' )
.data('expanded', false)
.data( 'id', ID )
.data( 'level', newContainerLevel )
.addClass( 'categoryNavigationLevel' + newContainerLevel );
$( '<div class="categoryNavigationExpandIcon"></div>' ).appendTo($newElem);
$( '<a href="index.cfm?action=products&cat=' + ID + '" rel="?cat=' + ID + '" class="categoryMenuLabel">' + label + '</a>' ).appendTo($newElem);
// Add triangle icons if there are children
if ($itemTree[ID]) {
$($newElem)
.find('.categoryNavigationExpandIcon')
.addClass('ui-icon')
.addClass('ui-icon-triangle-1-e');
}
$(container).after($newElem);
});
},
_contract: function(container) {
var containerLevel = $(container).data('level');
$(container)
.data( 'expanded', false )
.find('.ui-icon-triangle-1-se')
.removeClass('ui-icon-triangle-1-se')
.addClass('ui-icon-triangle-1-e');
$(container)
.nextUntil( '.categoryNavigationLevel' + containerLevel )
.remove();
},
destroy: function() {
$.widget.prototype.destroy.call(this);
}
});
/**
* Name: Sort Javascript Object
* Credit: Arne Martin Aurlien
* URL: http://am.aurlien.net/post/1221493460/sorting-javascript-objects
*/
sortObj = function(obj, type, caseSensitive) {
var temp_array = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (!caseSensitive) {
key = (key['toLowerCase'] ? key.toLowerCase() : key);
}
temp_array.push(key);
}
}
if (typeof type === 'function') {
temp_array.sort(type);
} else if (type === 'value') {
temp_array.sort(function(a,b) {
var x = obj[a];
var y = obj[b];
if (!caseSensitive) {
x = (x['toLowerCase'] ? x.toLowerCase() : x);
y = (y['toLowerCase'] ? y.toLowerCase() : y);
}
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
} else {
temp_array.sort();
}
var temp_obj = {};
for (var i=0; i<temp_array.length; i++) {
temp_obj[temp_array[i]] = obj[temp_array[i]];
}
return temp_obj;
};
答案 0 :(得分:13)
当您必须附加一些新创建的内容时,最好绑定文档上的事件,给定选择器或自定义事件。
例如,如果您尝试绑定给定类'.your-class'的点击:
$('.your-class').on('click', function (e) {
// ...
})
您希望将其替换为:
$(document).on('click', '.your-class', function (e) {
// ...
})
jQuery UI完全相同:
您更愿意替换:
// Here you just bind a click on the existing elements of your class
this._on('.categoryNavigationExpandIcon', {
click: function(event) {
var $container = $(event.target).parent();
if( ($container).data('expanded') === false ) {
this._expand($container);
} else {
this._contract($container);
}
}
});
人:
// Bind a custom event on the document in order to delegate this event event to the new created classes
this._on(this.document, {
'click.categoryNavigationExpandIcon': function(event) {
var $container = $(event.target).parent();
if( ($container).data('expanded') === false ) {
this._expand($container);
} else {
this._contract($container);
}
}
});
您可以在此处找到更新的JSFiddle: http://jsfiddle.net/vEAhq/7/
顺便说一下,在使用jQuery创建元素时可以跳过结束标记。
$('<div>'); // instead of $('<div></div>');