I am trying to add a Qaptcha feature to my comment form and it works fine but does not function on touch screens.
I read here that all I need to do to solve this issue is to add:
function touchHandler(event)
{
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
{
case "touchstart": type = "mousedown"; break;
case "touchmove": type="mousemove"; break;
case "touchend": type="mouseup"; break;
default: return;
}
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY,
first.clientX, first.clientY, false,
false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
function init()
{
document.addEventListener("touchstart", touchHandler, true);
document.addEventListener("touchmove", touchHandler, true);
document.addEventListener("touchend", touchHandler, true);
document.addEventListener("touchcancel", touchHandler, true);
}
And just call the init() function in my document.ready.
This is part is my document.ready:
$outer.= '<script type="text/javascript">jQuery(document).ready(function(){if(jQuery("p:has(\'textarea\')").length>0) jQuery("p:has(\'textarea\')").before(\'<div class="QapTcha"></div>\'); else jQuery("#comment").before(\'<div class="QapTcha"></div>\');jQuery(\'.QapTcha\').QapTcha({disabledSubmit:true,autoRevert:true});});</script>'."\n";
I tried this but could not make it function. Maybe I am not calling it correctly in document.ready? Can you kindly assist?
Related
I m trying to lock and unlock scroll interactions like this answer.
My Code
var preventDefault = function (e) {
e.preventDefault();
};
var preventDefaultSpecialKey = function (e) {
if (this.keys[e.keyCode]) {
preventDefault(e);
return false;
}
};
class Loader {
keys = { 37: 1, 38: 1, 39: 1, 40: 1 };
supportPassive = false;
get option() { return this.supportPassive ? { passive: false } : false; }
get event() { return "onwheel" in document.createElement("div") ? "wheel" : "mousewheel"; }
constructor() {
try {
const sP = () => (this.supportPassive = true);
window.addEventListener("test",null,
Object.defineProperty({}, "passive", { get: sP })
);
} catch (e) {}
}
open() {
window.addEventListener("DOMMouseScroll", preventDefault, false);
window.addEventListener(this.event, preventDefault, this.option);
window.addEventListener("touchmove", preventDefault, this.option);
window.addEventListener(
"keydown",
preventDefaultSpecialKey.bind(this),
false
); // Special keys
}
close() {
window.removeEventListener("DOMMouseScroll", preventDefault, false); // Throw warning on Firefox
window.removeEventListener(this.event, preventDefault, this.option); // Throw error on Chrome
window.removeEventListener("touchmove", preventDefault, this.option);
window.removeEventListener(
"keydown",
preventDefaultSpecialKey.bind(this),
false
);
}
}
Google Chrome -- Version 96.0.4664.93 (x64)
open method work as well, but after call close, window.removeEventListener(this.event, preventDefault, this.option); that throw an error: "Unable to preventDefault inside passive event listener due to target being treated as passive." when I trying scroll.
Firefox - Version 95.0 (x64)
open method work too, but after call close, window.removeEventListener("DOMMouseScroll", preventDefault, false); that throw the next warning (only one time):
"The "preventDefault()" call on a "DOMMouseScroll" event from a listener registered as "passive" was ignored." when I trying scroll.
I dont understand why error/warning is throwed, because I only remove event and not adding.
Any help will be much appreciate 💌.
first question ever on this page. I have a animated css/js accordion which I took from this page http://codepen.io/chriswrightdesign/pen/cmanI and I have just implemented it in a jsp web application.
It is working very well in Chrome, Firefox and IE 11. But not showing up properly in IE 9. As far as I know there are some js components (classList, setAttribute and querySelectorAll) which I need to polyfill in order to get the functionality working correctly in that last navigator.
To be honest, I don't have the slightest idea on how to polyfill this js code. So I would really apreciate if anyone could help me.
//uses classList, setAttribute, and querySelectorAll
//if you want this to work in IE8/9 youll need to polyfill these
(function(){
var d = document,
accordionToggles = d.querySelectorAll('.js-accordionTrigger'),
setAria,
setAccordionAria,
switchAccordion,
touchSupported = ('ontouchstart' in window),
pointerSupported = ('pointerdown' in window);
skipClickDelay = function(e){
e.preventDefault();
e.target.click();
}
setAriaAttr = function(el, ariaType, newProperty){
el.setAttribute(ariaType, newProperty);
};
setAccordionAria = function(el1, el2, expanded){
switch(expanded) {
case "true":
setAriaAttr(el1, 'aria-expanded', 'true');
setAriaAttr(el2, 'aria-hidden', 'false');
break;
case "false":
setAriaAttr(el1, 'aria-expanded', 'false');
setAriaAttr(el2, 'aria-hidden', 'true');
break;
default:
break;
}
};
//function
switchAccordion = function(e) {
e.preventDefault();
var thisAnswer = e.target.parentNode.nextElementSibling;
var thisQuestion = e.target;
if(thisAnswer.classList.contains('is-collapsed')) {
setAccordionAria(thisQuestion, thisAnswer, 'true');
} else {
setAccordionAria(thisQuestion, thisAnswer, 'false');
}
thisQuestion.classList.toggle('is-collapsed');
thisQuestion.classList.toggle('is-expanded');
thisAnswer.classList.toggle('is-collapsed');
thisAnswer.classList.toggle('is-expanded');
thisAnswer.classList.toggle('animateIn');
};
for (var i=0,len=accordionToggles.length; i<len; i++) {
if(touchSupported) {
accordionToggles[i].addEventListener('touchstart', skipClickDelay, false);
}
if(pointerSupported){
accordionToggles[i].addEventListener('pointerdown', skipClickDelay, false);
}
accordionToggles[i].addEventListener('click', switchAccordion, false);
}
})();
For one, classList is not supported in IE9, so you are definitely going to have to build a fallback if a requirement is IE9 support.
I have a website that generates tables based on results from a database. I would like the user to have the ability to move the tables (which are nested in cells) around to reorder them.
I found an article Here which is pretty close. so I tried messing around with a jsfiddle but I can't get much to work.
Here's the JavaScript:
var dragSrcEl = null;
function handleDragStart(e) {
this.style.opacity = '0.4';
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
}
function HandleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'move';
return false;
}
function handleDragEnter(e) {
this.classList.Add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
function handleDrop(e) {
// this/e.target is current target element.
if (e.stopPropagation) {
e.stopPropagation(); // Stops some browsers from redirecting.
}
// Don't do anything if dropping the same column we're dragging.
if (dragSrcEl != this) {
// Set the source column's HTML to the HTML of the column we dropped on.
dragSrcEl.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text/html');
}
return false;
}
function handleDragEnd(e) {
[].forEach.call(cols, function (col) {
col.classList.remove('over');
});
}
var cols = document.querySelectorAll('td.DashPad');
[].forEach.call(cols, function (col) {
col.addEventListener('dragstart', handleDragStart, false);
col.addEventListener('dragenter', handleDragEnter, false);
col.addEventListener('dragover', handleDragOver, false);
col.addEventListener('dragleave', handleDragLeave, false);
col.addEventListener('drop', handleDrop, false);
col.addEventListener('dragend', handleDragEnd, false);
});
It changes the opacity of the first table upon move, but none of the others. And it does not do drag and drop at all.
Is it possible to do what I am trying to do with table cells that hold tables?
I recommend jQuery for this. There is a sortable method that takes care of this task pretty easy. All I did was add class="sortable" to the outer table and replaced all your javascript with the following:
$('.sortable').sortable({items: '.DashPad'});
Here is a working copy on JSFiddle http://jsfiddle.net/d1s5ur48/3/
More on jQuery sortable:
https://jqueryui.com/sortable/
Re-arranging columns and click is now working on touch devices. Now facing the issue with scrolling. I tried to resolve it with iScroll plugin but it didn't work. The screenshot I took from device mode of chrome browser.
Table columns can be added on-the-fly and so number of columns may vary.
Is there any css way to work scrolling properly ??? If not how do I implement it with javascript or jquery ???
Update:
-webkit-overflow-scrolling: touch; is not working.
Update 2:
Tried with below code:
if (Modernizr.touch) {
$('.container-fluid').css('overflow', 'auto');
}
and this one as well:
if (Modernizr.touch) {
//iScroll plugin
var myScroll = new IScroll('#tblGrid', {
scrollbars: true
});
}
None of them worked.
Update 3:
Below is the code to enable dragging of table columns and click event:
var clickms = 200;
var lastTouchDown = -1;
function touchHandler(event) {
var touch = event.changedTouches[0];
var d = new Date(); var type = "";
switch (event.type) {
case "touchstart": type = "mousedown"; lastTouchDown = d.getTime(); break;
case "touchmove": type = "mousemove"; lastTouchDown = -1; break;
case "touchend": if (lastTouchDown > -1 && (d.getTime() - lastTouchDown) < clickms) { lastTouchDown = -1; type = "click"; break; } type = "mouseup"; break;
default: return;
}
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY, false,
false, false, false, 0, null);
touch.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
function init() {
document.addEventListener("touchstart", touchHandler, true);
document.addEventListener("touchmove", touchHandler, true);
document.addEventListener("touchend", touchHandler, true);
document.addEventListener("touchcancel", touchHandler, true);
}
$(document).ready(function () {
init();
var myScroll;
function loaded() {
myScroll = new IScroll('#tblGrid', {
mouseWheel: true,
scrollbars: true,
click: true,
eventPassthrough: true,
tap: true
});
}
if (Modernizr.touch) {
loaded();
}
});
Update 4:
I tried to use iScroll 4 and scrolling now works. But when I rearrange/drag-drop columns, the scrolling also works and in that case Drag-drop does not work properly due to touchmove event.
And jquery.floatThead also stopped working which fixes the headers.
I'm not entirely sure what your end goal is, but let me see if I understand:
You want to be able to scroll your table horizontally on touch devices. This works right now.
You want to be able to drag and drop your columns to rearrange them. You want to do this by dragging the column headers. Right now, when you do this the touchmove listener is causing the whole table to scroll horizontally when you drag a column, which is a problem.
If I'm correct on the two points above, then I think what might fix your problem is to change init() so that it adds the touch listeners only to your table headers (instead of the entire document). Something like this:
function init() {
$( "th" ).each(function( index ) {
this.addEventListener("touchstart", touchHandler, true);
this.addEventListener("touchmove", touchHandler, true);
this.addEventListener("touchend", touchHandler, true);
this.addEventListener("touchcancel", touchHandler, true);
});
}
You would also need to apply the four event listeners to any new column headers added to the table (wherever you're currently handling you 'add column' logic).
I'm not certain this will 100% work - if you could post a repro of the problem somewhere like http://jsfiddle.net/, it might be easier to help you debug it.
I have a little question of the touch handler...it sometimes work on touch sometimes not, and it cant read my data after i draw it, and it draw with straight line, so i wonder what problem and what i did wrong? please help me..i already put my code into jsfiddle..please help me (http://jsfiddle.net/Frebu/1/)
function touchHandler(event) {
var touches = event.changedTouches,
first = touches[0],
type = "";
switch (event.type) {
case "touchstart": type = "mousedown"; break;
case "touchmove": type = "mousemove"; break;
case "touchend": type = "mouseup"; break;
default: return;
}
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY,
first.clientX, first.clientY, false,
false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
function init(id) {
document.getElementById(id).addEventListener("touchstart", touchHandler, true);
document.getElementById(id).addEventListener("touchmove", touchHandler, true);
document.getElementById(id).addEventListener("touchend", touchHandler, true);
}
$(document).ready(function() {
init('myCanvas');
});​
My recomendation is to use hammer.js, it's a great touch library (that fallbacks to mouse on browsers).
http://eightmedia.github.com/hammer.js/
Aside from that, i didn't have any issues testing the fiddle on Chrome simulating touch events. And altought weird, the code seems to be fine.