Meteor Dynamic Template Events - templates

I'm new to Meteor, I could not find a sufficient answer to this but how does one go about referencing a Template's event handlers programmatically.
For example I would like to add or update or trigger an event defined in a template without actually as an example (pressing or clicking a button).
In the Template object I can see the events object below and can I access it but is this the right way?
Template.myTemplate._tmpl_data.events[]
Thanks!

You can define the handler outside the event map and call it as a function:
someHandler = function(this, evt,tpl) {
// do something with this, evt, and tpl
}
Template.myTemplate.events({
'click .myButton': function(event,template) {
var self = this;
return someHandler(self, event,template);
}
});
// Call someHandler whereever you want passing in whichever args you want
This is not a complete example, but should be able to get you going on some workable direction. If it works, please edit this answer to reflect a more complete example.

Related

Should all buttons contain a reference to the controller in MVC code (C++)?

I'm trying to figure out the best (cleanest) way to structure some code in C++ for an application I'm building. I think MVC makes sense as the way to go, but after a fair amount of research I'm not totally clear I'm doing things the right way.
Here's an example to illustrate my question:
Model
I have a class which contains drawing data called Canvas. An example function, used to clear the current contents of the canvas, is ClearCanvas().
Ultimately, I want a button in the interface to be able to call this function and clear the canvas.
Controller
I have a controller class for the canvas: CanvasController
The controller creates and then holds a reference to a canvas object: CurrentCanvas
The controller also creates the view: CanvasView and then sets a reference to itself on the view: CurrentCanvasView->SetControllerRef(this);
View
The view is made up of a series of nested classes that define the UI. For example, the hierarchy leading to the button in question might be something like this:
CanvasView
-VerticalBox
--HorizontalBox
---Button
During the view's constructor, a reference to the controller is passed from the view to all interactive elements, eg. NewButton->SetControllerRef(this->GetControllerRef());
Button Pressed
So now when the button is pressed, it can function like this:
void ClearCanvasButton::OnButtonPressed()
{
Controller->CurrentCanvas->ClearCanvas();
}
So my general question is: (1) does this seem like the right way to be doing things, or badly structured?
Also (2): Should the controller be encapsulating the canvas functions, for example:
void CanvasController::ClearCanvas()
{
CurrentCanvas->ClearCanvas();
}
Such that the function on the button could simply be:
void ClearCanvasButton::OnButtonPressed()
{
Controller->ClearCanvas();
}
I'm just not sure whether it's correct to essentially be passing down a reference to the controller to all elements of the view which ultimately want to change the model, or whether there is a cleaner way.
Apologies if the question has been asked a thousand times in a thousand different ways, I have been searching around trying to understand this.
You don't need a class ClearCanvasButton, if your Button class contains a member like
std::function<void()> onButtonPressed;
or similar, rather than
virtual void onButtonPressed() {};
You then pass a lambda that references the controller
CanvasView::CanvasView()
{
// make the widgets
Button.onButtonPressed = [Controller](){ Controller->ClearCanvas(); };
}

call wxHyperlinkEvent without clicking on link

I am using wxHyperLink. OnHyperlinkClicked(wxHyperlinkEvent&) is called when user clicks on the link. OnHyperlinkClicked() helps to switch between 2 screens. I want to call this function explicitly - without user interaction.
I am using the following code for that:
BEGIN_EVENT_TABLE(UserRegistrationFrame, wxFrame)
EVT_HYPERLINK(wxID_ANY, UserRegistrationFrame::OnAuthCodeOptionLinkClicked)
END_EVENT_TABLE()
void MyClass::MyFunction()
{
wxHyperlinkEvent event;
OnAuthCodeOptionLinkClicked(event);
}
void MyClass::OnAuthCodeOptionLinkClicked(wxHyperlinkEvent& event)
{
// code to switch
}
Is this the correct way to achieve my goal? Or do I have to use something different?
The code is not correct, because with EVENT_TABLE you are setting a handler that doesn't exist.
When the user clicks on the control the event is fired, and the static table will call UserRegistrationFrame::OnAuthCodeOptionLinkClicked, not MyClass::OnAuthCodeOptionLinkClicked
I'd better forget EVENT_TABLES and go with Dynamic Event Handling. Using Bind() gives you more features.
Now, you want to call the event-handler function directly, not coming from a user action. Then you need to create an event just to pass it to the handler. That's what you do in MyClass::MyFunction(), right?
Don't mix jobs. If both your direct-call and the event-handler use a common feature, put it in a different function and call it directly or from the event-handler.
But the question is Why do you use a wxHyperlinkCtrl for a task like screen switching? Do you want also the default browser to be launched?

How to work with the input and output handers in famo.us?

In order to build clean code, Famo.us is using events to communicate to modules. Most of the Event guide shows example about EventHandler. Now we are supposed to build robust view with input and output events, how to actually work with it ? i.e. what is the purpose of the input and output handlers ?
In order to build robust modules is is convenient to separate the code into Widgets which are only responsible for the function they are built for. Here is the official way of building a widget:
function Widget(){
this.eventOutput = new EventHandler();
this.eventInput = new EventHandler();
EventHandler.setInputHandler(this, this.eventInput);
EventHandler.setOutputHandler(this, this.eventOutput);
}
var widget = new Widget();
To summarise the function above it does create an object with 2 EventHandler, one for the input and another one for the output.
Their purpose is trivial:
all the incoming events i.e. the events triggered from outside of the widget object will be triggered to the eventInput handler.
all the outgoing events i.e. events generated by the widget to the outside are triggered through the eventOutput.
To understand a little better, you will very likely be listening to an eventInput handler from inside of the widget and trigger to an eventOutput handler still from inside of the widget code.
Here is an example:
function Widget(){
// here we are inside the Widget code scope
var self = this; // just to keep the root "this" somewhere
this.eventOutput = new EventHandler();
this.eventInput = new EventHandler();
this.eventInput.on("sayHello", function()
{
alert("Hello")
});
function didSomething()
{
self.eventOutput.trigger("didSomething");
}
}
You might then use the widget as follow:
var widget = new Widget();
widget.eventOutput.on("didSomething", function(){alert("The widget did something!")})
widget.eventInput.trigger("sayHello"); // will alert "Hello" from inside the widget
Now we might not be willing to know the internal structure of a widget to use it. Here we are calling and listening on the eventOutput and eventInput which might actually have any name. For the clarity of the code, we can bind those events functions to the widget itself adding the following lines into the widget:
... code ...
EventHandler.setInputHandler(this, this.eventInput);
EventHandler.setOutputHandler(this, this.eventOutput);
... code ...
Now the widget can be listened and triggered in the following way:
widget.on("didSomething", function(){alert("The widget did something!")});
widget.trigger("sayHello"); // will let the widget alert "Hello"
What about piping ?
This is quite simple, while piping a widgetA to a widgetB
widgetA.pipe(widgetB);
All the events triggered by widgetA.eventOutput are piped (read triggered) to widgetB.eventInput
Note: The same principle can be applied on subscription, the following will achieve exactly the same result:
widgetB.subscribe(widgetA);

Raphael JS 2 Hover event

Hi I'm currently experimenting with Raphael JS 2 and have produced a nice circle of paths but after much searching cannot figure out how to implement a hover event on these paths to change the color...
http://jsfiddle.net/goosefat/HYmd2/
This fiddle changes a bit the way you set the hover functions. If that's not what you want, please explain.
http://jsfiddle.net/vzkxC/1/
Raphael's documentation http://raphaeljs.com/reference.html#Element.hover says you can pass the context of the hoverIn and hoverOut functions as third and fourth parameters (in my example they're both cItem). These are the values of the this inside the callbacks.
Of course, you could move the hoverIn and hoverOut functions to an appropriate scope (out of the for loop)
Edit: Marcelo's example is more readabe/maintainable, use his.
You need a closure to achieve it:
(function (cItem) {
cItem.hover(function(){
cItem.attr({"stroke": "#E3E3E3"});
},
function(){
cItem.attr({"stroke": "#000"});
});
})(cItem)
http://jsfiddle.net/yxDap/
Another nice method for you to handle this kind of problems, code here:
(Event handler defined like this)
var hoverIn = function (item) {
return function (event) {
self.hoverFlag = true;
self.hintElementObj = {};
self._drawHint(paper, event, item);
};
};
(Event handler called like this)
paper.rect(x, y, item.rectWidth, item.rectHeight, round).attr({
fill: fill,
"stroke-width": 0
}).hover(hoverIn(item), hoverOut(item));
In fact, this is a JS trick that you could use in many situations. With it you could do many more interesting things.

Configuring new document in MFC

When the user creates a new document in my SDI-application, I need to present a dialog specifying details on the document to be created (think: resolution, bit-depth, etc.) I initially put the code for displaying this dialog in OnNewDocument() (I don't need it when opening an existing document), but putting user-interface code in the document-class just doesn't feel right (also, I don't have any CWnd* to use as a parent for the dialog).
Is there a better place to do this in MFC?
You're right, the document class is no good place for UI.
CDocTemplate::[OpenDocumentFile][1](pszPath) looks like a better candidate:
pszPath==NULL means 'create a new document'.
The method is virtual -> Just derive CMySingleDocTemplate from CSingleDocTemplate and use an instance of this class in CMyWinApp::InitInstance().
This class is responsible for creating docs, frames and views, hence I think it's a good place to put a UI operation.
BOOL CMyWinApp::InitInstance()
{
...
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CMySingleDocTemplate( // <--Derives from CSingleDocTemplate
IDR_MAINFRAME,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
...
}
CDocument* CMySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)
{
CDocument *pDoc =
CSingleDocTemplate::OpenDocumentFile(lpszPathName, bMakeVisible);
if (lpszPathName==NULL)
{
// GUI to get user info
// update doc
m_pOnlyDoc->Blah(input);
// update view
m_pOnlyDoc->UpdateAllViews(NULL,...,...);
}
}
This might not be ideal though: In SDI, there is one and only doc object. It's re-used accross File/Load and File/New operation.
This function will then be called a first time before the initial mainframe is created. You may not want to have a dialog presented to user before the frame is created. Ouch! It's a little more complicated:
Instead of popping up a GUI in in OpenDocumentFile(NULL) as above, just post a custom message/command to the main frame. Then add a handler that will react by the sequence pop up GUI/update doc/update views. That way, the main frame will be displayed before the GUI is popped up and your user will be happier.
This also solves your problem where you don't have a CWnd parent: the main frame is already created and your dialog will use it byt default.
BTW, another solution consists in adding a command handler for ID_FILE_NEW in your CMyWinApp's message map and add your own override of OnFileNew(). But when you write OnFileNew(), I believe you'll quickly find out that it's an ugly solution :-(