I'm currently build a telegram bot and i have one issue.
In my case has had a few inline keyboard. here are
but all inline keyboard has a one handler
bot.on('callback_query',query=>{
bot.answerCallbackQuery(query.id,{text:query.data,show_alert:false})
console.log(query)
})
so i will need check with a if else condition for all handler in callback_query event but i don't like this way. Then i will had find one to get rid of 'if else'. In this i will had use a EventEmitter to separate each handler
emitter.on('eventOne',(chatId)=>{
... business logic of handler
})
emitter.on('eventTwo',(chatId)=>{
... business logic of handler
})
bot.on('callback_query',query=>{
emitter.emit(query.data,query.message.chat.id)
bot.answerCallbackQuery(query.id,{text:query.data,show_alert:false})
console.log(query)
})
is this way right or not, if not i need a right implementation of this issue.
Sorry for grammar mistakes, my native language is Uzbek ;)
I need a right implamentation of inline_keyboards handler
Related
This is regarding javascript programming pattern. while working with the gulp, I came across 2 different type of function calling pattern and this is really confusing so someone clarifies Is both functions are doing the same job?
gulp.watch(path.join(conf.paths.src, '/app/**/*.js'),
function(event) {
if(event.type === 'changed') {
callAMethod();
} else {
callBMethod();
}
});
in above method, we can write if else condition
but in this pattern
gulp.watch(path.join(conf.paths.src, '/app/**/*.js'))
.on('change', callAMethod);
If yes then please suggest some links Where I can read about it and which is the better way to handle the errors? also, where do we write else part in the later method style?
They are both different.
The first one is a callback to the gulp.watch method and it gets all the events that the watcher produces
The second one does not provide a callback, instead it subscribes to one event (change) produced.
The watch method returns a Gaze object and to handle errors, subscribe to the error event:
watcher.on('error', function(error) {
// Handle error here
});
Gulp4 which is still in alpha stage uses chokidar. To watch for errors, it's exactly the same as the above:
watcher.on('error', error => log(`Watcher error: ${error}`))
These functions are different.
Gulp uses a utility named glob-watcher for handling file changes and the first one is a callback called by glob-watcher.
The second one is a raw event from Event Emitter (NodeJS Emitter or Chokidar) instance.
Some events from EventEmmiter propagate to glob-watcher callback - for example, "change", so it may look the same on the first look.
For handling errors, I recommend having a look at gulp-plumber plugin.
I have a form that has a javascript validation function built from its previous functioning web site (i.e. old domino form). I am in the process of converting that website to xpages. Is it possible to tie that function as a CSJS to the save and close button like it was in the past application?
I only ask as there are lots of conditional validation requirements that would all need to be recreated that are existing in this function. . Also the form has tab pannels, and partial refresh conditions that I would have to code around to avoid refreshes calling validation, etc.
I have a feeling I will have problems with some of the calls, example:
document=document1;
form1 = document.forms[0] ;
val_AlphaSuffix = form1.Suffix.value ;
var msg="";
form = document.forms[0] ;
val_Eff_Date = form.Eff_Date.value ;
if (val_Eff_Date== "") {
msg=msg+"Effective Date is missing.\n";
}
If anyone has a better way of passing the document instead of each item, I would love to see that, but if not I think this answer by Tim T. probably is the best answer I can see:
Expression Language (e.g. #{id:Hours20}) can only be interpreted within the context of a component attribute, such as the onChange event code for a field. Once you move the code into a separate library, the code is no longer an attribute of a component, it's code that can be referenced in component attributes.
As with any other good function, design all client-side JavaScript functions to accept anything that might be context-sensitive as a parameter. For example:
function updateHours(inputId, outputId) {
var hours20 = XSP.getElementById(inputId).value;
XSP.getElementById(outputId).value = hours20;
}
Then your onChange event can reference this function, but pass in only the context-sensitive information:
updateHours("#{id:Hours20}", "#{id:Hours10}");
This way you're keeping reusable business logic in script libraries, which is always a good thing, but nothing in those libraries is assuming anything about page structure or server-side variables.
shareeditflag
answered Jan 16 '14 at 0:17
Tim Tripcony
7,73611532
There are a few moving parts you want to look at...
If you want to perform an entire client side validation, don't tie it to a button, but use the form event onSubmit="validate(this)". This will call your function with the form as parameter and you don't need to worry if you got the right form. You could use class parameters on your fields to specify generic validation requirements e.g. class="mandatory max_50" etc.
However be aware: client side validation is only for the comfort of the user, since it can be bypassed easily. Unless you are on very slow connection, you might want to take advantage of XPages server side validators and the error control.
Update: use the XSP object to add the event: https://www.notessensei.com/blog/2010/07/meet-the-xsp-object.html
I want to implement a custom event that can be "broadcast", rather than sent to specific targets. Only those elements that have registered themselves as listeners for such events will receive them.
What I have in mind would look as follows.
First, in various places of the code, there would be statements of the form
some_subscriber.on_signal( 'some_signal', some_handler );
I'm using the term signal as shorthand for "broadcast event". In the expression above, some_subscriber registers itself as a listener of one type (called 'some_signal') of such signals, by providing a handler for it.
Elsewhere in the code, there would be statements of the form
publisher.signal_types[ 'some_signal' ].broadcast( event_data );
When statements like these get executed, a new event is generated and "broadcast". By this I mean that the code that calls the broadcast method has no direct information about the listeners for the signal it is issuing.
I have implemented a sketch of this idea in this jsFiddle, mostly in order to illustrate what I described in words above1. (It's certainly not production-grade, and I'm not particularly confident that it could be made so.)
The key elements of this implementation are the following. First, publisher objects do not keep track of their subscribers, as can be seen in the implementation of a factory method for such a publisher, shown below:
function make_publisher ( signal_types ) {
// ...
var _
, signal = {}
, ping = function ( type ) {
signal[ type ].broadcast( ... );
}
;
signal_types.forEach( function ( type ) {
signal[ type ] = $.register_signal_type( type );
} );
return { signal_types: signal_types, ping: ping };
}
This publisher object exposes only two items: the types of signals it broadcasts (in signal_types), and a ping method. When its ping method is invoked, the publisher responds by broadcasting a signal:
signal[ type ].broadcast( ... )
The ultimate recipients of this broadcast are nowhere to be seen in this code.
Second, elsewhere in the code, subscribers register themselves as listeners of these broadcast signals, like so
$( some_selector ).on_signal( signal_type, some_handler );
Note: It is basically impossible to illustrate the rationale for this scheme using an example that is both small and realistic. The reason for this is that the strength of this scheme is that it supports very loose coupling between the publisher code and subscriber code, and this is a feature that is never necessary in a small example. On the contrary, in a small example, code that implements such loose coupling invariably comes across as unnecessarily complex. It is therefore important to keep in mind that this apparent excess complexity is an artifact of the context. Loose coupling is very useful in larger projects. In particular, loose coupling via a publisher/subscriber-type pattern is one of the essential features of MVC.
My question is: is there a better (or at least more standard) way to achieve this effect of "broadcasting" custom events?
(I'm interested in both jQuery-based answers as well as "pure JS" ones.)
1An earlier, ill-fated version of this post was met with almost universal incomprehension, and (of course) the all-too-typical down-voting. With one exception, all the comments I got challenged the very premises of the post, and one directly questioned my grasp of the basics of event-driven programming, etc. I'm hoping that by presenting a working example of what I mean at least it won't come across as utterly inconceivable as it did when I described it in words alone. Luckily, the one helpful comment I did get on that earlier post informed me of the function jQuery.Callbacks. This was indeed a useful tip; the sketch implementation mentioned in the post is based on jQuery.Callbacks.
All right.
So I think what you can do is use the native dispatchEvent and addEventListener methods and use document as the only element for both publishing and subscribing to those events. Something like:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
document.addEventListener('someEvent', doSomething, false);
And to make cross-browser, you could:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
if (document.addEventListener) {
document.addEventListener('someEvent', doSomething, false);
} else {
document.attachEvent('someEvent', doSomething);
}
You can read more on the subject here and here. Hope this helps.
My question is: is there a better (or at least more standard) way to
achieve this effect of "broadcasting" custom events?
No, there is not a more standard way of doing publish/subscribe in Javascript. It is not directly built into the language or the browser and there are no platform standards for it that I'm aware of.
You have several options (most of which you seem aware of) to put your own system together.
You could pick a specific object such as the document object or the window object or a new object you create and use jQuery's .on() and .trigger() with that object as a central clearing house to cobble together a publish/subscribe-like model. You could even hide the existence of that object from your actual use by just coding it into a few utility functions if you want.
Or, as you seem to already know, you could use the jQuery.Callbacks functionality. There's even publish/subscribe sample code in the jQuery doc.
Or, you can find a third party library that offers a somewhat traditional publish/subscribe model.
Or, you can build your own from scratch which really just involves keeping a list of callback functions that are associated with a specific event so when that event is triggered, you can call each callback function.
If you came here looking for the jQuery way of doing this, here you go:
Add the event broadcast/dispatch code:
Syntax:
$(<element-name>).trigger(<event-name>);.
Example:
$.ajax({
...
complete: function () {
// signal to registered listeners that event has occured
$(document).trigger("build_complete");
...
}
});
Register a listener for the event:
Syntax:
$(<element-name>).on(<event-name>, function() {...});
Example:
$(document).on("build_complete", function () {
NextTask.Init();
});
Note:
Doing it this way: $(document).build_complete(function() {...}); leads to an error: Uncaught TypeError: $(...).build_complete is not a function.
I know this has been marked as answered back in 2015 -- but a solution that is also elegant and simple could be to use Redux
We have a situation where we are utilizing a combination of events and routing inside of angular to handle navigation and communication between modules. Unfortunately the technique doesn't seem to work for us:
Neither this
Events.identifierSearch.fireOnChange(symbol);
$location.path('/explore');
nor this
Events.identifierSearch.fireOnChange(symbol);
$location.path('/explore');
Is working. The event handlers don't seem to fire. However a less optimal solution that we tried to demonstrate our event handlers are properly connected seems to work:
$location.path('/explore');
$timeout(function(){
var symbol = $event.target.innerText;
Events.identifierSearch.fireOnChange(symbol);
}, 500);
Now that is not what we want to have in our production code. In reality the "symbol" will be a large group of nested objects, so passing them on the URL of a route isn't ideal. And rewriting the routing seems like too much of a pain, it handles segregating partial pages nicely.
An idea i had would be to break this into two parts. First fire the event AND handle the event in the controller that fired it. This would require me adding a source to the event - so no sweat:
var controllerName = "thisBlahController" ;
Events.identifierSearch.fireOnChange(controllerName, symbol);
then in the same controller, handle the event and fire the location change:
$scope.$on(Events.identifierSearch.onChange, function() {
var source = Events.identifierSearch.source
if(source === controllerName) {
$location.path('/explore');
}
}
Again - it is not ideal, because it uses the assumption that the event has been handled by all sources prior to the route changing.
First, it would be great to know what it is in the angular routing that is causing the defusing of the events?
Second, I would love an official solution to this problem, one that has been battle tested.
Third, failing a systematic solution, can would like to hear opinions on the two solutions I have proposed up thread.
Quick modification
If i rewrite the order using the timeout approach:
Events.identifierSearch.fireOnChange(symbol);
$timeout(function(){
$location.path('/explore');
}, 1000);
The functionality doesn't seem to work either. Leading to question four Does a controller for a partial page, that is not the current ng-view get their event plumbing hooked up?
Taking Jeff Atwood's advice, I decided to use a JavaScript library for the very basic to-do list application I'm writing. I picked the Dojo toolkit, version 1.1.1. At first, all was fine: the drag-and-drop code I wrote worked first time, you can drag tasks on-screen to change their order of precedence, and each drag-and-drop operation calls an event handler that sends an AJAX call to the server to let it know that order has been changed.
Then I went to add in the email tracking functionality. Standard stuff: new incoming emails have a unique ID number attached to their subject line, all subsequent emails about that problem can be tracked by simply leaving that ID number in the subject when you reply. So, we have a list of open tasks, each with their own ID number, and each of those tasks has a time-ordered list of associated emails. I wanted the text of those emails to be available to the user as they were looking at their list of tasks, so I made each task box a Dijit "Tree" control - top level contains the task description, branches contain email dates, and a single "leaf" off of each of those branches contains the email text.
First problem: I wanted the tree view to be fully-collapsed by default. After searching Google quite extensively, I found a number of solutions, all of which seemed to be valid for previous versions of Dojo but not the one I was using. I eventually figured out that the best solution would seem to be to have a event handler called when the Tree control had loaded that simply collapsed each branch/leaf. Unfortunately, even though the Tree control had been instantiated and its "startup" event handler called, the branches and leaves still hadn't loaded (the data was still being loaded via an AJAX call). So, I modified the system so that all email text and Tree structure is added server-side. This means the whole fully-populated Tree control is available when its startup event handler is called.
So, the startup event handler fully collapses the tree. Next, I couldn't find a "proper" way to have nice formatted text for the email leaves. I can put the email text in the leaf just fine, but any HTML gets escaped out and shows up in the web page. Cue more rummaging around Dojo's documentation (tends to be out of date, with code and examples for pre-1.0 versions) and Google. I eventually came up with the solution of getting JavaScript to go and read the SPAN element that's inside each leaf node and un-escape the escaped HTML code in it's innerHTML. I figured I'd put code to do this in with the fully-collapse-the-tree code, in the Tree control's startup event handler.
However... it turns out that the SPAN element isn't actually created until the user clicks on the expando (the little "+" symbol in a tree view you click to expand a node). Okay, fair enough - I'll add the re-formatting code to the onExpand() event handler, or whatever it's called. Which doesn't seem to exist. I've searched to documentation, I've searched Google... I'm quite possibly mis-understanding Dojo's "publish/subscribe" event handling system, but I think that mainly because there doesn't seem to be any comprehensive documentation for it anywhere (like, where do I find out what events I can subscribe to?).
So, in the end, the best solution I can come up with is to add an onClick event handler (not a "Dojo" event, but a plain JavaScript event that Dojo knows nothing about) to the expando node of each Tree branch that re-formats the HTML inside the SPAN element of each leaf. Except... when that is called, the SPAN element still doesn't exist (sometimes - other times it's been cached, just to further confuse you). Therefore, I have the event handler set up a timer that periodically calls a function that checks to see if the relevant SPAN element has turned up yet before then re-formatting it.
// An event handler called whenever a "email title" tree node is expanded.
function formatTreeNode(nodeID) {
if (dijit.byId(nodeID).getChildren().length != 0) {
clearInterval(nodeUpdateIntervalID);
messageBody = dijit.byId(nodeID).getChildren()[0].labelNode.innerHTML
if (messageBody.indexOf("<b>Message text:</b>") == -1) {
messageBody = messageBody.replace(/>/g, ">");
messageBody = messageBody.replace(/</g, "<");
messageBody = messageBody.replace(/&/g, "&");
dijit.byId(nodeID).getChildren()[0].labelNode.innerHTML = "<b>Message text:</b><div style=\"font-family:courier\">"+messageBody+"</div>";
}
}
}
// An event handler called when a tree node has been set up - we changed the default fully-expanded to fully-collapsed.
function setupTree(theTree) {
dijit.byId("tree-"+theTree).rootNode.collapse();
messageNode = dijit.byId("tree-"+theTree).rootNode.getChildren();
for (pl = 0; pl < messageNode.length; pl++) {
messageNode[pl].collapse();
messageNode[pl].expandoNode.onclick = eval("nodeUpdateIntervalID = setInterval(\"formatTreeNode('"+messageNode[pl].id+"')\",200); formatTreeNode('"+messageNode[pl].id+"');");
}
}
The above has the feel of a truly horrible hack, and I feel sure I must have taken a wrong turn somewhere early on in my thought process. Can someone please tell me:
The correct way to go about putting nicely-formatted text inside a Dojo/Dijit Tree control.
The correct way to handle Dojo events, like where I can figure out what events are available for me to subscribe to.
A better JavaScript library to use (can I do what I want to with JQuery and avoid the all-around-the-houses approach seen above?).
PS: If you're naming a software project, give thought to its name's uniqueness in Google - I'm sure searching for "Dojo" documentation in Google would be easier without all the martial arts results getting in the way.
PPS: Firefox spellchecker knows how to spell "Atwood", correcting me when I put two 'T's instead of one. Is Jeff just that famous now?
I assume that you followed the dijit.Tree and dojo.data in Dojo 1.1 tutorial which directed you to pass the data to the tree control using a data store. That had me banging my head of a brick wall for a while.
Its not really a great approach and the alternative is not really well documented. You need to create a use model instead. I have included an example below of a tree model that I created for displaying the structure of an LDAP directory.
You will find the default implementation of the model in your dojo distribution at ./dijit/_tree/model.js. The comments should help you understand the functions supported by the model.
The IDirectoryService class the code below are stubs for server-side Java POJOs generated by Direct Web Remoting (DWR). I highly recommend DWR if you going to be doing a lot of client-server interaction.
dojo.declare("LDAPDirectoryTreeModel", [ dijit.tree.model ], {
getRoot : function(onItem) {
IDirectoryService.getRoots( function(roots) {
onItem(roots[0])
});
},
mayHaveChildren : function(item) {
return true;
},
getChildren : function(parentItem, onComplete) {
IDirectoryService.getChildrenImpl(parentItem, onComplete);
},
getIdentity : function(item) {
return item.dn;
},
getLabel : function(item) {
return item.rdn;
}
});
And here is an extract from the my JSP page where I created the model and used it to populate the tree control.
<div
dojoType="LDAPDirectoryTreeModel"
jsid="treeModel"
id="treeModel">
</div>
<div
jsid="tree"
id="tree"
dojoType="dijit.Tree" model="treeModel"
labelAttr="name"
label="${directory.host}:${directory.port}">
</div>