【发布时间】:2015-07-28 13:15:22
【问题描述】:
我遇到了 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 事件处理程序的行为没有变化。
【问题讨论】:
-
可以分享一下TaskButton的代码吗?没有它就很难猜出哪里出了问题。
标签: events dojo onclick widget