我遇到了Dojo 1.10的问题,需要一些关于如何找出罪魁祸首的建议。我有一个自定义小部件,TaskButton,实现onMouseDown,onMouseUp和onClick方法。这三个都有记录声明。始终会调用onMouseDown和onMouseUp,并在控制台中显示正确的时间及其日志语句。但是,尽管反复单击TaskButton,有时仍然无法调用onClick。大多数时候在TaskButton外部点击然后返回它内部使得onClick工作但并非总是如此。当没有调用onClick时,它的日志语句不会显示在控制台中。
TaskButton.js自定义小部件
define([
"dojo/_base/declare",
"dojo/_base/event",
"dojo/_base/lang",
"dojo/dom-class",
"dojo/dom-construct",
"dojo/mouse",
"dojo/on",
"dojo/query",
"dojo/topic",
"dijit/Menu",
"dijit/MenuItem",
"dijit/MenuSeparator",
"dijit/PopupMenuItem",
"dijit/popup",
"dijit/Tooltip",
"dijit/Tree",
"dijit/tree/ForestStoreModel",
"dijit/registry",
"dijit/form/Button",
"dijit/_WidgetBase",
"dijit/_OnDijitClickMixin",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojo/text!./templates/TaskButton.html"
], function(declare, event, lang, domClass, domConstruct, mouse, on, query, topic, Menu, MenuItem, MenuSeparator, PopupMenuItem,
Popup, Tooltip, Tree, ForestStoreModel, registry, button, _WidgetBase, _OnDijitClickMixin, _TemplatedMixin, _WidgetsInTemplateMixin, template){
return declare("TaskButton", [_WidgetBase, _OnDijitClickMixin, _TemplatedMixin, _WidgetsInTemplateMixin, Menu], {
scene:0,
sceneId:0,
target:"",
state:"pending",
cloudCover: false,
cloudPercentage: 0,
targetInterest: false,
hsv: false,
previousState:"pending",
backgroundcolor:"#414141",
templateString:template,
baseClass: "TaskButton",
innerNode:undefined,
cm:null,
theTask:null,
eventHandle:null,
postCreate: function()
{
// Get a DOM node reference for the root of our widget
var domNode = this.domNode;
this.innerNode = domNode.firstChild.nextElementSibling.firstElementChild;
domClass.replace(this.innerFill, "task"+this.state+"Background", "task"+this.state+"Background");
if (this.cloudCover && ((this.state === "Ready") || (this.state === "Unassigned"))) {
domClass.replace(this.innerFill, "task"+"Red"+"Background", "task"+this.state+"Background");
}
this.previousState = this.state;
console.log("getting context menu for Scene-" + this.scene + "ContextMenu");
cm = registry.byId("Scene-" + this.scene + "ContextMenu");
this.own(
on(domNode, "contextmenu", lang.hitch(this, "_showContextMenu"))
);
this.inherited(arguments);
},
startup: function()
{
//Turn off button icons if warranted Must do here after dom nodes built
if (!this.cloudCover)
{
dojo.style(dojo.byId("Scene-"+this.scene+"Cloud"), "display", "none");
}
if (!this.targetInterest)
{
dojo.style(dojo.byId("Scene-"+this.scene+"Target"), "display", "none");
}
if (!this.hsv)
{
dojo.style(dojo.byId("Scene-"+this.scene+"HSV"), "display", "none");
}
this.inherited(arguments);
},
test: function(sceneId)
{
console.log("testing");
if (sceneId != this.scene)
{
domClass.replace("Scene-" + sceneId + "Fill", "taskInnerFill", "taskInnerFillSelected");
}
},
buildRendering: function()
{
console.log("buildRendering scene:" + this.scene);
this.inherited(arguments);
},
//
uninitialize: function()
{
if (this.eventHandle != null)
{
console.log("unsubscribing from event topic");
eventHandle.remove();
eventHandle = null;
}
this.inherited(arguments);
},
//
_onMenuClick: function(event)
{
console.log("menu item clicked");
},
_showContextMenu: function(event) {
console.log("opening context menu for scene:" + this.scene);
this.inherited(arguments);
},
// This is always called
_onMouseDown: function(e)
{
var scene = e.currentTarget.attributes["scene"].value;
if (e.button == 0)
{
console.log("mouse left pressed, scene=" + scene + " button=" + e.button);
domClass.replace("Scene-" + scene + "OuterBorder", "taskOuterBorderPressed", "taskOuterBorder");
}
else if (e.button == 2)
{
console.log("mouse right pressed, scene=" + scene + " button=" + e.button);
domClass.replace("Scene-" + scene + "OuterBorder", "taskOuterBorderPressed", "taskOuterBorder");
}
this.inherited(arguments);
},
// This is always called
_onMouseUp: function(e)
{
var scene = e.currentTarget.attributes["scene"].value;
if (e.button == 0)
{
console.log("mouse left released, scene=" + scene + " button=" + e.button);
}
else if (e.button == 2)
{
console.log("mouse right released, scene=" + scene + " button=" + e.button);
}
domClass.replace("Scene-" + this.scene + "OuterBorder", "taskOuterBorder", "taskOuterBorderPressed");
dijit.hideTooltip(e.currentTarget);
this.inherited(arguments);
},
//
_onMouseEnter: function(e)
{
label = "Scene: " + this.scene + "<BR>State: " + this.state + "<BR>Target: " + this.target;
dijit.showTooltip(label,e.currentTarget);
dijit.popup.close();
this.inherited(arguments);
},
//
_onMouseLeave: function(e)
{
this._onMouseUp("");
this.inherited(arguments);
dijit.hideTooltip(e.currentTarget);
},
// This is what is not always called
_onClick: function(e)
{
var scene = e.currentTarget.attributes["scene"].value;
console.log("scene " + scene + " clicked");
this._publishEvent(this.scene, "clicked");
this.inherited(arguments);
},
//
_onBlur: function(e)
{
dijit.popup.close();
this.inherited(arguments);
},
//
_onContextMenu: function(e)
{
this.inherited(arguments);
this._publishEvent({"scene":this.scene,"sceneId":this.sceneId}, "clicked");
dijit.hideTooltip(e.currentTarget);
var widget = this;
theNode = "TaskButtonContainer" + widget.scene;
console.log("mouse right clicked, scene=" + widget.scene + " target: " + e.target + "current target");
theTask = missionCache.query({"sceneId" : this.scene}).then( function(results) {
theTask = results;
if (widget.state === "Unassigned" || widget.state === "Ready") {
//The context menu should fire to allow assignment
var cb = new dijit.form.ComboBox({style:"width:96%;background-color:#414141;margin-top:4px;margin-bottom:4px;",
name:"usersByTask", placeholder:"Assign this task to: ", store:usersContextMenuCB,
labelAttr: 'name',
searchAttr: 'name',
onChange: function(){
theTask[0].taskStatus = "Assigned";
theTask[0].taskOwner = this.item.userName;
missionCache.put(theTask[0]);
console.log("nothing");
widget.set("state", "Assigned");
assignTask(this.item.userName);
widget.domNode.classList.remove("Unassigned");
widget.domNode.classList.add("Assigned");
widget.domNode.setAttribute("dndtype", "Assigned");
this.destroy();
},
onClose: function() { this.destroy();}
});
cb.toggleDropDown();
dijit.popup.open({parent: widget, popup:cb, around:e.target,
onClose: function(){
dijit.popup.close(cb);
}
});
}
});
},
_publishEvent: function(sceneNumber, eventName)
{
console.log("publishing " + eventName + " for scene " + sceneNumber);
topic.publish("TaskButton/tasks", { scene:sceneNumber, task:this, event:eventName });
},
_setStateAttr: function(newState)
{
if (newState != "")
{
console.log("setting state for scene:" + this.scene + " to " + newState);
this._set("state", newState);
if (this.innerNode !== undefined)
{
domClass.replace(this.innerFill, "task"+newState+"Background", "task"+this.previousState+"Background");
}
this.previousState = this.state;
this.state = newState;
}
this.inherited(arguments);
},
_changeTaskState: function(newState)
{
require(["dijit/registry"], function(registry) {
var node = registry.byId(clickedItem);
if (node !== undefined)
{
node.set("state", newState);
console.log("changed task " + this.clickedItem + " state to " + newState);
}
});
this.inherited(arguments);
},
_menuTaskDetails: function(e)
{
console.log("do task deatils");
}
});
})
模板中的所有按钮操作都有附加事件。
TaskButton.html模板:
<li class="dojoDndItem" dndType="${state}" style="border:none;padding:0" data-dojo-props="scene:${scene}">
<div id="TaskButtonContainer-${scene}" widgetid="TaskButtonContainer-${scene}" class="${baseClass}" data-dojo-attach-point="taskButtonContainer"
data-dojo-attach-event="onContextMenu:_showContextMenu">
<div widgetid="Scene-${scene}ContextMenu" data-dojo-type="dijit/Menu" data-dojo-props="contextMenuForWindow:false"
data-dojo-attach-point="contextMenu" targetNodeIds="Scene-${scene}Fill" style="display: none;">
<div data-dojo-type="dijit/MenuItem" data-dojo-attach-event="onClick:_menuTaskDetails">
Task Details
</div>
</div>
<div id="Scene-${scene}OuterBorder" widgetid="Scene-${scene}OuterBorder" class="taskOuterBorder" data-dojo-attach-point="outerBorder" scene="${scene}">
<div id="Scene-${scene}Fill" class="taskInnerFill task${state}Background" data-dojo-attach-point="innerFill" scene="${scene}"
data-dojo-attach-event="onMouseDown:_onMouseDown,onMouseUp:_onMouseUp,onDijitClick:_onClick,onMouseEnter:_onMouseEnter,onMouseLeave:_onMouseLeave,onContextMenu:_onContextMenu,onBlur:_onBlur">
<div id="Scene-${scene}Text" class="taskText" data-dojo-attach-point="text">
<table style="margin:0;padding:0">
<tr>
<td>${scene}</td>
</tr>
<tr>
<td>
<img id="Scene-${scene}Cloud" src="img/cloud.png" alt="Cloud cover" height="21" width="21">
<img id="Scene-${scene}Target" src="img/target.png" alt="ATR" height="21" width="21">
<img id="Scene-${scene}HSV" src="img/HSV.png" alt="HSV" height="21" width="21">
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</li>
我还根据建议清理了代码,并且TaskButton的onClick事件处理程序的行为没有任何变化。
答案 0 :(得分:0)
嗯, 有多个错误...
_WidgetBase
,_TemplatedMixin
和_OnDijitClickMixin
,而是Menu
Menu
应该是Base(所以应该是继承列表中的第一个)domNode.firstChild.nextElementSibling.firstElementChild
,而应该在模板中使用data-dojo-attach-point
cm = registry.byId('Scene-' + this.scene + 'ContextMenu');
应为this.cm = registry.byId('Scene-' + this.scene + 'ContextMenu');
dojo
命名空间。因此,dojo.style
应该替换为dojo/dom-style
和domStyle.set()
,而dojo.byId
应该替换为dojo/dom
和dom.byId()
dijit
命名空间。因此,dijit.hideTooltip
应替换为dijit/Tooltip
,然后Tooltip.hide()
,dijit.showTooltip
应替换为Tooltip.show()
,而dijit.popup.close()
应替换为dijit/_base/popup
要求popup.close()
然后dijit.popup.open()
和popup.open()
应替换为var
label
中的_onMouseEnter
之前缺少onChange
dijit.form.ComboBox
assignTask
的{{1}}中称为非现有方法_changeTaskState
dijit/registry
方法中您需要_onClick
,但它已经可用。所以额外的要求是没用的data-dojo-attach-event
方法没有附加任何内容。我不了解事件有时会如何执行...但是可以使用define([
'dojo/_base/declare',
'dojo/_base/event',
'dojo/_base/lang',
'dojo/dom',
'dojo/dom-class',
'dojo/dom-construct',
'dojo/dom-style',
'dojo/mouse',
'dojo/on',
'dojo/query',
'dojo/topic',
'dijit/Menu',
'dijit/MenuItem',
'dijit/MenuSeparator',
'dijit/PopupMenuItem',
'dijit/popup',
'dijit/Tooltip',
'dijit/Tree',
'dijit/tree/ForestStoreModel',
'dijit/registry',
'dijit/_base/popup',
'dijit/form/Button',
'dijit/_WidgetBase',
'dijit/_OnDijitClickMixin',
'dijit/_TemplatedMixin',
'dijit/_WidgetsInTemplateMixin',
'dojo/text!./templates/TaskButton.html'
], function(declare, event, lang, dom, domClass, domConstruct, domStyle, mouse, on, query, topic, Menu, MenuItem, MenuSeparator, PopupMenuItem,
Popup, Tooltip, Tree, ForestStoreModel, registry, popup, button, _WidgetBase, _OnDijitClickMixin, _TemplatedMixin, _WidgetsInTemplateMixin, template) {
return declare('TaskButton', [Menu, _WidgetsInTemplateMixin], {
scene: 0,
sceneId: 0,
target: '',
state: 'pending',
cloudCover: false,
cloudPercentage: 0,
targetInterest: false,
hsv: false,
previousState: 'pending',
backgroundcolor: '#414141',
templateString: template,
baseClass: 'TaskButton',
innerNode: undefined,
cm: null,
theTask: null,
eventHandle: null,
postCreate: function() {
// Get a DOM node reference for the root of our widget
var domNode = this.domNode;
this.innerNode = domNode.firstChild.nextElementSibling.firstElementChild;
domClass.replace(this.innerFill, 'task' + this.state + 'Background', 'task' + this.state + 'Background');
if (this.cloudCover && ((this.state === 'Ready') || (this.state === 'Unassigned'))) {
domClass.replace(this.innerFill, 'task' + 'Red' + 'Background', 'task' + this.state + 'Background');
}
this.previousState = this.state;
console.log('getting context menu for Scene-' + this.scene + 'ContextMenu');
cm = registry.byId('Scene-' + this.scene + 'ContextMenu');
this.own(
on(domNode, 'contextmenu', lang.hitch(this, '_showContextMenu'))
);
this.inherited(arguments);
},
startup: function() {
//Turn off button icons if warranted Must do here after dom nodes built
if (!this.cloudCover) {
domStyle.set(dom.byId('Scene-' + this.scene + 'Cloud'), 'display', 'none');
}
if (!this.targetInterest) {
domStyle.set(dom.byId('Scene-' + this.scene + 'Target'), 'display', 'none');
}
if (!this.hsv) {
domStyle.set(dom.byId('Scene-' + this.scene + 'HSV'), 'display', 'none');
}
this.inherited(arguments);
},
test: function(sceneId) {
console.log('testing');
if (sceneId != this.scene) {
domClass.replace('Scene-' + sceneId + 'Fill', 'taskInnerFill', 'taskInnerFillSelected');
}
},
buildRendering: function() {
console.log('buildRendering scene:' + this.scene);
this.inherited(arguments);
},
//
uninitialize: function() {
if (this.eventHandle != null) {
console.log('unsubscribing from event topic');
eventHandle.remove();
eventHandle = null;
}
this.inherited(arguments);
},
//
_onMenuClick: function(event) {
console.log('menu item clicked');
},
_showContextMenu: function(event) {
console.log('opening context menu for scene:' + this.scene);
this.inherited(arguments);
},
// This is always called
_onMouseDown: function(e) {
var scene = e.currentTarget.attributes['scene'].value;
if (e.button == 0) {
console.log('mouse left pressed, scene=' + scene + ' button=' + e.button);
domClass.replace('Scene-' + scene + 'OuterBorder', 'taskOuterBorderPressed', 'taskOuterBorder');
} else if (e.button == 2) {
console.log('mouse right pressed, scene=' + scene + ' button=' + e.button);
domClass.replace('Scene-' + scene + 'OuterBorder', 'taskOuterBorderPressed', 'taskOuterBorder');
}
this.inherited(arguments);
},
// This is always called
_onMouseUp: function(e) {
var scene = e.currentTarget.attributes['scene'].value;
if (e.button == 0) {
console.log('mouse left released, scene=' + scene + ' button=' + e.button);
} else if(e.button == 2) {
console.log('mouse right released, scene=' + scene + ' button=' + e.button);
}
domClass.replace('Scene-' + this.scene + 'OuterBorder', 'taskOuterBorder', 'taskOuterBorderPressed');
Tooltip.hide(e.currentTarget);
this.inherited(arguments);
},
//
_onMouseEnter: function(e) {
var label = 'Scene: ' + this.scene + '<BR>State: ' + this.state + '<BR>Target: ' + this.target;
Tooltip.show(label, e.currentTarget);
popup.close();
this.inherited(arguments);
},
//
_onMouseLeave: function(e) {
this._onMouseUp('');
this.inherited(arguments);
Tooltip.hide(e.currentTarget);
},
// This is what is not always called
_onClick: function(e) {
var scene = e.currentTarget.attributes['scene'].value;
console.log('scene ' + scene + ' clicked');
this._publishEvent(this.scene, 'clicked');
this.inherited(arguments);
},
//
_onBlur: function(e) {
popup.close();
this.inherited(arguments);
},
//
_onContextMenu: function(e) {
this.inherited(arguments);
this._publishEvent({
'scene': this.scene,
'sceneId': this.sceneId
}, 'clicked');
Tooltip.hide(e.currentTarget);
var widget = this;
theNode = 'TaskButtonContainer' + widget.scene;
console.log('mouse right clicked, scene=' + widget.scene + ' target: ' + e.target + 'current target');
theTask = missionCache.query({
'sceneId': this.scene
}).then(function(results) {
theTask = results;
if (widget.state === 'Unassigned' || widget.state === 'Ready') {
//The context menu should fire to allow assignment
var cb = new dijit.form.ComboBox({
style: 'width:96%;background-color:#414141;margin-top:4px;margin-bottom:4px;',
name: 'usersByTask',
placeholder: 'Assign this task to: ',
store: usersContextMenuCB,
labelAttr: 'name',
searchAttr: 'name',
onChange: function() {
theTask[0].taskStatus = 'Assigned';
theTask[0].taskOwner = this.item.userName;
missionCache.put(theTask[0]);
console.log('nothing');
widget.set('state', 'Assigned');
//assignTask(this.item.userName);
widget.domNode.classList.remove('Unassigned');
widget.domNode.classList.add('Assigned');
widget.domNode.setAttribute('dndtype', 'Assigned');
this.destroy();
},
onClose: function() {
this.destroy();
}
});
cb.toggleDropDown();
popup.open({
parent: widget,
popup: cb,
around: e.target,
onClose: function() {
popup.close(cb);
}
});
}
});
},
_publishEvent: function(sceneNumber, eventName) {
console.log('publishing ' + eventName + ' for scene ' + sceneNumber);
topic.publish('TaskButton/tasks', {
scene: sceneNumber,
task: this,
event: eventName
});
},
_setStateAttr: function(newState) {
if (newState != '') {
console.log('setting state for scene:' + this.scene + ' to ' + newState);
this._set('state', newState);
if (this.innerNode !== undefined) {
domClass.replace(this.innerFill, 'task' + newState + 'Background', 'task' + this.previousState + 'Background');
}
this.previousState = this.state;
this.state = newState;
}
this.inherited(arguments);
},
_changeTaskState: function(newState) {
var node = registry.byId(clickedItem);
if (node !== undefined) {
node.set('state', newState);
console.log('changed task ' + this.clickedItem + ' state to ' + newState);
}
this.inherited(arguments);
},
_menuTaskDetails: function(e) {
console.log('do task deatils');
}
});
})
进行连接吗?如果是,那么请同时提供您的模板。尝试应用所有更改来清除一些错误,并查看它是否更好。 如果不是,请分享按钮的模板。
LPAD