Hi I am a beginner with raphael and have question.
Whenever I create a raphael object with a callback function (like below), the paper object isn't returned by the call.
var w = 1000;
var h = 400;
var paper = Raphael('svgContainer', w, h, function(){
console.log('callback');
});
paper.setViewBox(0,0,w,h,true);
Why isn't paper the raphael object returned when a callback function is used?
https://dmitrybaranovskiy.github.io/raphael/reference.html#Raphael
Whenever i use a callback function paper.setViewBox fails because paper is some kind of On() event function of eve.
It works without the callback.
var paper = Raphael('svgContainer', w, h);
here is the fiddle about this problem:
jsfiddle.net/svb0y2un/
I'm not quite sure about your none working code of your intent, as you are alerting outside of the callback, so paper may not be defined (as the callback may be called after that).
I 'think' what you need is to understand that the callback function is passed the paper element as the 'context' for the function. This means it will be passed into the 'this' variable inside the callback. So for example this should work....
var paper = Raphael('svgContainer', w, h, function(){
console.log('callback');
alert('working typeof of paper: '+typeof(this));
this.setViewBox(0,0,w,h,true);
});
jsfiddle
Related
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(); };
}
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.
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.
I'm writing an (unmanaged) C++ class to wrap the Windows PropertySheet. Essentially, something like this:
class PropSheet {
PROPSHEETHEADER d_header;
public:
PropSheet(/* parameters */);
INT_PTR show();
private:
static int CALLBACK *propSheetProc(HWND hwnd, UINT msg, LPARAM lParam);
};
The constructor just initializes the d_header member:
PropSheet::PropSheet(/* parameters */) {
d_header.dwSize = sizeof(PROPSHEETHEADER);
d_header.dwFlags = PSH_USECALLBACK;
// ...
d_header.pfnCallback = &propSheetProc;
// ...
}
After which I can show it, modally, with:
INT_PTR PropSheet::show() {
return PropertySheet(&d_header);
}
Now the problem is, because the callback is static, that it cannot access the wrapper class. If this were a normal window, with a WindowProc instead of a PropSheetProc, I could attach some extra data to the window using cbWndExtra in WNDCLASS, in which I could store a pointer back to the wrapper, like in this article. But property sheets do not offer this functionality.
Furthermore, because the property sheet is shown modally, I can execute no code between the creation and destruction of the actual window, except when that code is executed through the callback or one of the sheets's window procedures.
The best solution I've come up with so far is to, right before showing the property sheet, store a pointer to the wrapper class inside a global variable. But this assumes that I'll only be showing one property sheet at a time, and is quite ugly anyway.
Does anyone have a better idea how to work around this?
As you are showing the property sheet modally, you should be able to use the parent window (i.e. its handle) of the property sheet to map to an instance, using ::GetParent() on the hwndDlg parameter of PropSheetProc().
Awesome, yet another Win32 API that uses callbacks without a user-defined context parameter. It is not the only one, alas. e.g. CreateWindow is bad (it gives you user-defined context, but that context isn't available for the first few window messages), SetWindowsHookEx is even worse (no context at all).
The only "solution" that is general-purpose and effective is to emit a small piece of executable code with a 'this' pointer hardcoded. Something like this: http://episteme.arstechnica.com/eve/forums/a/tpc/f/6330927813/m/848000817831?r=848000817831#848000817831
It's horrible.
The PROPSHEETPAGE structure has an lParam field available for callbacks. In your PROPSHEETHEADER, you can include the PSH_PROPSHEETPAGE flag to pass an array of PROPSHEETPAGE items describing your pages, or omit the flag to pass an array of preallocated HPROPSHEETPAGE handles instead (which means using CreatePropertySheetPage(), and thus using PROPSHEETPAGE anyway).
You've already admitted "I can execute no code between the creation and destruction of the actual window". It seems that a global variable wouldn't be a terrible hack.
I've found another option: using SetProp to add a property that stores the pointer to the wrapper. Only requires the global variable once, to be able call SetProp from the property sheet callback.
I've created a very simple one-button MFC dialog app that attempts to utilize a callback function. The app complies and runs just fine, but the callback routine never gets triggered.
What needs to be modified in order to get the callback to trigger properly?
You can download the test.zip file here (the test app is in VS 2003 to ensure more people can try it out): http://tinyurl.com/testfile-zip
The code utilizes an alarm class on CodeProject, and the callback function is suppsed to get triggered every 3 seconds (as determined by the code being passed in).
Thanks!
I've looked at your code and the I believe the Function called from the button is the problem
void CTestDlg::OnBnClickedButton1()
{
CAlarmClock clock;
REPEAT_PARMS rp;
ZeroMemory(&rp, sizeof(REPEAT_PARMS));
rp.bRepeatForever = TRUE;
rp.Type = Repeat_Interval;
rp.ss = 3;
clock.SetRepeatAlarm(0, 0, 0, rp, CallbackRtn);
}
This creates the Alarm clock on the function stack.
This CAlarmclock object is therefore destroyed at the end of the function along with its contents.
For it to be able to exist for long enough to actually do the callback
you need to add it as a member variable of your dialog class for it to exist and callback for as long as the dialog exists.
See the example code on the CAlarmclock codeproject page for how to use this class correctly.