I'm developing a web application with Kendo Mobile and using the Drawer widget as a menu. One of my views is a Google map and I'd like to disable the swipe-to-open feature of Kendo Mobile's Drawer when in this view, for obvious reasons...
I've tried the following :
Bind to the Drawer's beforeShow event
...and stop it from opening if the current view is the map view
beforeShow: function (beforeShowEvt) {
if(app.view().id == "#stationMap") {
beforeShowEvt.preventDefault();
}
}
The problem with this is that it also trigger's (and prevents drawer from opening) when I click on the menu button in my top bar.
I've looked through the beforeShowEvt and can't seem to find anything to let me know if it was triggered via swipe of via menu click.
Bind to the Google maps containing div
...and catch touchstart events to stop them propagating up and being picked up by Kendo.
This hasn't worked at all.
Here's how I solved my problem :
Added an event handler to Google Map's dragstart event which sets a flag to true
Added an event handler to the Drawer button's touchstart event which sets this flag to false
Added a check in the Drawer's beforeShow event to see if flag is true, if it is I preventDefault();
Works like a charm!
I know this isnt the real answer but I have a work around. Just create a new .html file and put your google widget in that and then call it like so:
app.navigate("nodrawerwidgets.html");
OR
<a href="nodrawerwidgets.html">Google widget<a>
My first thought was to intercept the swipe actions by wrapping your widget in a div :
<div id="divStopSwipe">
...
$("#divStopSwipe").kendoTouch({
enableSwipe: true,
swipe: function (e) { //do nothing or figure out how to let the action pass down to the widget
}
});
..however this would stop the google widget from getting the swipe actions.
hope this helps a little - I am new to mobile ui as well.
Related
I have SAP microchart in smart table.
This smart table has navigation to other app, when user clicks on table row (via "itemPress" method).
Now, I implemented StackedBarMicroChart in one of the columns. I implemented onClick method for the StackedBarMicroChart, which inturn opens an popup showing more details.
When I click on StackedBarMicroChart, due to row-click-event of table, I am navigating to another app before StackedBarMicroChart can open the popup.
How can I override this behaviour, so that if I click on StackedBarMicroChart, it opens popup; If I click anywhere else in table row, it navigates to another app?
Thanks.
I guess this issue is not happening with sap.m controls(e.g. sap.m.Button#press event) since those controls, as a convention, mark the (simulated)touch events but the microchart library controls stop the event propagation for the "click" event which is a different (not a touch) event.
In this case maybe you can check the srcControl parameter of the itemPress event and execute your navigation code only if the srcControl is not a microchart. e.g.
onItemPressHandler: function(oEvent) {
var oSourceControl = oEvent.getParameter("srcControl");
if (oSourceControl.isA("sap.suite.ui.microchart.StackedBarMicroChart")) {
return;
}
this.navigateToNextPage(...);
}
I am trying to create web automation for a site. I am simulating clicks. Usually I add an ID to an element like below and trigger a click using the Chrome developer console and it always works.
p.s: below question is outdated.I am actually trying to click an item from context menu in web.whatsapp.com
<div id="myapp">button1</div>
<script>
$("#myapp").click();
</script>
Or, if that won't work, I use a mousedown event using pure JavaScript like below and it will work smoothly.
function triggerMouseEvent(node, eventType) {
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent(eventType, true, true);
node.dispatchEvent(clickEvent);
}
var targetNode = document.querySelector("#myapp");
triggerMouseEvent(targetNode, "mousedown");
Now my question is: this is not working for the menu that is generated via the jQuery contextMenu plugin.
You can see the demo for contextMenu here, where I am testing the above via the developer console.
So when you right click on the context menu there is a list of menu items listed with ul and li tags.I manually added ID #myapp to one of menu and with below code it is also choosing correct element via developer console.
var targetNode = document.querySelector("#myapp");
targetNode;
But I am unable to trigger a click on that menu item generated via context menu. I was struggling with it for more than 24 hours. I tried all events in JavaScript that I could think of, like mouseup, mousedown, and mouseenter.
You can only click the menu items when the context menu is created, which is done dynamically by the plugin. So, we first need to trigger the menu.
Triggering a native context menu is not possible, as far as I know. Triggering a right click however is possible, you need to use the contextmenu event.
In particular, using $(el).trigger('contextmenu') seems to work fine. This seems to be working because the plugin explicitly supports this. When that is done, we need to trigger a click on the menu item we want to click on.
// first, trigger the context menu
$('.button-that-has-contextmenu').trigger('contextmenu');
// then click the menu item you want to click
// substitute the correct index in `eq(X)` here
$('.context-menu-item:eq(1)').trigger('mouseup');
Because this plugin is not hosted on a CDN, it is not easy to create a snippet here. I have however created a JSFiddle to demo this fully, where I copy + pasted the plugin source into the fiddle.
In the comments, you asked about web.whatsapp.com. I happen to have a WhatsApp account and tested it there. It seems that they are not using the jQuery contextMenu plugin. A $ function is indeed defined, but it appears not to be jQuery, but just a shortcut to document.querySelector.
What their custom context menu code is I don't know, but I did manage to trigger it. Basically, I used the vanilla JS version of the above code and then had to figure out which element to trigger. The latter was easier than I thought. There is a list of chats that is open, .infinite-list-item elements. Their order in the DOM does not match the visual order, but finding the one you want can be done using the browser inspector for example. Given that you have that, you want the .chat element inside of that list item. Say we are interested in the second item, we can select it as follows:
var target = $('.infinite-list-item:nth-child(2) .chat');
You can check in the browser console that you got the right element. Then, fire an event as follows.
var evt = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: true,
view: window,
buttons: 2
});
target.dispatchEvent(evt);
This uses the modern MouseEvent constructor, code is based on this example.
The above will open the context menu in the upper left corner of your browser. You can change the position by passing a clientX and clientY property into the MouseEvent constructor, that represent a position in the window.
When that is done, you can click the items in the context menu. Except you cannot automate this using JavaScript. I peeked at the source and the click handler of those menu items checks if event.isTrusted, meaning that you cannot programmatically trigger a click on them.
You may want to look into using something that can emulate clicks on a lower level, like Selenium 2.0 (WebDriver), or some wrapper around it like WebdriverIO.
I'm using the Twitter API to embed tweets on a page. I'm trying to bind a JQuery context menu to the <a> tags in each tweet by attaching it to the selectors ".hashtag" and ".profile". These CSS classes are already applied to the anchor tags by twitter. The context menu is configured to show up on right clicks.
The problem is the context menu doesn't show up though, I'm assuming somehow the right click event is being blocked by some of Twitter's code so the event isn't getting to the JQuery Context Menu? I've successfully been able to create my own <a> tags and have the context menu work with those so my code is correct.
Not much code to show since libraries are doing most of the work but here is how I'm initializing the context menu, done in $.ready:
$.contextMenu({
selector: '.hashtag, .profile',
build: function ($triggerElement, e) {
console.log(e);
return false;
}
});
If you return false on the build command the contextmenu will not be shown. So if this really is the way you initialize, it won't work.
Have a look at: http://swisnl.github.io/jQuery-contextMenu/docs.html#build
There is also i typo in your keycode, it should be keyCode, with capital.
I have a map which has a google.maps.event.addListener set on the map object for click events to place a marker on the map. Now I want to add a context menu to the markers, so am creating a custom overlay in the floatPane. Again google.maps.event.addListener is used to add a rightclick event to each marker to position and display the menu.
Once the menu is displayed I want it to be cleared by either a menu item being selected, escape being pressed, or a click on the map.
The menu has a div for each items using jQuery .on to attach a click handler to them, whilst when the menu is displayed a keydown handler is attached to the document using .on to check for escape being pressed. These work as desired but I am unable to find a satisfactory solution to detecting a click on the map.
If I use google.maps.event.addListener on the map object to cancel the menu it works, but also registers with the listener to add a marker and event.stopPropagation() does not affect this. i.e. Cancelling the menu also adds a marker. I believe the Google API triggers the handlers in the order they were added with no way to change the priority.
I have also tried using a jQuery .on handler on the div to which the map is attached. But if I use click or mouseup event it is triggered by the right click which adds the menu. i.e. The menu flashes on screen as it appears but immediately closes. A mousedown event avoids this problem, but obviously still triggers the Google API handler to add a marker. It also registers the click to drag the map to scroll it, which the Google API does not and would be the preferred behaviour.
So it seems to me there are only two solutions to this problem.
One would be to cancel any handlers on the map when the menu is displayed, then re-add them once it closes. This seems unnecessarily excessive though.
The other is to make wrap the content of the handlers in a conditional statement to detect whether the menu is open. This could be either by using a global variable as a flag or adding a status property to the menu's object.
But this would make the code less reusable and go against the point of having separate event handlers. I may as well just put the code to close the menu in the original handler too.
Is there anything I am missing? It does not seem to be too obscure a thing to want to do but the inability to set the priority of handlers in the Google API means either having to code the handlers around each other.
For what it's worth, I believe your first approach (adding and removing handlers) is the "cleanest" (or most elegant?) approach.
If you think of the handlers as only having use/meaning when the menu is present, from a conceptual perspective, there's no need for them to exist when the menu is not visible.
If you bundle the event-wiring into the same function(s) or method(s) that handle the menu, then it becomes a self-contained, re-usable element that doesn't leave any "garbage" behind.
Since I don't have your code in front of you, here's some pseudocode:
function displayMenu() {
$menu.show()
.on('click', function() { /* etc */ });
}
function hideMenu() {
$menu.hide()
.off() // remove ALL event handlers
}
Or, even better, encapsulate it in an object:
var menu = {
show: function() {
// ...
}
hide: function() {
// ...
}
};
Or you could use a jQuery function too (though I generally eschew jQuery when I'm working with a map API, just to keep the number of dependencies low).
I want to add a close full screen option to tinyMCE editor. Sometimes users don't know that they have to click "fullscreen" icon from the toolbar to close the fullscreen mode. so in the plug in I've added this:
$('#mce_fullscreen_container').click(function (e) {
e.stopPropagation();
tinyMCE.activeEditor.execCommand('mceFullScreen');
});
However, this is also called when the user clicks inside the wysiwyg area. mce_fullscreen_container is the gray area around the wysiwyg and I want it so that when clicked outside the wysiwyg editor itself the fullscreen mode will close.
I've tried applying .not("#mce_fullscreen_container") which is inside the container without any luck.
The variable named e is the click event. Check the target of the click event and based on that run tinyMCE.activeEditor.execCommand('mceFullScreen'); if appropriate. Fingers crossed that works as I have no way to test it at the moment.
For more advanced TinyMCE programming, look at the setup configuration option which can take a function named that you can use to configure the editor for programmatic events. It's very useful if you need to do multiple things.
http://www.tinymce.com/wiki.php/API3:event.tinymce.Editor.onClick
The example is useful in your context as it may be a cleaner way of getting TinyMCE to do what you want:
// Adds an observer to the onClick event using tinyMCE.init
tinyMCE.init({
...
setup : function(ed) {
ed.onClick.add(function(ed, e) {
console.debug('Editor was clicked: ' + e.target.nodeName);
// check target here to see if it is your close button and if so...
});
}
});