diff --git a/package.json b/package.json
index 691a53e5..44a36b73 100644
--- a/package.json
+++ b/package.json
@@ -38,8 +38,10 @@
"webpack-dev-server": "1.15.0"
},
"dependencies": {
+ "sprintf": "0.1.5",
"diff-match-patch": "1.0.0",
"numeric": "1.2.6",
- "jwerty": "0.3.2"
+ "jwerty": "0.3.2",
+ "mustache-loader": "0.3.3"
}
}
diff --git a/web/app/3d/actions/actions.js b/web/app/3d/actions/actions.js
index 20fc3c18..f65cbf0d 100644
--- a/web/app/3d/actions/actions.js
+++ b/web/app/3d/actions/actions.js
@@ -66,7 +66,7 @@ ActionManager.prototype.run = function(actionId, event) {
if (action.state.enabled) {
action.__handler(this.app, event);
} else {
- this.app.inputManager.info("action '"+actionId+"' is disabled and can't be launched
" + action.state.hint);
+ this.app.inputManager.messageSink.info("action '"+actionId+"' is disabled and can't be launched
" + action.state.hint);
}
};
diff --git a/web/app/3d/ui/bind.js b/web/app/3d/ui/bind.js
new file mode 100644
index 00000000..af409091
--- /dev/null
+++ b/web/app/3d/ui/bind.js
@@ -0,0 +1,26 @@
+import {sprintf} from 'sprintf'
+
+export function Bind(dom, data, policy) {
+ if (!policy) policy = DEFAULT_POLICY;
+ const props = Object.getOwnPropertyNames(data);
+ for (let prop of props) {
+ const node = $(dom).find('[data-bind="'+prop+'"]');
+ if (node.length == 0) continue;
+ let value = data[prop];
+ if (!policy.hideEmptyValue || value || value === 0) {
+ var format = node.attr('bind-format');
+ if (format) {
+ value = sprintf(format, value);
+ }
+ node.text(value);
+ node.show();
+ } else {
+ node.text('');
+ node.hide();
+ }
+ }
+}
+
+const DEFAULT_POLICY = {
+ hideEmptyValue: true
+};
\ No newline at end of file
diff --git a/web/app/3d/ui/input-manager.js b/web/app/3d/ui/input-manager.js
index 0040e981..77415e0c 100644
--- a/web/app/3d/ui/input-manager.js
+++ b/web/app/3d/ui/input-manager.js
@@ -1,6 +1,8 @@
import {jwerty} from 'jwerty'
import {keymap} from './keymaps/default'
-import {DefaultMouseEvent, EventData, fit} from './utils'
+import {Bind} from './bind'
+import {MessageSink} from './message-sink'
+import {LoadTemplate, DefaultMouseEvent, EventData, fit} from './utils'
export function InputManager(app) {
this.app = app;
@@ -8,19 +10,20 @@ export function InputManager(app) {
this.keymap = keymap;
this.mouseInfo = new DefaultMouseEvent();
this.requestedActionInfo = null;
+ this.actionInfoDom = $(LoadTemplate('action-info')({}));
+ this.messageSink = new MessageSink(this);
$(() => {
$(document)
.on('keydown', (e) => this.handleKeyPress(e))
.on('mousedown', (e) => this.clear(e))
.on('mouseenter', '.action-item', (e) => this.showActionInfo($(e.target)))
- .on('mouseleave', '.action-item', (e) => this.emptyInfo())
+ .on('mouseleave', '.action-item', (e) => this.hideActionInfo())
.on('mousemove', (e) => this.mouseInfo = e)
.on('click', '.action-item', (e) => this.handleActionClick(e));
});
}
InputManager.prototype.handleKeyPress = function(e) {
- console.log(e.keyCode);
switch (e.keyCode) {
case 27 : this.clear(); break;
}
@@ -44,7 +47,7 @@ InputManager.prototype.clear = function(e) {
this.openMenus = [];
}
this.requestedActionInfo = null;
- $('#message-sink').hide();
+ this.messageSink.hide();
};
InputManager.prototype.handleActionClick = function(event) {
@@ -62,39 +65,21 @@ InputManager.prototype.registerOpenMenu = function(menu) {
this.openMenus.push(menu);
};
-InputManager.messageSink = function() {
- return $('#message-sink');
-};
-
-InputManager.prototype.emptyInfo = function() {
+InputManager.prototype.hideActionInfo = function() {
this.requestedActionInfo = null;
- var messageSink = InputManager.messageSink();
- messageSink.empty();
- messageSink.hide();
+ this.messageSink.hide();
};
InputManager.prototype.showActionInfo = function(el) {
//show hint immediately and deffer showing the full info
- var hint = el.data('actionHint');
- if (hint) {
- InputManager.messageSink().text(hint);
- this.showMessageSinkAround();
- }
+ //var hint = el.data('actionHint');
+ //if (hint) {
+ // InputManager.messageSink().text(hint);
+ // this.showMessageSinkAround();
+ //}
this.requestInfo(el.data('action'));
};
-InputManager.prototype.info = function(text) {
- InputManager.messageSink().html(text);
- this.showMessageSinkAround();
-};
-
-InputManager.prototype.showMessageSinkAround = function() {
- var messageSink = InputManager.messageSink();
- messageSink.show();
- messageSink.offset({left: this.mouseInfo.pageX + 10, top: this.mouseInfo.pageY + 10});
- fit(messageSink, $('body'));
-};
-
InputManager.prototype.requestInfo = function(action) {
this.requestedActionInfo = action;
setTimeout(() => {
@@ -103,13 +88,14 @@ InputManager.prototype.requestInfo = function(action) {
if (actionId != null) {
const action = this.app.actionManager.actions[actionId];
if (action) {
- var hotkey = this.keymap[actionId];
- InputManager.messageSink().html(
- (action.state.hint ? action.state.hint : '') +
- ('