Polymer: How to test "on-tap" in mocha? - polymer

I have a component that when tapped on mobile, it hides an overlay and shows a description (like a hover does on desktop).
So far for desktop I've been testing mouse events such as mouseenter on my components by using myElement.fire("mouseenter"):
test('it shows the description on hover', function() {
var actionCardOverlay = missionCard.querySelector('ct-action-card-overlay');
var actionCardDescription = missionCard.querySelector('ct-action-card-description');
actionCardOverlay.fire("mouseenter");
expect(actionCardDescription.hidden).to.equal(false);
});
However when trying to test mobile, it doesn't look like my tap events are firing in my tests when I do something like myElement.fire("tap"):
suite('when user is using a mobile device', function() {
test('it shows the description on tap', function() {
var actionCardOverlay = missionCard.querySelector('ct-action-card-overlay');
var actionCardDescription = missionCard.querySelector('ct-action-card-description');
actionCardOverlay.fire("tap");
expect(actionCardDescription.hidden).to.equal(false);
});
test('it hides the overlay on tap', function() {
var actionCardOverlay = missionCard.querySelector('ct-action-card-overlay');
var actionCardDescription = missionCard.querySelector('ct-action-card-description');
actionCardOverlay.fire("tap");
expect(actionCardOverlay.hidden).to.equal(true);
});
});
Here's a simplified version of my code in JSFiddle. I've also verified that the demo works on mobile: https://jsfiddle.net/Lnws78cb/1/
What event would I fire? In other words, how would I simulate a tap on the element?
I'm using these test frameworks:
"chai": "^3.2.0",
"mocha": "^2.2.5",
"sinon": "^1.15.4",
"sinon-chai": "^2.8.0",
"supertest": "^1.0.1",
"web-component-tester": "^3.4.2"

You need to create a custom event instance
myElement.fire(new CustomEvent('tap'));

Related

Google maps on mobile with gestureHandling = cooperative still fires click event

When on a mobile device, if I want to scroll the page by clicking somewhere on the Google map and scrolling down, I still receive a click event.
I see the "use two fingers to move the map" message, and the page is scrolling as expected but I receive a click event after. And I use this click event to add a marker. So at this point, it's messing the behavior of the whole page.
Here is a simple jsfiddle to reproduce (on mobile of course, or in mobile mode on chrome https://developers.google.com/web/tools/chrome-devtools/device-mode/):
Just scroll down while clicking on the map and an alert with the text "Click Event" will popup.
google.maps.event.addListener(map, 'click', function (evt) {
alert("Click Event");
});
https://jsfiddle.net/83o1my1p/
I believe this problem has already been reported in Google issue tracker. Have a look at the following bug:
https://issuetracker.google.com/issues/64586414
Feel free to add a star in the bug to express your interest and subscribe to notifications. Also, note that the person who filed the bug also found a workaround:
The clicks can be prevent after the scroll, the same way they they are prevented after dragend events when using on a desktop. As I said above, I worked around it myself by handling the mousedown event, and comparing the location of it, to the location of the click event.
I hope this helps!
Here is the work around I used.
var mouseDownPos = null;
google.maps.event.addListener(map, 'mousedown', function(e) { mouseDownPos = e.pixel });
google.maps.event.addListener(map, 'click', function(e) {
var mouseUpPos = e.pixel;
var distance = Math.sqrt(Math.pow(mouseDownPos.x - mouseUpPos.x, 2) + Math.pow(mouseDownPos.y - mouseUpPos.y, 2));
if(distance > 10) return; // Adjust for tolerance
// Do what you need here
});
My solution is to use a var and change it state on touch events. Then use it in the click event:
var dragged = false;
google.maps.event.addListener(map, 'click', function (evt) {
if (!dragged) {
// Do stuff here
}
});
google.maps.event.addDomListener(canvas, 'touchmove', function (event) {
if (event.touches.length == 1) {
dragged = true;
}
});
google.maps.event.addDomListener(canvas, 'touchend', function(event) {
dragged = false;
});

Extending sap.ui.core.Icon with hover event or mouseover

I extended sap.ui.core.Icon with hover event handling:
sap.ui.define(function () {
"use strict";
return sap.ui.core.Icon.extend("abc.reuseController.HoverIcon", {
metadata: {
events: {
"hover" : {}
}
},
// the hover event handler, it is called when the Button is hovered - no event registration required
onmouseover : function(evt) {
this.fireHover();
},
// add nothing, just inherit the ButtonRenderer as is
renderer: {}
});
});
The event onmouseover is never fired. I also used this extension for sap.m.Button and it works. But I need this for sap.ui.core.Icon.
I also tried this jquery example but it did not work at all.
$("testIcon").hover(function(oEvent){alert("Button" + oEvent.getSource().getId());});
Please, do you have any idea why event handler onmouseover is not called for sap.ui.core.Icon? Or can you propose some other solution?
Bellow is how I added icon to my sap.suite.ui.commons.ChartContainer:
var oFilterIcon = new HoverIcon({
tooltip : "{i18n>filter}",
src : "sap-icon://filter",
hover : function(oEvent){alert("Button" + oEvent.getSource().getId());},
});
this.byId("idChartContainer").addCustomIcon(oFilterIcon);
This is my analysis:
Your new custom Control Icon for hover is correct. If you will use it independently it will work correctly .
However, your custom control will not work as your icons are converted to sap.m.OverflowToolbarButton when you use ChartContainer.
I looked into the source code of Chart Container and below is the code:
sap.suite.ui.commons.ChartContainer.prototype._addButtonToCustomIcons = function(i) {
var I = i;
var s = I.getTooltip();
var b = new sap.m.OverflowToolbarButton({
icon: I.getSrc(),
text: s,
tooltip: s,
type: sap.m.ButtonType.Transparent,
width: "3rem",
press: [{
icon: I
}, this._onOverflowToolbarButtonPress.bind(this)]
});
this._aCustomIcons.push(b);
}
So, you Icon is not used but its properties are used. As this is standard code, your hover code of Custom icon is not passed along.
One solution will be to add the onmouseover to sap.m.OverflowToolbarButton :
sap.m.OverflowToolbarButton.prototype.onmouseover=function() {
alert('hey')
};
However, this is dangerous as all OverflowToolbarButton button start using this code and I will not recommend it.
Next solution would be to overwrite the private method:_addButtonToCustomIcons ( again not recommendred :( )
sap.suite.ui.commons.ChartContainer.prototype._addButtonToCustomIcons = function(icon) {
var oIcon = icon;
var sIconTooltip = oIcon.getTooltip();
var oButton = new sap.m.OverflowToolbarButton({
icon : oIcon.getSrc(),
text : sIconTooltip,
tooltip : sIconTooltip,
type : sap.m.ButtonType.Transparent,
width : "3rem",
press: [{icon: oIcon}, this._onOverflowToolbarButtonPress.bind(this)]
});
this._aCustomIcons.push(oButton);
//oButton.onmouseover.
oButton.onmouseover = function() {
this.fireHover();
}.bind(oIcon);
};
Let me know if this helps u. :)

HTML 5 Drop File only in a div

I am doing JSF primefaces project.We have primefaces file upload component in a div id="dropBox" which accepts drag and drop files.Normally if you drop a file anywhere on the page, browser opens it up.I want to disable this behavior and allow drops only in the div dropBox. following code disables file drag and drops on entire page .
$(document).bind({
dragenter: function (e) {
e.stopPropagation();
e.preventDefault();
var dt = e.originalEvent.dataTransfer;
dt.effectAllowed = dt.dropEffect = 'none';
},
dragover: function (e) {
e.stopPropagation();
e.preventDefault();
var dt = e.originalEvent.dataTransfer;
dt.effectAllowed = dt.dropEffect = 'none';
}
});

Jquery mobile doesn't follow a link comming from another JQM page

I'm using the jquery-ui-map plugin and my test page (test.html) loads a Google Map correctly when I click the button. This SAME test.html don't work if a load it from another jquery mobile page. What I'm doing bad or what I'm missing? Next the significant code:
Javascript in the header (like in the example for the basic map):
var mobileDemo = { 'center': '57.7973333,12.0502107', 'zoom': 10 };
$('#basic_map').live('pageinit', function() {
demo.add('basic_map', function() {
$('#map_canvas').gmap({
'center': mobileDemo.center,
'zoom': mobileDemo.zoom,
'disableDefaultUI':true,
'callback': function() {
var self = this;
self.addMarker({'position': this.get('map').getCenter() }).click(function() {
self.openInfoWindow({ 'content': 'Hello World!' }, this);
});
}});
}).load('basic_map');
});
$('#basic_map').live('pageshow', function() {
demo.add('basic_map', function() { $('#map_canvas').gmap('refresh'); }).load('basic_map');
});
And the html (sorry, I can't post the HTML code because it's interpretatded, but the link is below):
http://www.medlifesolutions.com.mx/locations/mobile/test.html
As I said, this works perfect if I write test.html in the browser directly but if comes from another page:
http://www.medlifesolutions.com.mx/locations/mobile/main.php
it simply ignores a "click" or touching the button to show the map. Thanks in advance for your help.
One problem I see in your code is the use of live. It is recommended to replace live with on.

dojo 1.8 integrating html5 postmessage

Im trying to get some html5 post messaging going with dojo 1.8, i've created a jsfiddle to try to explain it better. One thing to note is that the button is being loaded within the iframe. So basically if a click happens within the iframe then the parent node should receive and act upon the message. Any pointers would be appreciated.
http://jsfiddle.net/AvPFv/
Basically, you should listen for message on iframe window, i.e. iframe.contentWindow. Also, please note there is no dojo in your iframe.
I created a jsFiddle to show how it works: http://jsfiddle.net/phusick/H7Zh8/ but I'm afraid it is very messy to have everything in a single file, i.e. in the context of the parent window, because it does not explain properly where window reference points to and it does not simulate real world usage. I suggest you try it at localhost having two sets of scripts, one for parent window and one for iframe.
require([
"dojo/dom",
"dojo/on",
"dojo/date/locale",
"dojo/domReady!"
], function(
dom,
on,
locale
) {
var buttonNode = dom.byId("postMessageButton");
var iframeNode = dom.byId("iframe");
var iframe = iframeNode.contentWindow;
var iframeButtonNode = iframe.document.getElementById("postMessageButton");
on(buttonNode, "click", function() {
iframe.postMessage("hello from parent", "*");
});
on(iframe, "message", function(event) {
var msgNode = iframe.document.getElementById("msg");
msgNode.innerHTML += formatMessage(event);
event.source.postMessage("echo from iframe", "*");
});
on(iframeButtonNode, "click", function() {
iframe.parent.postMessage("hello from iframe", "*");
})
on(window, "message", function(event) {
dom.byId("msg").innerHTML += formatMessage(event);
});
function formatMessage(event) {
var time = locale.format(new Date(event.timeStamp),{
selector: "time",
formatLength: "medium"
});
return time + ": " + event.data + "<br>";
}
});