How to enable touch events on pjax library? - javascript

I am developing a site where I use Pjax library (a port of jquery pjax). However the touch events don't go through. I am using Pjax like so:
var pjax = new Pjax({ selectors: ["head title", "body"] })
and also have some animations:
document.addEventListener('pjax:send', function(){
var $main = document.querySelector('main')
$main.style.opacity = 0
})
document.addEventListener('pjax:complete', function(){
var $main = document.querySelector('main')
$main.style.visibility = 'hidden'
$main.style.opacity = 0
setTimeout(function(){
document.querySelector('main').style.visibility = 'visible'
document.querySelector('main').style.opacity = 1
attach_menu_control()
}, 10)
})
I need it to work on mobile. The site is www.saulesinterjerai.lt (can be buggy)

I found the solution, it works by redirecting touch event to click event like this:
if (is_touch_device()) {
var all_links = document.querySelectorAll('a[href]')
var event = new Event('click');
for (var index = 0 ; index < all_links.length ; ++index) {
all_links[index].addEventListener("touchend", function() {
all_links[index].dispatchEvent(event)
});
}
}
function is_touch_device() {
return 'ontouchstart' in window // works on most browsers
|| navigator.maxTouchPoints; // works on IE10/11 and Surface
}

Related

How to make ondblclick event works on phone?

I want to achieve the double click event on a specific div like this:
<div id="divID" ondblclick = 'alert("double click!!");' >
it worked on the google chrome browser but when I open it with phone it didn't work, by the way the single click worked.
ps: i added this two things
<meta name="viewport" content="width=device-width, initial scale=1,user-scalable=no">
and this
body {
-ms-touch-action: manipulation;
touch-action: manipulation;}
but it didnt work!
I got the same issue. On touch devices, if you want to detect a double-tap gesture and you use the ondblclick event in most cases it will not work and also the problem is it will also fire an onclick. One of the solution is to implement a double tap detection pattern using the following code sample:
var doubletapDeltaTime_ = 700;
var doubletap1Function_ = null;
var doubletap2Function_ = null;
var doubletapTimer = null;
function tap(singleTapFunc, doubleTapFunc) {
if (doubletapTimer==null) {
// First tap, we wait X ms to the second tap
doubletapTimer_ = setTimeout(doubletapTimeout_, doubletapDeltaTime_);
doubletap1Function_ = singleTapFunc;
doubletap2Function_ = doubleTapFunc;
} else {
// Second tap
clearTimeout(doubletapTimer);
doubletapTimer_ = null;
doubletap2Function_();
}
}
function doubletapTimeout() {
// Wait for second tap timeout
doubletap1Function_();
doubleTapTimer_ = null;
}
And you can call it like
<div id="divID" onclick="tap(tapOnce, tapTwice)" >
tapOnce and tapTwice are your functions which will be called in respective cases. This solution will work on browsers too.
Reference
Here is the external function 'doubletap' which can be helpful:
/*
* jQuery Double Tap
* Developer: Sergey Margaritov (sergey#margaritov.net)
* Date: 22.10.2013
* Based on jquery documentation http://learn.jquery.com/events/event-extensions/
*/
(function($){
$.event.special.doubletap = {
bindType: 'touchend',
delegateType: 'touchend',
handle: function(event) {
var handleObj = event.handleObj,
targetData = jQuery.data(event.target),
now = new Date().getTime(),
delta = targetData.lastTouch ? now - targetData.lastTouch : 0,
delay = delay == null ? 300 : delay;
if (delta < delay && delta > 30) {
targetData.lastTouch = null;
event.type = handleObj.origType;
['clientX', 'clientY', 'pageX', 'pageY'].forEach(function(property) {
event[property] = event.originalEvent.changedTouches[0][property];
})
// let jQuery handle the triggering of "doubletap" event handlers
handleObj.handler.apply(this, arguments);
} else {
targetData.lastTouch = now;
}
}
};
})(jQuery);
Load jQuery Mobile into your project and try using taphold or some of the other mobile specific touch events that are available to you through that API.
Here's the jQuery Mobile documentation with all the events you can use: http://api.jquerymobile.com/category/events/
Here is the snippet for TS React users. Pass in the click event, so that double click is only invoked if the same element is clicked twice
import React from "react";
type CallBack = () => any;
type TapParams = { onSingleTap?: CallBack; onDoubleTap?: CallBack };
var DELTA_TIME_THRESHOLD_MS = 700;
var timer: NodeJS.Timeout | null = null;
var target: EventTarget;
export function tap(
e: React.MouseEvent,
{ onSingleTap, onDoubleTap }: TapParams
) {
if (timer == null) {
// First tap
onSingleTap?.();
timer = setTimeout(() => {
timer = null;
}, DELTA_TIME_THRESHOLD_MS);
} else {
// Second tap
if (e.target === target) {
onDoubleTap?.();
}
clearTimeout(timer);
timer = null;
}
target = e.target;
}
Usage
<div
onClick={(e) => tap(e, { onSingleTap, onDoubleTap })}
>Tap or doubletap</div>
Using only JavaScript
You can use "touchstart" event for a single touch,
but with calculating the time when he should click again
I used 400 (0.4s) as it's the longer duration between two touches
It's only an estimate, but it's still a reasonable time
let expired
let doubleClick = function () {
console.log('double click')
}
let doubleTouch = function (e) {
if (e.touches.length === 1) {
if (!expired) {
expired = e.timeStamp + 400
} else if (e.timeStamp <= expired) {
// remove the default of this event ( Zoom )
e.preventDefault()
doubleClick()
// then reset the variable for other "double Touches" event
expired = null
} else {
// if the second touch was expired, make it as it's the first
expired = e.timeStamp + 400
}
}
}
let element = document.getElementById('btn')
element.addEventListener('touchstart', doubleTouch)
element.addEventListener('dblclick', doubleClick)
In case of this error :
Unable to preventDefault inside passive event listener due to target being treated as passive.
event.preventDefault( ) not working if element = "document" or "document.body"
So the solution of that, you should have a full page div container :
let element = document.getElementById('container')
element.style.minWidth = '100vw'
element.style.minHeight = '100vh'
document.body.style.margin = '0px'
element.addEventListener('touchstart', elementTouch)
element.addEventListener('dblclick', doubleClick)

getElementById in jquery dialog?

I is it any way i can make this work:
document.getElementById('someid').onclick = function(e) {
If the element is in a child html loaded into a jquery-dialog?
Edit:
Just to be clear. Im trying this map-view function which i didn't write myself. It looks like this:
document.getElementById('map-navigation').onclick = function(e) {
var pos = e.target.getAttribute('data-position');
var zoom = e.target.getAttribute('data-zoom');
if (pos && zoom) {
var loc = pos.split(',');
var z = parseInt(zoom);
map.setView(loc, z, {animation: true});
return false;
}
}
It works when i put the anchor on the main page but not if i put it in the child-html which i load into a dialog (#dialog)
$('someid').on('click', function(e) {...}
Something like that will work. on let's you attach events to elements that exist now or will exist in the future.
If that element isn't on the page on load, you could do something like
$('body').on('click','someid', function(e) {...}
UPDATE
To incorporate the code you added, you could write the handler like this:
$('body').on('click','someid', function(e) {
var pos = e.target.getAttribute('data-position');
, zoom = e.target.getAttribute('data-zoom')
, loc
, z;
if (pos && zoom) {
loc = pos.split(',');
z = parseInt(zoom, 10);
map.setView(loc, z, {animation: true});
return false;
}
}
If you are only using click function then you can go for .click() API
$('#yourId').click(function()
{
//Function callback logic
})
Besides this you can also go for .on() (version 1.7+) and .bind() to attach events. Checkout their documentation on http://api.jquery.com/on/ and https://api.jquery.com/bind/
Simply like this:
document.getElementById('idOfYourDialog').getElementId('elementInDialog').onclick = function()
{
//Some Code
}
Or, if you want to do it in JQuery,
$('#idOfYourDialog #elementInDialog').on('click', function()
{
//Some Code
});
Demo

call jquery function after page load not working - Firefox extension

I've been working on Create Firefox extension. i can inject some js file for all webpages. this function works fine.
codevar myExtension = {
init: function() {
// The event can be DOMContentLoaded, pageshow, pagehide, load or unload.
if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);
},
onPageLoad: function(aEvent) {
if ((aEvent.originalTarget.nodeName == '#document') &&
(aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec))
{
//alert('loaded');
var htmlns = "http://www.w3.org/1999/xhtml";
var doc = gBrowser.selectedBrowser.contentDocument;
var filerefs = doc.createElementNS(htmlns,'script');
filerefs.setAttribute("type","text/javascript");
filerefs.setAttribute("src", "http://code.jquery.com/jquery-1.9.1.min.js");
doc.getElementsByTagName("head")[0].appendChild(filerefs);
var filerefst = doc.createElementNS(htmlns,'script');
filerefst.setAttribute("type","text/javascript");
filerefst.setAttribute("src", url+"js/tipped/tipped.js");
doc.getElementsByTagName("head")[0].appendChild(filerefst);
filerefst.setAttribute(tripnow());
}
}
}
function tripnow()
{
//function working fine
var j = $.noConflict();
var imageslist = j('img');
var output = '';
// count image using jquery its not working
alert(imageslist.length);
for (var i = 0, len = imageslist.length; i < len; i++) {
var images = j(imageslist).attr('src');
//alert(images)
Tipped.create(imageslist[i], "htmlphp.php?id="+i,
{
ajax: true,
skin: 'white',
hook: 'topleft',
afterUpdate: function()
{
Cufon.replace('.HummingbirdDemo h1.museo');
}
});
}
}
window.addEventListener("load", function load(event){
window.removeEventListener("load", load, false); //remove listener, no longer needed
myExtension.init();
},false);
I want to call my function after script loads. my function call working fine but my inner function script are in jquery its not working.
Main Problem : I want count current page img tags using jquery
Please advise
To interact with the page in addon-sdk, you have to use a content script. and you can use jquery on those, but not the way are using it. See Content Scripts

Changing erik vold toolbarbutton image on the fly

I'm trying to make a firefox extension with the SDK. (if I can avoid XUL i'm happy)
I'm using erik vold toolbarbutton
But I need to change the toolbar image on the fly.
My lib/main.js (background page) is :
var tbb = require("toolbarbutton").ToolbarButton({
id: "My-button",
label: "My menu",
image: Data.url('off.png'),
onCommand: function(){
Tabs.open(Data.url("signin.html"));
}
});
tbb.setIcon({image:Data.url('on.png')});
console.log(tbb.image);
tbb.moveTo({
toolbarID: "nav-bar",
forceMove: false // only move once
});
tbb.image is correct, but the button isn't refreshed.
I tried to change packages/toolbarbutton-jplib/lib/toolbarbutton.js
function setIcon(aOptions) {
options.image = aOptions.image || aOptions.url;
getToolbarButtons(function(tbb) {
tbb.image = options.image;
tbb.setAttribute("image", options.image); // added line
}, options.id);
return options.image;
}
But it doesn't seem to refresh...
Is erik vold lib enough for this kind of need ?
also be sure to update with this fix https://github.com/voldsoftware/toolbarbutton-jplib/pull/13/files
there is a setIcon method and a image setter that you can use to update the toolbar button's image
I had the same problem so I just wrote the code my self using this tutorial:
http://kendsnyder.com/posts/firefox-extensions-add-button-to-nav-bar
Try this, I rewrote my code to fit your needs:
var btn = null;
var btnId = 'My-button';
var btnLabel = 'My menu';
var btnIconOn = 'on.png';
var btnIconOff = 'off.png';
var {Cc, Ci} = require('chrome');
var self = require("sdk/self");
var mediator = Cc['#mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
// exports.main is called when extension is installed or re-enabled
exports.main = function(options, callbacks) {
btn = addToolbarButton();
// do other stuff
};
// exports.onUnload is called when Firefox starts and when the extension is disabled or uninstalled
exports.onUnload = function(reason) {
removeToolbarButton();
// do other stuff
};
// add our button
function addToolbarButton() {
// this document is an XUL document
var document = mediator.getMostRecentWindow('navigator:browser').document;
var navBar = document.getElementById('nav-bar');
if (!navBar) {
return;
}
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', btnId);
btn.setAttribute('type', 'button');
// the toolbarbutton-1 class makes it look like a traditional button
btn.setAttribute('class', 'toolbarbutton-1');
// the data.url is relative to the data folder
btn.setAttribute('image', self.data.url(btnIconOff));
btn.setAttribute('orient', 'horizontal');
// this text will be shown when the toolbar is set to text or text and iconss
btn.setAttribute('label', btnLabel);
navBar.appendChild(btn);
return btn;
}
function removeToolbarButton() {
// this document is an XUL document
var document = mediator.getMostRecentWindow('navigator:browser').document;
var navBar = document.getElementById('nav-bar');
var btn = document.getElementById(btnId);
if (navBar && btn) {
navBar.removeChild(btn);
}
}
btn.addEventListener('click', function() {
Tabs.open(Data.url("signin.html"));
}, false);
tbb.setIcon({image:self.data.url(btnIconOn)});

Remove specific JS code with a click?

I've tried searching around but couldn't find a solution to this.
I am running two main JS functions on a site I am building. One which is lazy load, and one which is a smooth scroll, the latter for an anchor link to the bottom of the page.
However, with them both being present, they conflict each other as you can't anchor smooth scroll to the bottom of the page with lazyload... it just isn't happening.
Is there a way to disable lazyload if the user clicks on the anchor link? Thus making it work, and if they don't, then the lazyload works just fine?
Lazy Load:
<script>
$("img").lazyload({
threshold : 10000,
placeholder : "images/white.gif",
effect : "fadeIn"
});
</script>
Smooth scroll (although unfortunately this works for ALL anchor links... grrr):
<script>
$(document).ready(function() {
function filterPath(string) {
return string
.replace(/^\//,'')
.replace(/(index|default).[a-zA-Z]{3,4}$/,'')
.replace(/\/$/,'');
}
var locationPath = filterPath(location.pathname);
var scrollElem = scrollableElement('html', 'body');
$('a[href*=#]').each(function() {
var thisPath = filterPath(this.pathname) || locationPath;
if ( locationPath == thisPath
&& (location.hostname == this.hostname || !this.hostname)
&& this.hash.replace(/#/,'') ) {
var $target = $(this.hash), target = this.hash;
if (target) {
var targetOffset = $target.offset().top;
$(this).click(function(event) {
event.preventDefault();
$(scrollElem).animate({scrollTop: targetOffset}, 1400, function() {
location.hash = target;
});
});
}
}
});
// use the first element that is "scrollable"
function scrollableElement(els) {
for (var i = 0, argLength = arguments.length; i <argLength; i++) {
var el = arguments[i],
$scrollElement = $(el);
if ($scrollElement.scrollTop()> 0) {
return el;
} else {
$scrollElement.scrollTop(1);
var isScrollable = $scrollElement.scrollTop()> 0;
$scrollElement.scrollTop(0);
if (isScrollable) {
return el;
}
}
}
return [];
}
});
</script>
Thanks in advance,
R
You could replace the contents of the script with the contents surrounded by comments /* / on click and then re-enable by removing these comments / */. If the script never needs to be used again on the same page you could place the script inside a container element with an id and use jquery to remove that element from the page on click event. Another option that may work would be to alter the javascript to check a 'flag' that is toggled upon clicking the anchor link, the 'flag' can just be a javascript variable in the page that prevents the scripts you don't want to run from running.

Categories

Resources