How to declare handler for OnPointerEntered using cppwinrt? - c++-winrt

In cppwinrt (xaml not yet available) I have a handler for the PointerEntered event of a Button, and it works fine. But in attempting to remove the default hover behavior of this Button, which displays as an image, it seems I may need to handle the OnPointerEntered event instead - I have seen solutions that involve using a xaml trigger and this would seem to be a code equivalent. But OnPointerEntered has a different argument list, and I can't find a way to invoke it that will build. Here is how the PointerEntered event handle is successfully declared:
button.PointerEntered([&](winrt::Windows::Foundation::IInspectable const & sender, Windows::UI::Xaml::RoutedEventArgs const & args) { EnteredButton(); });
That builds and correctly calls EnteredButton. But
button.OnPointerEntered([&](winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const & e)
{
EnteredButton();
});
will not build - I am declaring it incorrectly but am not sure how, after trying a number of variants. (Using the fully-qualified names is maybe not necessary, but seems not to hurt in either case). Can OnPointerEntered be used in cppwinrt, and how would it be declared if so? I have tried using IPointerRoutedEventArgs instead of PointerRoutedEventArgs with no effect. Or - if anyone knows a different way to disable the hover effect in a Button created with cppwinrt, that would work.

You can't do what you're asking. Echoing IInspectable's comment:
PointerEntered is an event on Windows::UI::Xaml::UIElement. Your code is correctly declaring a handler for it.
OnPointerEntered is not an event, so there is no way to handle it. It is an overridable method for which you can provide your own implementation.

Related

How to use a global InkToolbar for multiple InkCanvas controls?

So I have a ListView made up of multiple InkCanvas controls (which basically are pages of a document). Now I would like to use a global InkToolbar for all of my pages (the InkCanvas controls). However, InkToolbar only allows to bind to a single TargetInkCanvas object and I am not really sure how I can get around that and design my pages so they all share the same InkToolbar.
How to use a global InkToolbar for multiple InkCanvas controls?
InkToolbar only allows to bind to a single TargetInkCanvas in xaml code with x:bind scheme. If you do want a global InkToolbar, please try to set TargetInkCanvas in the code behind when you use the specific InkCanvas.
private void Button_Click(object sender, RoutedEventArgs e)
{
inkToolbar.TargetInkCanvas = MyInkCanvas;
}
Ok so I found a workaround. The solution is rather unelegant but it does work. It is possible to handle pointer input in an InkCanvas prior to processing. This can be done
using CoreInkIndependentInputSource class as follows:
CoreInkIndependentInputSource core = CoreInkIndependentInputSource.Create(inkCanvas.InkPresenter);
core.PointerEntering += PointerEntering;
Then in my PointerEntering event handler, I can change propagate the signal that the current canvas should be bound to the InkToolbar (in my case I had to use VisualTreeHelper to propagate the information to the parent ListView).

Is it possible to HIDE Javascript Object's prototype! What's the MYSTERY behind this?

I'm using openui5. There is a constructor Function for UI control Button,unable to see the prototype properties of the Button but the same thing when executed in browser console, shows up!
sap.m.Button.prototype.Move = function(){
console.log('Move');
}
var oButton = new sap.m.Button({text:"Hello"});
oButton.Move(); // throws undefined function!
The same code when executed browser in console, it works!
jsbin --> http://jsbin.com/tepum/1/edit
After running the code I find that creating the first instance of sap.m.Button causes script to change the prototype of sap.m.Button. It's valid in JavaScript but not very smart if you ask me.
A first creation causes a synchronous request (no no as well) to fetch library-parameters.json.
If you run the code the second time it will have prototype.move because creating an instance of Button will not change the Button.prototype.
The capital M in Move would suggest a constructor function so I would advice changing it to lower case.
Since fetching the parameters is synchronous you can create the first instance and then set the prototype:
console.log("First Button creation changes Button.prototype");
var oButton = new sap.m.Button({text:"Hello"});
sap.m.Button.prototype.move = function(){
console.log('Move');
}
oButton.placeAt('content');
oButton.move(); // logs Move
My guess is that this is done to lazy load controls, if a Button is never created then the json config files are never loaded for these unused controls. It has a couple of drawbacks though.
You have to create an instance first before you can set the prototype.
The config files are synchronously loaded so when creating first instance of many controls with a slow connection would cause the app to be unresponsive.
A better way would be for a factory function to return a promise so you create the control the same way every time and the config files can be fetched asynchronously.
[update]
Looking at the config it seems to be config for the whole gui library so I can't see any reason why this is loaded only after creating a first instance. A library that changes it's object definitions when creating instances is not very easy to extend because it's unpredictable. If it only changes prototype on first creation then it should be fine but it looks like the makers of the library didn't want people to extend it or they would not make the object definition unpredictable. If there is an api documentation available then maybe try to check that.
[update]
It seems the "correct" way to extend controls is to use extend.
#HMR is right the correct way to extend a control is by using the extend function provided by UI5 managed objects, see http://jsbin.com/linob/1/edit
in the example below when debugging as mentoned by others you will notice that the control is lazy loaded when required, any changes you make prior are lost when loaded
jQuery.sap.declare("my.Button");
jQuery.sap.require("sap.m.Button");
sap.m.Button.extend("my.Button", {
renderer: {}
});
my.Button.prototype.Move = function() {
console.log('Move');
};
var oButton = new my.Button({
text: "Hello"
});
oButton.placeAt('content');
oButton.Move();
It's not hiding the prototype per se. If a constructor function exits normally then you get that function's prototype. But, if a constructor function actually returns some other object then you get that other object's prototype, so it's not valid to assume that just because you added to the Button prototype that when you call new Button() that you will see your method on whatever you get back. I'm sure if you de-obfuscate that code you'll find that the constructor you are calling has a "return new SomeOtherInstanceOfButton()" or similar at the end of it.
Edit: Ok it's a bit difficult to see what's really going on in that sap code but, it looks like they have code that overwrites the prototypes of controls to add features to them, such as: sap.ui.core.EnabledPropagator, and those things aren't run until you actually instantiate a button. So if you change your code to instantiate the button on the page, then add to it's prototype, then construct and call the method, it works fine. Like so:
http://jsbin.com/benajuko/2/edit
So I guess my answer is, when you run it from console it's finished mucking around with that prototype, whereas in your test you were adding to the prototype, then constructing the button for the first time (which changes the prototype again) then trying to call your old one, which is no longer there.

Cancelling the onChange event of a dijit/form/FilteringSelect

I need to be able cancel the onChange when a user tries to change value in FilteringSelect depending on if another action has made the information dirty or not.
I have tried to use the FilteringSelect's undo() method, but it's not working. I've tried aspect.before for the onChange event, but that seems to be hooked too late since the control has already got the new value. I tried to hook to the method that calls onChange, but have not been able to find that method.
How do I best accomplish this?
Once the value is set to this widget, the value of "_lastDisplayedValue" also updates. So, undo is not apt for this case.
If the onChange event handler on this widget need to be detached, based on some conditions, "_onChangeActive" private flag can be made use. This is not supposed to be used by programmers explicitly and is for internal purpose of the widget. But, for this case, this can give a hack.
Set _onChangeActive=false, and the handler will be detached. But do not forget to reset it to true again, else, onChange function does not work, if this is set to false.
e.g:
var widget = dijit.byId('widgetId');
widget.set('_onChangeActive',false);
widget.set('value',newValue); //onChange handler function does not run
//not just programmatic,
//even if user tries to select, when onChangeActive=false this works
widget.set('_onChangeActive',true);
//now the onChange is resumed back

Win8 JS App: How can one prevent backward navigation? Can't set WinJS.Navigation.canGoBack

Fairly new to developing for Windows 8, I'm working on an app that has a rather flat model. I have looked and looked, but can't seem to find a clear answer on how to set a WinJS page to prevent backward navigation. I have tried digging into the API, but it doesn't say anything on the matter.
The code I'm attempting to use is
WinJS.Navigation.canGoBack = false;
No luck, it keeps complaining about the property being read only, however, there are no setter methods to change it.
Thanks ahead of time,
~Sean
canGoBack does only have a getter (defined in base.js), and it reflects the absence or presence of the backstack; namely nav.history.backstack.
The appearance of the button itself is controlled by the disabled attribute on the associated button DOM object, which in turn is part of a CSS selector controlling visibility. So if you do tinker with the display of the Back button yourself be aware that the navigation plumbing is doing the same.
Setting the backstack explicitly is possible; there's a sample the Navigation and Navigation History Sample that includes restoring a history as well as preventing navigation using beforenavigate, with the following code:
// in ready
WinJS.Navigation.addEventListener("beforenavigate", this.beforenavigate);
//
beforenavigate: function (eventObject) {
// This function gives you a chance to veto navigation. This demonstrates that capability
if (this.shouldPreventNavigation) {
WinJS.log && WinJS.log("Navigation to " + eventObject.detail.location + " was prevented", "sample", "status");
eventObject.preventDefault();
}
},
You can't change canGoBack, but you can disable the button to hide it and free the history stack.
// disabling and hiding backbutton
document.querySelector(".win-backbutton").disabled = true;
// freeing navigation stack
WinJS.Navigation.history.backStack = [];
This will prevent going backward and still allow going forward.
So lots of searching and attempting different methods of disabling the Back Button, finally found a decent solution. It has been adapted from another stackoverflow question.
Original algorithm: How to Get Element By Class in JavaScript?
MY SOLUTION
At the beginning of a fragment page, right as the page definition starts declaring the ready: function, I used an adapted version of the above algorithm and used the resulting element selection to set the disabled attribute.
// Retrieve Generated Back Button
var elems = document.getElementsByTagName('*'), i;
for (i in elems)
{
if((" "+elems[i].className+" ").indexOf("win-backbutton") > -1)
{
var d = elems[i];
}
}
// Disable the back button
d.setAttribute("disabled", "disabled");
The code gets all elements from the page's DOM and filters it for the generated back button. When the proper element is found, it is assigned to a variable and from there we can set the disabled property.
I couldn't find a lot of documentation on working around the default navigation in a WinJS Navigation app, so here are some methods that failed (for reference purposes):
Getting the element by class and setting | May have failed from doing it wrong, as I have little experience with HTML and javascript.
Using the above method, but setting the attribute within the for loop breaks the app and causes it to freeze for unknown reasons.
Setting the attribute in the default.js before the navigation is finished. | The javascript calls would fail to recognize either methods called or DOM elements, presumably due to initialization state of the page.
There were a few others, but I think there must be a better way to go about retrieving the element after a page loads. If anyone can enlighten me, I would be most grateful.
~Sean R.

Using Dojo to reenable a submit button when a form is edited

I'm trying to build a web app using Dojo. I have a form that posts data via Dojo's xhrPost capabilities to a server side program that saves changes made on the form whenever the user hits the "save" button. What I would like to do is disable the save button after a successful save until the next time something is changed in any of the form's fields to avoid repeated attempts to save an unchanged document.
I tried having Dojo's event watching functionality watch for changes, but have not been successful. The event intended to trigger reenabling the save button never does anything. Here is what I tried:
eventWatching.push(dojo.connect(dijit.byId('editForm'), 'onChange', function() { dijit.byId('saveButton').set('disabled', false); }));
Using onKeyPress instead of onChange seemed promising, but that did not (obviously) reenable the button when the form was edited using the mouse alone.
Prior to 1.6, I don't think dijit.form.Form connects its children's onChange to its own, which is likely why your onChange idea didn't work.
In Dojo 1.6, what you're asking for is easily possible by taking advantage of the fact that widgets now inherit dojo.Stateful functionality:
form.watch('value', function(property, oldvalue, newvalue) {
/* ... */
});
In 1.5 or lower this might take some work; can't think of an easy way off the top of my head but maybe someone else has an idea or one will hit me later.
You can find the code responsible for hooking up the onChange and value-watching functionality in 1.6 here: https://github.com/dojo/dijit/blob/master/form/_FormMixin.js#L396-429
If the newvalue is emptyString the form is valid.
frm1.watch('state',function(property, oldvalue, newvalue) {
console.log(newvalue)
})