Keyup event not on inside a form - meteor

I'm trying to do something simple: using keys to move a character on the screen with Meteor
I got it working using a Collection to store the character's position, but the keyup event is only working inside of a form/input
I'd like to capture the client keypress everywhere.
Template.main.events({
'keyup': function(evt, tmpl){
evt.preventDefault();
// Move up
if(evt.keyCode === 38){
console.log('Moving up');
}
);
This code only works when the focus in on an input :/

Add events to Template.body the reference
Template.body.events({
'keyup': function(evt, tmpl){
evt.preventDefault();
// Move up
if(evt.keyCode === 38){
console.log('Moving up');
}
);
Or to $(window):
var keyupFunc = function(evt){
if(evt.keyCode === 38){
console.log('Moving up');
}
}
Template.main.created = function(){
$(window).on("keyup", keyupFunc);
}
Template.main.destroyed = function(){
$(window).off("keyup", keyupFunc);
}

Related

button needs to be clicked twice to toggle layer visibility?

Using an example I found on this thread https://gis.stackexchange.com/questions/198896/mapbox-gljs-group-layers/198920#198920?newreg=120a87a082494e41b2e6ab240c94b266 I have grouped multiple layers together and created a single toggle button to turn on and off visibility.
However, the buttons need to be clicked twice to trigger the function. Is it possible to have them only clicked once for the function to work?
Here is my codepen example https://codepen.io/charlie-enright/pen/BarRgbo
//whatever layers you want to toggle go in to this function
toggleLayer(['site location markers'], 'markers');
toggleLayer(['Pen Dinas', 'Rudbaxton','Brawdy Castle', 'Caer Blaen Minog', 'Castell Bach', 'Castell Gwyn', 'Tancredston', 'Thornton Rath', 'Walesland Rath'], 'Geophys');
toggleLayer(['Pendinas 50cm DSM'], '50cm DSM');
toggleLayer(['Pendinas 50cm DTM'], '50cm DTM');
function toggleLayer(ids, name) {
var link = document.createElement('a');
link.href = '#';
link.className = 'active';
link.textContent = name;
link.onclick = function (e) {
e.preventDefault();
e.stopPropagation();
for (layers in ids){
var visibility = map.getLayoutProperty(ids[layers], 'visibility');
if (visibility === 'visible') {
map.setLayoutProperty(ids[layers], 'visibility', 'none');
this.className = '';
} else {
this.className = 'active';
map.setLayoutProperty(ids[layers], 'visibility', 'visible');
}
}
};
var layers = document.getElementById('menu');
layers.appendChild(link);
}
I'm not exactly sure why, but the first time you check the visibility of the layer var visibility = map.getLayoutProperty(ids[layers], 'visibility');, visibility is undefined.
If you check for this in the if statement below, it will toggle on the first click:
if (visibility === 'visible' || visibility === undefined) {
// ^^ if 'visible' or undefined, set visibility to 'none'
...
}

Fullcalendar background events

Is it possible to hide events that are inside background events so that the user cannot see it?
if yes what is the way to do it ?
var isValidEvent = function(start,end,id){
return $("#calendar").fullCalendar('clientEvents', function (event) {
return (event.rendering === "background" && id!='test' &&
(start>event.start) && (end<event.end)) ;
}).length > 0;
};
eventRender:function(event, element, view) if(isValidEvent(event.start,event.end,event.id)){
$(element).hide();
},
As of the docs, eventRender callback should either return an event OR false if the event should be hidden:
eventRender:function(event, element, view)
if(isValidEvent(event.start,event.end,event.id)){
return event;
}
else {
return false;
}
},
I haven't tested yet as I don't need it, but should work that way.
I got it like this:
eventRender:function(event, element, view){
var array= new Array();
array = $("#calendar").fullCalendar('clientEvents','test');
for(i of array){
if(event.source.url=="events.php" && moment(event.start)>=moment(i.start) && moment(event.end)<=moment(i.end)){
return false;
}
} }

extension appearing in the context menu of the browsers

I am developing a cross browser extension using kango framework. I want to add my extension to the context menu of the browser. I already have set "context_menu": true in the permissions array in extension_info.json file, but still my extension does not appear in the context menu ( when there is a right click in the browser window). How can I do this?
You need to add an event listener to main.js like this:
kango.ui.contextMenuItem.addEventListener(kango.ui.contextMenuItem.event.CLICK, function() {
kango.browser.tabs.getCurrent(function(tab) {
tab.dispatchMessage('ContextMenuItemClick');
});
});
And in the content.js you need to consume the event like this:
function handleContextMenuClick() {
var clickedElement = null;
if ('addEventListener' in document) {
document.addEventListener('mousedown', function(event) {
if (event.button == 2 && IsSupported()) {
clickedElement = event.target;
kango.console.log('StopIt menu item click 1');
}
}, true);
} else {
document.attachEvent('onmousedown', function(event) {
event = event || window.event;
if (event.button == 2&& IsSupported()) {
clickedElement = event.srcElement;
kango.console.log('StopIt menu item click 2');
}
});
}
kango.addMessageListener('ContextMenuItemClick', function(event) {
kango.console.log("addMessageListener: ContextMenuItemClick added");
});
}
handleContextMenuClick();
// Only activate the menu when the user is on facebook or twitter.
// This should be loaded from a service and updated one each new domain visited.
function IsSupported()
{
if(document.domain.indexOf("facebook.") > -1) return true;
if(document.domain.indexOf("twitter.") > -1) return true;
return false;
}

How to implement editable text in Meteor and DRY?

I have come up with a methodology for making editable text in my Meteor app. However, it does not follow the DRY paradigm and I'd like to change that but I am not too good with Javascript yet...
Suppose I have a table cell with some text and I'd like to double click it to edit it. I created a template variable to handle this:
<td class="itemName">
{{#unless editItemName}}
{{name}}
{{else}}
<input class="editItemName" type="text" value="{{name}}" style="width:100px;">
{{/unless}}
</td>
I then create an event to execute this transition on a double-click:
Template.inventoryItemDetail.events = {
'dblclick td.itemName': function (evt) {
Session.set("editItemName",true);
},
'blur input.editItemName': function () {
Session.set("editItemName",null);
},};
I also reused the ok_cancel code from the ToDo's example app (but that's sort of irrelevant):
// Returns an event_map key for attaching "ok/cancel" events to
// a text input (given by selector)
var okcancel_events = function (selector) {
return 'keyup '+selector+', keydown '+selector+', focusout '+selector;
};
// Creates an event handler for interpreting "escape", "return", and "blur"
// on a text field and calling "ok" or "cancel" callbacks.
var make_okcancel_handler = function (options) {
var ok = options.ok || function () {};
var cancel = options.cancel || function () {};
return function (evt) {
if (evt.type === "keydown" && evt.which === 27) {
// escape = cancel
cancel.call(this, evt);
evt.currentTarget.blur();
} else if (evt.type === "keyup" && evt.which === 13) {
// blur/return/enter = ok/submit if non-empty
var value = String(evt.target.value || "");
if (value) {
ok.call(this, value, evt);
evt.currentTarget.blur();
}
else {
cancel.call(this, evt);
evt.currentTarget.blur();
}
}
};
};
Template.inventoryItemDetail.events[ okcancel_events('input.editItemName') ] = make_okcancel_handler({
ok: function (value) {
Items.update(this._id, {$set: {name: value}});
}
});
Finally, I have to tie this Session variable to the template variable:
Template.inventoryItemDetail.editItemName = function () {
return Session.get("editItemName");
};
So right now, I have repeated all of this again and again for each editable text field and it all works, but it seems like terribly programming practice. I have found various editable text utilities on Github but I don't entirely understand them and none of them are for Meteor!
I'd really like to expand my knowledge of Meteor and Javascript by creating a tool that allows me to have editable text without repeating myself this ridiculous amount for each editable text field.
Thanks,
Chet
https://github.com/nate-strauser/meteor-x-editable-bootstrap for the package.
http://vitalets.github.io/x-editable/docs.html for the docs.
I just implemented this in my project and I won't ever go back to contenteditable.

input text return event in Meteor

I want to capture the event of a user pressing enter on an input of type="text" when they are filling out a form. This is done all over the web, yet the answer eludes me.
This is what I have so far:
In the html file, I have a text input like so:
<input type="text" size=50 class="newlink">
In the Javascript file, I am trying to capture the the user pressing enter to effectively submit the form. I am then grabbing the text from the input and going to stash it in the database:
Template.newLink.events = {
'submit input.newLink': function () {
var url = template.find(".newLink").value;
// add to database
}
};
The submit event is emitted from forms, not single input elements.
The built in event map for meteor is documented here: http://docs.meteor.com/#eventmaps.
You'll have to listen for a keyboard event (keydown, keypress, keyup). Within the event handler, check, if it's the return/enter key (Keycode 13), and proceed on success.
Template.newLink.events = {
'keypress input.newLink': function (evt, template) {
if (evt.which === 13) {
var url = template.find(".newLink").value;
// add to database
}
}
};
You could look into how this is achieved in the todos example (client/todos.js).
It uses a generic event handler for input fields (as seen below). You can browse the rest of the code for usage.
////////// Helpers for in-place editing //////////
// Returns an event map that handles the "escape" and "return" keys and
// "blur" events on a text input (given by selector) and interprets them
// as "ok" or "cancel".
var okCancelEvents = function (selector, callbacks) {
var ok = callbacks.ok || function () {};
var cancel = callbacks.cancel || function () {};
var events = {};
events['keyup '+selector+', keydown '+selector+', focusout '+selector] =
function (evt) {
if (evt.type === "keydown" && evt.which === 27) {
// escape = cancel
cancel.call(this, evt);
} else if (evt.type === "keyup" && evt.which === 13 ||
evt.type === "focusout") {
// blur/return/enter = ok/submit if non-empty
var value = String(evt.target.value || "");
if (value)
ok.call(this, value, evt);
else
cancel.call(this, evt);
}
};
return events;
};
I used this js function once to suppress the user using the return key in the text field to submit the form data. Perhaps you could modify it to suit the capture?
function stopRKey(evt) { // Stop return key functioning in text field.
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
if ((evt.keyCode == 13) && (node.type=="text")) { return false; }
}
document.onkeypress = stopRKey;
You can also use event.currentTarget.value
Template.newLink.events = {
'keypress input.newLink': function (evt) {
if (evt.which === 13) {
var url = event.currentTarget.value;
// add to database
}
}
};

Resources