How do you close a vue-material md-menu? - vuejs2

I'd like to call close on a mouseleave event on an md-menu component. I'm using version 0.7.4 of the vue-materiallibrary, and using this documentation it says that there is a close method.
How do I call this method? I've tried the following:
<md-menu md-size="1" ref="aRef" id="aRef">
<div #mouseleave="this.$refs['aRef'].close()">
...other stuff...
</md-menu>
When I run this I get an error saying:
Uncaught TypeError: Cannot read property 'aRef' of undefined
I'm guessing this is something to do with the component not being available at creation time. What's the correct way of doing this?
I should say that the md-menu is actually nested inside another md-menu (which seems to work ok from a functional perspective). Not sure if that screws up the event hierarchy.

I stumbled across the solution for this one while I was trying to solve a different problem (how to close any other menus before opening another).
Your problem is that you can't use this inline in the html template. You need to send the event to a method and then call it...
<md-menu
ref="aRef"
#mouseleave="closeMenu"
>
// menu contents
</md-menu>
Then in your script section:
methods: {
closeMenu() {
this.$refs['aRef'].close();
}
}

Related

sencha touch Cannot read property 'detach' of null comes up that is cause by setActiveItem

I am developing app with sencha touch but facing a problem when activating a tab on a tapPanel
I'm making a tab active by next statement:
tabpanel.setActiveItem('#idLogin');
Everything works fine and the tab is actually activated, but later on (so not directly after this statement) an error appears in the console.log. When removing this piece of code the error doesn't appear so I am sure it is related to this statement.
The error:
Uncaught TypeError: Cannot read property 'detach' of null
Does anybody has faced this issue and were you able to solve?
First, define "later on." Run your app using sencha-touch-all-debug.js to locate the statement throwing the error.
Second, look at the source. You'll see that 'detach' is sencha-speak for 'remove an element from the DOM:"
detach: function() {
var dom = this.dom;
if (dom && dom.parentNode && dom.tagName !== 'BODY') {
dom.parentNode.removeChild(dom);
}
return this;
},
This is invoked in just a few places: when removing an element directly, or when updating an inner wrapper as a result of view navigation or other view swapping.
In most cases, the affected element has animation applied to it, which implies that the error is a side effect of an attempt to remove an element that has already been animated out of scope. The solution, as hacky as it seems, is to get the layout of the parent container, suppress its animation, remove your element, then reapply animation, like this:
container.getLayout().setAnimation(false);
// item removal or view change here;
container.getLayout().setAnimation(true);
I was getting the same error when using a form field with name="id"

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.

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.

How to replace jquery's live for elements that don't exist when the page is loaded

I have seen numerous advice on stackexchange and all over the web suggesting that I not use jquery's live function. And at this point, it is deprecated, so I'd like to get rid of it. Also I am trying to keep my javascript in one place(unobtrusive)--so I'm not putting it at the bottom of the page. I am unclear though on how to rewrite the code to avoid live for elements that don't yet exist on the page.
Within the javascript file for my site I have something like this:
$(function() {
$('button.test').live('click', function(){
alert('test');
});
});
.on( doesn't work since the element doesn't exist yet.
The button is in a page I load in a colorbox pop-up modal window. I'm not sure exactly where that colorbox window sits in the DOM but I think it is near the top.
I could use delegate and attach this to the document--but isn't the whole point of not using live to avoid this?
What is the best way to get rid of live in this case?
You can use .on() - http://api.jquery.com/on/
$(document).on("click", "button.test", function() {
alert('test');
});
If you use live() you can use die().
You can also use on() and off().
They do about the same thing but its recomended to use on.
I ended up avoiding both live and an on attached at the document level. Here's how:
Wrap all of the jquery code specific to objects in a page which loads in the colorbox window in the function like so:
function cboxready(){
...
}
The code wrapped in this function can attach directly to the objects (instead of attaching at the document level) since it will only get run once the colorbox window is open.
Then just call this function using colorbox's callback when you attach the colorbox, like so:
$('a.cbox').colorbox({
onComplete:function(){ cboxready(); }
});

Dojo and unregistering widgets

I am new to the Dojo Toolkit. I'm getting the error
Tried to register widget with id=myButton but that id is already registered
whenever I try to load dojo content twice (meaning I load HTML content through jQuery.Load into a container div). Is there a way of unregistering already registered widgets in dojo? I've seen some examples, but I don't really get them working.
My button:
<button dojoType="dijit.form.Button" id="myButton">button</button>
If you're looking to unregister specific widgets, you can use their destroy() or destroyRecursive() methods. The second one destroys any widgets inside the one you are destroying (i.e. calling destroyRecursive on a form widget will also destroy all the form components).
In your case, it sounds like your best bet would be to do this before jQuery.load -
var widgets = dijit.findWidgets(<containerDiv>);
dojo.forEach(widgets, function(w) {
w.destroyRecursive(true);
});
The above code will unregister all widgets in <containerDiv>, and preserve their associated DOM Nodes. To destroy the DOM nodes, pass false to destroyRecursive instead.
Reference:
http://dojotoolkit.org/api/1.3/dijit/_Widget/destroyRecursive
Based on http://bugs.dojotoolkit.org/ticket/5438, I found a sufficient way of destroying dojo-widgets:
dijit.registry.forEach(function(w){
w.destroy();
});
This worked for me:
dijit.byId( 'myButton' ).destroy( true );
I think you would be better off removing the id from your button and accessing it using an attach point. You would basically do <button dojoType="dijit.form.Button" data-dojo-attach-point="myButton">button</button>
then in your code you would access it like this.myButton.... however im not sure which version of dojo you are using. This will fix any id issues since dojo will assign a unique id to it automatically.