Disable Touch on Materialize Carousel - javascript

It looks like no one has asked this question before since I've pretty much scoured the internet looking for a very simple answer.
How would one go about disabling the ability to swipe left/right on the materialize carousel?

in Materialize.js add/edit:
var allowCarouselDrag = true;
value: function _handleCarouselDrag(e) {
if(allowCarouselDrag){
....
}
}
You can set the allowCarouselDrag variable per application.

I solved it like this
// Create carouser
$('#carousel').carousel({
fullWidth: true,
indicators: false,
duration: 100,
});
// Get instance of carousel
carouselInstance = M.Carousel.getInstance(sliderDOM);
// Remove event listeners added by Materialize for corousel
document.getElementById("carousel").removeEventListener('mousedown', carouselInstance._handleCarouselTapBound);
document.getElementById("carousel").removeEventListener('mousemove', carouselInstance._handleCarouselDragBound);
document.getElementById("carousel").removeEventListener('mouseup', carouselInstance._handleCarouselReleaseBound);
document.getElementById("carousel").removeEventListener('mouseleave', carouselInstance._handleCarouselReleaseBound);
document.getElementById("carousel").removeEventListener('click', carouselInstance._handleCarouselClickBound);
After that drag/swipe is disabled and you can still change page/item via
carouselInstance.set(0);
and
carouselInstance.next(0);

This is far from a perfect solution, and it might disable too much of the functionality in your case, I'm not sure. An option to turn this on/off would be much appreciated.
But for my needs, turning off the events on the carousel did the job:
var carousel = $('.carousel.carousel-slider').carousel();
// Disable all swipping on carousel
if (typeof window.ontouchstart !== 'undefined') {
carousel.off('touchstart.carousel');
}
carousel.off('mousedown.carousel');

function tap(e) {
pressed = true;
dragged = false;
vertical_dragged = true;
reference = xpos(e);
referenceY = ypos(e);
velocity = amplitude = 0;
frame = offset;
timestamp = Date.now();
clearInterval(ticker);
ticker = setInterval(track, 100);
}

I have attempted to solve this problem for the past ~three days and have come to the conclusion that there is no clean solution other than directly editing the materialize.js file as in Lester's answer. Unfortunately, this is not an ideal solution as it causes issues when updating Materialize etc.
The simplest solution that I have come up with after this time is the following piece of javascript:
window.onload = function() {
window.mouseDownNow = false;
// The selector below must be more specific than .carousel.carousel-slider in
// order for the event to be cancelled properly.
$('.class-added-to-block-swiping-functionality')
.mousedown(function() {
window.mouseDownNow = true;
})
.mousemove(function(event) {
if(window.mouseDownNow) {
event.stopPropagation();
}
})
.mouseup(function() {
window.mouseDownNow = false;
});
};
This will simply stop the event from bubbling to the Materialize swiping functionality.
Note: I am not sure how specific the selector must be, mine were classes that were specific to text areas.

Related

Vis.js: Adding showPopup in react style

I have a question to ask regarding vis.js popup option. Currently I am trying to implement it in react style so I was using https://github.com/crubier/react-graph-vis/tree/master/example as a starting point.
I realized that in src\index.js file I can add events array since I realize the select option is in there. However, when I do the following:
const events = {
select: function(event) {
var { nodes, edges } = event;
console.log("Selected nodes:");
console.log(nodes);
console.log("Selected edges:");
console.log(edges);
},
showPopup: function(event) {
document.getElementById('root').innerHTML = '<h2>showPopup event</h2>'+ JSON.stringify(params, null, 4);
}
};
I am not able to trigger the popup even at all. Inside the lib\index.js, I noticed that the code is supposed to loop over the events array:
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = Object.keys(events)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var _eventName = _step2.value;
this.Network.on(_eventName, events[_eventName]);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
and I checked that vis.js has the popup option according to the documentation which can be found here: http://visjs.org/docs/network/
I am currently stuck on figuring out how to trigger the popup. There is a requirement to use react since the application will be based on it. It would be great if someone can point out what I did wrong.
Thanks in advance. XD
NOTE: This question is in regards to the github project that I am trying to build on top of. Therefore it is a little different because I am not taking a barebone vis.js
You are mixing things up. showPopup is an event, a function that is called when the popup is shown. You do not call it to show the popup.
To show the popup you simply hover over a node that has a title property.
Check out this fiddle I made (is in pure JS though): http://jsfiddle.net/56t9c0t4/

Animate.CSS - Remove class after end of animation with vanilla JavaScript

I want to make a button so whenever I click it the animation plays. But the problem that I have is when I click the button, the animation doesn't play because the class is already applied. I want to know how to remove the class when the animation is done. I know this can be done with jQuery, but I want to know how to do it with just regular vanilla JavaScript.
Another approach is
ELEMENT.classList.remove("CLASS_NAME");
Versus
document.getElementById("whatever").className = "";
Which removes all classes, not a class
Or perhaps this
div.classList.add("foo");
div.classList.remove("foo");
See more from Remove Class
Try this:
var btn = document.getElementsByClassName("yourBTNClass")[0]; // Your (N-1)th button
btn.onclick = function() {
btn.className = "yourBTNClass"; // Setting the class back to what it was before
animation(); // The function your animation takes place in
btn.className = ""; // Reseting the class
}
Hope you found this useful! :)
If I understand the question correctly, it sounds like you want to know how to modify the class of a particular element with javascript (not jQuery).
This is how I would do it:
document.getElementById("elementId").className = "";
Hope that helps!
EDIT 1
So it sounds like you want the class to be removed automatically once the event has finished, rather than some external action removing the class.
I think the best way to go would be to create your own eventListener function for animation like jQuery has. Here is a good example that I found:
function whichTransitionEvent(){
var t;
var el = document.createElement('fakeelement');
var transitions = {
'transition':'transitionend',
'OTransition':'oTransitionEnd',
'MozTransition':'transitionend',
'WebkitTransition':'webkitTransitionEnd'
}
for(t in transitions){
if( el.style[t] !== undefined ){
return transitions[t];
}
}
}
/* Listen for a transition! */
var transitionEvent = whichTransitionEvent();
transitionEvent && e.addEventListener(transitionEvent, function() {
console.log('Transition complete! This is the callback, no library needed!');
});
Source: https://davidwalsh.name/css-animation-callback

onmouseout and onmouseover

I am working on homework that involves working with javascript. Part of my homework assignment is to use the event handlers onmouseout and onmouseouver. What is supposed to happen when the user hovers over a specific div element, the font size grows by 25%, and when the user mouses out of the div element, the font size goes back to normal. My question is, is it possible to incorporate both an onmouseover function and an onmouseout function into one function? Somehow that is what my teacher wants us to do. I have this started so far.
function FontSize(x)
{
x.style.fonstSize = large;
}
I'm also thinking this isnt the correct code to make the font 25% larger, but I'm not sure how to really incorporate an onmouseout in this function.
As a teacher myself, I am 99% sure that by "one function" the instructor means one general-purpose function to change the font size, not one function which uses conditional statements to work backwards and figure out whether it should be doing onmouseout or onmouseover.
Your script should contain:
function resize(elem, percent) { elem.style.fontSize = percent; }
Your HTML should contain:
<div onmouseover="resize(this, '125%')" onmouseout="resize(this, '100%')"
Text within div..
</div>
Note: Situations such as here, are exactly why JavaScript has the keyword "this"--to save us from needing to use complicated document.getElementById() statements.
You can use "%" property for controlling font-size as described here with the following code.
document.getElementById("div1").onmouseover = function() {
document.getElementById("div1").style.fontSize = "125%"
};
document.getElementById("div1").onmouseout = function() {
document.getElementById("div1").style.fontSize = "100%";
};
Here is the working jsfiddle : http://jsfiddle.net/LxhdU/
Yes you can. Call the same function on both events, and pass a parameter to indicate whether the fontsize should increase or decrease.
ChangeFontSize = function(element, shouldIncreaseFontsize)
{
var small=14;
var large = small * 1.25;
if(shouldIncreaseFontsize) {
element.style.fontSize = large + "px";
}
else {
element.style.fontSize = small + "px";
}
}
http://jsfiddle.net/TMHbW/1/
I'd do something simple like the following. The large and small values can be whatever you need them to be for the font size to work or they can be variables you've defined in prior code.
Demo: http://jsfiddle.net/lucuma/EAbYn/
function doHover(e) {
if (e.type=='mouseover') {
this.style.fontSize = "large";
} else {
this.style.fontSize = "small";
}
}
var el = document.getElementById('myelement')
el.onmouseout =doHover;
el.onmouseover=doHover;
It is possible you do not need to call both the events on the element explicitly instead extension you create will do that.Extend the Element's prototype. Jquery also does similar to this.
Ref Prototype
See Fiddle:- http://jsfiddle.net/4fs7V/
Element.prototype.hover= function( fnOver, fnOut ) {
this.onmouseover=fnOver;
this.onmouseout=fnOut || fnOver;
return this;
};
document.getElementById('test').hover(function(){
//do your mouseover stuff
},
function(){
//do your mouseout stuff
});
Update
Same can be achieved with just one function too:-
Hover me
.largeFont {
font-size:125%;
}
Element.prototype.hover = function (fnOver, fnOut) {
this.onmouseover = fnOver;
this.onmouseout = fnOut || fnOver;
return this;
};
document.getElementById('test').hover(changeMe);
function changeMe()
{
if(this.hasAttribute('class'))
{
this.removeAttribute('class');
}
else
{
this.setAttribute('class', 'largeFont');
}
}

How to disable scrolling in outer elements?

I have a vertically-scrolling div within a page that also scrolls vertically.
When the child div is scrolled with the mouse wheel and reaches the top or bottom of the scroll bar, the page (body) begins to scroll. While the mouse is over the child div, I'd like the page (body) scroll to be locked.
This SO post (scroll down to the selected answer) demonstrates the problem well.
This SO question is essentially the same as mine, but the selected answer causes my page contents to noticeably shift horizontally as the scrollbar disappears and reappears.
I thought there might be a solution that leverages event.stopPropagation(), but couldn't get anything to work. In ActionScript, this kind of thing would be solved by placing a mousewheel handler on the child div that calls stopPropagation() on the event before it reaches the body element. Since JS and AS are both ECMAScript languages, I thought the concept might translate, but it didn't seem to work.
Is there a solution that keeps my page contents from shifting around? Most likely using stopPropagation rather than a CSS fix? JQuery answers are welcome as is pure JS.
here's what i ended up with. very similar to #mrtsherman's answer here, only pure JS events instead of jQuery. i still used jQuery for selecting and moving the child div around, though.
// earlier, i have code that references my child div, as childDiv
function disableWindowScroll () {
if (window.addEventListener) {
window.addEventListener("DOMMouseScroll", onChildMouseWheel, false);
}
window.onmousewheel = document.onmousewheel = onChildMouseWheel;
}
function enableWindowScroll () {
if (window.removeEventListener) {
window.removeEventListener("DOMMouseScroll", onArticleMouseWheel, false);
}
window.onmousewheel = document.onmousewheel = null;
}
function onChildMouseWheel (event) {
var scrollTgt = 0;
event = window.event || event;
if (event.detail) {
scrollTgt = -40 * event.detail;
} else {
scrollTgt = event.wheelDeltaY;
}
if (scrollTgt) {
preventDefault(event);
$(childDiv).scrollTop($(childDiv).scrollTop() - scrollTgt);
}
}
function preventDefault (event) {
event = event || window.event;
if (event.preventDefault) {
event.preventDefault();
}
event.returnValue = false;
}
i've noticed the scrolling doesn't match normal scrolling exactly; it seems to scroll a bit faster than without this code. i assume i can fix by knocking down wheelDeltaY a bit, but it's odd that it would be reported differently by javascript than it's actually implemented by the browser...
I usually do it with a small hack listening to the scroll event on the document: it resets the scroll height back to the original one - effectively freezing the document from scrolling but any inner element with overflow: auto will still scroll nicely:
var scrollTop = $(document).scrollTop();
$(document).on('scroll.scrollLock', function() {
$(document).scrollTop(scrollTop);
});
and then when I'm done with the inner scroll lock:
$(document).off('scroll.scrollLock');
the .scrollLock event namespace makes sure I'm not messing with any other event listeners on scroll.
Although this is an old question, here is how I do it with jQuery. This allows you to scroll a list within an outer list, or you can change the outer list to the document to do what the OP asked.
window.scrollLockHolder = null;
function lockScroll(id){
if (window.scrollLockHolder == null){
window.scrollLockHolder = $('#' + id).scrollTop();
}
$('#' + id).on('scroll', function(){
$('#' + id).scrollTop(window.scrollLockHolder);
});
}
function unlockScroll(id){
$('#' + id).off('scroll');
window.scrollLockHolder = null;
}
And you can use it like this:
<ul onmousemove="lockScroll('outer-scroller-id')" onmouseout="unlockScroll('outer-scroller-id')">
<li>...</li>
<li>...</li>
</ul>
what about this:
div.onmousemove = function() { // may be onmouseover also works fine
document.body.style.overflow = "hidden";
document.documentElement.style.overflow = "hidden";
};
div.onmouseout = function() {
document.body.style.overflow = "auto";
document.documentElement.style.overflow = "auto";
};

How to improve image cross-fade performance?

I want to be able to do a cross fade transition on large images whose width is set to 100% of the screen. I have a working example of what I want to accomplish. However, when I test it out on various browsers and various computers I don't get a buttery-smooth transition everywhere.
See demo on jsFiddle: http://jsfiddle.net/vrD2C/
See on Amazon S3: http://imagefader.s3.amazonaws.com/index.htm
I want to know how to improve the performance. Here's the function that actually does the image swap:
function swapImage(oldImg, newImg) {
newImg.css({
"display": "block",
"z-index": 2,
"opacity": 0
})
.removeClass("shadow")
.animate({ "opacity": 1 }, 500, function () {
if (oldImg) {
oldImg.hide();
}
newImg.addClass("shadow").css("z-index", 1);
});
}
Is using jQuery animate() to change the opacity a bad way to go?
You might want to look into CSS3 Transitions, as the browser might be able to optimize that better than Javascript directly setting the attributes in a loop. This seems to be a pretty good start for it:
http://robertnyman.com/2010/04/27/using-css3-transitions-to-create-rich-effects/
I'm not sure if this will help optimize your performance as I am currently using IE9 on an amped up machine and even if I put the browser into IE7 or 8 document mode, the JavaScript doesn't falter with your current code. However, you might consider making the following optimizations to the code.
Unclutter the contents of the main photo stage by placing all your photos in a hidden container you could give an id of "queue" or something similar, making the DOM do the work of storing and ordering the images you are not currently displaying for you. This will also leave the browser only working with two visible images at any given time, giving it less to consider as far as stacking context, positioning, and so on.
Rewrite the code to use an event trigger and bind the fade-in handling to the event, calling the first image in the queue's event once the current transition is complete. I find this method is more well-behaved for cycling animation than some timeout-managed scripts. An example of how to do this follows:
// Bind a custom event to each image called "transition"
$("#queue img").bind("transition", function() {
$(this)
// Hide the image
.hide()
// Move it to the visible stage
.appendTo("#photos")
// Delay the upcoming animation by the desired value
.delay(2500)
// Slowly fade the image in
.fadeIn("slow", function() {
// Animation callback
$(this)
// Add a shadow class to this image
.addClass("shadow")
// Select the replaced image
.siblings("img")
// Remove its shadow class
.removeClass("shadow")
// Move it to the back of the image queue container
.appendTo("#queue");
// Trigger the transition event on the next image in the queue
$("#queue img:first").trigger("transition");
});
}).first().addClass("shadow").trigger("transition"); // Fire the initial event
Try this working demo in your problem browsers and let me know if the performance is still poor.
I had the same problem too. I just preloaded my images and the transitions became smooth again.
The point is that IE is not W3C compliant, but +1 with ctcherry as using css is the most efficient way for smooth transitions.
Then there are the javascript coded solutions, either using js straight (but need some efforts are needed to comply with W3C Vs browsers), or using libs like JQuery or Mootools.
Here is a good javascript coded example (See demo online) compliant to your needs :
var Fondu = function(classe_img){
this.classe_img = classe_img;
this.courant = 0;
this.coeff = 100;
this.collection = this.getImages();
this.collection[0].style.zIndex = 100;
this.total = this.collection.length - 1;
this.encours = false;
}
Fondu.prototype.getImages = function(){
var tmp = [];
if(document.getElementsByClassName){
tmp = document.getElementsByClassName(this.classe_img);
}
else{
var i=0;
while(document.getElementsByTagName('*')[i]){
if(document.getElementsByTagName('*')[i].className.indexOf(this.classe_img) > -1){
tmp.push(document.getElementsByTagName('*')[i]);
}
i++;
}
}
var j=tmp.length;
while(j--){
if(tmp[j].filters){
tmp[j].style.width = tmp[j].style.width || tmp[j].offsetWidth+'px';
tmp[j].style.filter = 'alpha(opacity=100)';
tmp[j].opaque = tmp[j].filters[0];
this.coeff = 1;
}
else{
tmp[j].opaque = tmp[j].style;
}
}
return tmp;
}
Fondu.prototype.change = function(sens){
if(this.encours){
return false;
}
var prevObj = this.collection[this.courant];
this.encours = true;
if(sens){
this.courant++;
if(this.courant>this.total){
this.courant = 0;
}
}
else{
this.courant--;
if(this.courant<0){
this.courant = this.total;
}
}
var nextObj = this.collection[this.courant];
nextObj.style.zIndex = 50;
var tmpOp = 100;
var that = this;
var timer = setInterval(function(){
if(tmpOp<0){
clearInterval(timer);
timer = null;
prevObj.opaque.opacity = 0;
nextObj.style.zIndex = 100;
prevObj.style.zIndex = 0;
prevObj.opaque.opacity = 100 / that.coeff;
that.encours = false;
}
else{
prevObj.opaque.opacity = tmpOp / that.coeff;
tmpOp -= 5;
}
}, 25);
}

Categories