Disable Locomotive Scroll for a specific page - javascript

I'm building a Woocommerce website and I would like to disable Locomotive Scroll on the Checkout page.
I tried this code, but it doesn't work. How could I disable Locomotive for a specific page? My website is not running with Ajax.
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
smoothMobile: true,
getSpeed: true,
getDirection: true
});
window.addEventListener("load", function() {
if ($('.woocommerce-checkout').length) {
scroll.stop();
scroll.destroy();
}
});
Thanks!

You could prevent the initialization of Locomotive Scroll by declaring it within a function like this:
let scroll;
function initLocoScroll() {
if (document.querySelector('.woocommerce-checkout')) return;
scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
smoothMobile: true,
getSpeed: true,
getDirection: true
});
}
initLocoScroll();
// if you are concerned that JavaScript will be unable to find the element
// because it is loaded before the DOM,
// you could replace the previous line with this one:
// window.addEventListener("load", initLocoScroll);
I don't think the '.length'-property is necessary. The jQuery (or querySelector) statement alone should be enough to determine if the element exists.
Another issue might be that the element you are trying to use to determine whether Locomotive Scroll should be active or not cannot be found. Be sure to check that if the error persists.
I hope this was helpful!

Related

Cypress - Always focus element to a given offset from top of screen

When I run tests in Cypress, it always scrolls down to the element, so it is in the very top of the screen. But I'm writing tests for a WordPress system, where the fixed bar always is in the top of the screen taking up 75px (ish). So I can never see what's going on, when my test run.
Are there a way, where I can define all elements, for all tests, to so when they're in focus, that they are 200px from the top? Like a global constant?
Code
cy.get( 'tr[data-slug="cmb2"]' ).should( 'have.class', 'active' );
See the problem here:
Solution attempt 1: Set it in the .env configuration-file
It would be smart if I could set it in the cypress.json-file. I read the docs on Cypress Configuration, but couldn't find it in there.
Solution attempt 2: Hiding the admin-bar with CSS
I could also try and add a stylesheet to always load, when running Cypress-tests in the backend. But is this a normal way to get around it?
And even if I did this, I wouldn't know how to do this.
Solution attempt 3: Use scrollIntoView
I tried adding scrollIntoView with some options:
cy.get( 'tr[data-slug="cmb2"]' ).scrollIntoView({ offset: { top: 150, left: 0 } }).should( 'have.class', 'active' );
But I'm still unable to see the title of my div, when hovering it. I also tried the solution suggested here that looks a bit like it.
Solution attempt 4: Add scrollBehavior to my .env-file
I add that to my .env-file:
{
"env": {
"name": "staging",
...
},
"viewportWidth": 1100,
"viewportHeight": 1800,
"watchForFileChanges": false,
"chromeWebSecurity": true,
"scrollBehavior": "bottom" <---- My attempt!
}
But no cigar:
Related questions
Cypress scrolling behaviour on get and relative positionning
I'm not sure about your Wordpress site, but the following worked for the Material-UI site referenced in Cypress scrolling behaviour on get and relative positionning
.scrollIntoView() offset should be negative
it('make Elvis appear', () => {
cy.viewport(750,480)
cy.visit('https://mui.com/getting-started/templates/dashboard/');
cy.contains('Elvis Presley').scrollIntoView({offset:{top: -100}})
})
use native scrollIntoView
it('make Elvis appear', () => {
cy.viewport(750,480)
cy.visit('https://mui.com/getting-started/templates/dashboard/');
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
cy.contains('Elvis Presley')
.then($el => $el[0].scrollIntoView(false)) // scrolls $el to bottom
})
make header transparent
it('make Elvis appear', () => {
cy.viewport(750,480)
cy.visit('https://mui.com/getting-started/templates/dashboard/');
cy.get('header').invoke('css', 'opacity', '0')
cy.contains('Elvis Presley').scrollIntoView()
})
using .scrollTo()
This command applies to the scroll container, not the element you target, so the positioning may not come out correctly every time.
function getScrollParent(node) {
if (node == null) return null;
if (node.scrollHeight > node.clientHeight) {
return node;
} else {
return getScrollParent(node.parentNode);
}
}
it('make Elvis appear', () => {
cy.viewport(750,480)
cy.visit('https://mui.com/getting-started/templates/dashboard/');
cy.contains('Elvis Presley')
.then($el => {
const scrollParent = getScrollParent($el[0])
cy.wrap(scrollParent).scrollTo('center')
})
})
Actually, there is a bug on this already reported here. Cypress peeps fixed this here. It needs to be merged though.
Solution for element being hidden by website top menu on get(), contains(), click().
Add following to Cypress global config or test config.
From my cypress.config.ts (reduced to focus):
import { defineConfig } from 'cypress'
export default defineConfig({
e2e: {
scrollBehavior: false
}
})
Then scroll "manually" using cy.scrollTo(), cy.scrollIntoView(), dynamically, ...
references:
Cypress configuration: Actionability
StackOverflow: Disable Cypress from automatic scrolling

How to stop swiping at last slide?

I feel bad that I have to ask for help in this forum but the site I downloaded the script from does not have any form of help.
Anyway, I'm using a swiping script from iDangerous Swiper. I can't figure out how to stop the swiping at the last slide or div. Anyway suggestion is much appreciated. I'm using the default swipe.
In the API options section, it says that the default for looping is false...but have you tried explicitly setting it to false?
var mySwiper = new Swiper('.swiper-container', {
speed:750,
loop: false
})
It looks like in their "default" example they are setting loop to true:
var mySwiper = new Swiper('.swiper-container',{
pagination: '.pagination',
loop: true,
grabCursor: true,
paginationClickable: true
})
If you simply remove, the loop property it may fix your issue.
From the documentation for iDangerous Swiper, it looks like you should add the noSwipingClass css class to the div for the last slide.
Via: http://www.idangero.us/sliders/swiper/api.php
noSwipingClass
string
'swiper-no-swiping'
'stop-swiping'
CSS class of html element that will be used to prevent swiping when "noSwiping" parameter is set to true.

jCarouselLite Rebinding Data

I have a jCarouselLite plug in on my website. I am loading the li's from a jquery.load function. I cycle through the carousel vertically and have a function that triggers as soon as the first item comes back around to the top.
At this point, I want to refresh the data with another ajax.load. This is where I run into a problem. Once that data is reloaded, the carousel stops rotating (or rather, is running in the background).
One solution I tried is to try re-instating the carousel with another:
$("#tableapp").jCarouselLite({})
line. This seems to cause two carousels to be running at the same time. And then a third, and 4th, and so on.
So basically I am looking for some way to clear the carousel, reload the updated data, then run it again. Any ideas?
$(document).ready(function () {
updateConsole() //Gets new data
scrollWindow() //Starts carousell
});
function updateConsole() {
$('#tableapp').load('AjaxPages/ApplicationMonitor.aspx #application');
}
function scrollwindow() {
$("#tableapp").jCarouselLite({
vertical: true,
hoverPause: true,
visible: 4,
auto: 6000,
speed: 500,
scroll: 4,
circular: true,
afterEnd: function (a) { ScrollEnd(a); }
});
};
function ScrollEnd(a) {
$('#tbDebug').val($('#tbDebug').val() + '\nScroll Ends');
if (**code that determines slide 1 is back on top**) {
updateConsoles();
scrollWindow(); //If this code is commented, the carousel stops cycling.
//If it isn't commented, two carousels start and things
//get buggy and eventually freezes.
}
}
I am pretty new to javascript, jquery, etc. I also tried this on jCarousel (not lite), but I couldn't get it working with vertical scrolling. It seemed buggy.
Here's a not-particulary thought out suggestion:
When you ScrollEnd, .remove that div.
http://api.jquery.com/remove/
Then recreate it and dump load into it.
Creating a div element in jQuery
Does that trick it into working?

When Jquery jScrollPane is reinitialized, it goes back to the top. Why?

I'm using jquery library jScrollPane to set the custom scroll bar for the whole page.
scroll_bar = $('body>div').jScrollPane(
{
autoReinitialise: true,
showArrows: true,
maintainPosition: false
}).data('jsp');
When new content is added at the bottom of the page (while user is at the bottom of the page), I call:
scroll_bar.getContentPane().find(".content").append(some_content);
scroll_bar.reinitialise();
This reinitializes the scroll bar, but it takes the user to the top of the page. I would like the window to stay at the same spot. Any solutions?
Are you sure you're getting the data needed, I have no idea if this works, but have you tried:
scroll_bar = $('body>div').jScrollPane(
{
autoReinitialise: true,
showArrows: true,
maintainPosition: false
});
scroll_bar.data('jsp');
And would'nt you normally use the .scroll-pane class for this, and not the body>div selector ?
I would think maybe it should be something like this:
var api = scroll_bar.data('jsp');
api.reinitialise();
If you want the scroll bar to retain its position, you should set the
maintainPosition: true
Also, try reconstruct the code like this:
// Use jscrollpane api function to enable reinitialization
var scrollelement = $('body>div').jScrollPane({ maintainPosition: true});
var api = scrollelement.data('jsp');
api.getContentPane().html(result);
// Needed to apply jscrollpane after change new container type
api.reinitialise();
Hope this help :)
From the docs:
maintainPosition [boolean] - Whether you want the contents of the scroll pane to maintain it's position when you re-initialise it - so it doesn't scroll as you add more content (default true)
You set it to false.
For people who have issues re-initializing after the above:
function reinitialiseScrollpane() {
var settings = {
maintainPosition: true,
// add your settings here, below are examples
arrowButtonSpeed: 1,
showArrows: true,
animateScroll: true
};
pane.jScrollPane(settings);
var api = pane.data('jsp');
api.getContentPane().append();
api.reinitialise();
}
The important part is using the settings. Without re-initialising the settings, it can be glitchy. I have put it in a function call, so you simply call this whenever content is altered in any of your scroll panes (assuming you kept the .scroll-pane class with all regions)

Codemirror editor is not loading content until clicked

I am using codemirror 2 and its working fine except that the editor's set value doesn't load into the editor until I click the editor and it becomes focused.
I want the editor to show the content of itself without it having to be clicked. Any ideas?
All of the codemirror demos work as expected so I figured maybe the textarea isn't focused so I tried that too.
$("#editor").focus();
var editor = CodeMirror.fromTextArea(document.getElementById("editor"), {
mode: "text/html",
height: "197px",
lineNumbers: true
});
You must call refresh() after setValue(). However, you must use setTimeout to postpone the refresh() to after CodeMirror/Browser has updated the layout according to the new content:
codeMirrorRef.setValue(content);
setTimeout(function() {
codeMirrorRef.refresh();
},1);
It works well for me. I found the answer in here.
Just in case, and for everyone who doesn't read the documentation carefully enough (like me), but stumbles upon this.
There's an autorefresh addon just for that.
You need to add autorefresh.js in your file.
Now you can use it like this.
var editor = CodeMirror.fromTextArea(document.getElementById("id_commentsHint"), {
mode: "javascript",
autoRefresh:true,
lineNumbers: false,
lineWrapping: true,
});
works like a charm.
I expect you (or some script you loaded) is meddling with the DOM in such a way that the editor is hidden or otherwise in a strange position when created. It'll require a call to its refresh() method after it is made visible.
I happen to be using CodeMirror within a bootstrap tab. I suspected the bootstrap tabs were what was preventing it from showing up until clicked. I fixed this by simply calling the refresh() method on show.
var cmInstance = CodeMirror.fromTextArea(document.getElementById('cm'), {
lineNumbers: true,
lineWrapping: true,
indentUnit: 4,
mode: 'css'
});
// to fix code mirror not showing up until clicked
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function() {
this.refresh();
}.bind(cmInstance));
Something worked for me.
$(document).ready(function(){
var editor = CodeMirror.fromTextArea(document.getElementById("code2"), {
//lineNumbers: true,
readOnly: true,
autofocus: true,
matchBrackets: true,
styleActiveLine: true
});
setTimeout(function() {
editor.refresh();
}, 100);
});
The 5.14.2 version of codemirror addresses this fully with an add on. See this answer for details.
I am working with react, and all these answers did not work with me...After reading the documentation it worked like this:
in the constructor, I initialized an instance of code Mirror:
this.mirrorInstance = null;
and on opening the tab that contains the codeEditor, I refreshed the instance after 1 millisecocnd:
toggleSubTab() {
setTimeout(() => {
this.mirrorInstance.refresh();
}, 1);
}
and here is the JSX code:
<CodeMirror
value={this.state.codeEditor}
options={{
mode: "htmlmixed",
theme: "default",
lineNumbers: true,
lineWrapping: true,
autoRefresh: true
}}
editorDidMount={editor => {
this.mirrorInstance = editor;
}}
/>
I just ran into a version of this problem myself this evening.
A number of other posts regard the visibility of the textarea parent as being important, if it's hidden then you can run into this problem.
In my situation the form itself and immediate surroundings were fine but my Backbone view manager higher up the rendering chain was the problem.
My view element isn't placed on the DOM until the view has rendered itself fully, so I guess an element not on the DOM is considered hidden or just not handled.
To get around it I added a post-render phase (pseudocode):
view.render();
$('body').html(view.el);
view.postRender();
In postRender the view can do what it needs knowing that all the content is now visible on the screen, this is where I moved the CodeMirror and it worked fine.
This might also go some of the way to explain also why one may run into problems with things like popups as in some cases they may try to build all content before displaying.
Hope that helps someone.
Toby
Yet another solution (which I also realised was because the editor needed to be visible to create properly) is to temporarily attach the parent element to the body element during construction, then reattach once complete.
This way, you don't need to meddle with elements, or worry about visibility in any existing hierarchies that your editor might be buried.
In my case, for processr.com, I have multiple, nested code editing elements, all of which need to be created on the fly as the user makes updates, so I do the following:
this.$elements.appendTo('body');
for (var i = 0; i < data.length; i++)
{
this.addElement(data[i]);
}
this.$elements.appendTo(this.$view);
It works great, and there's been no visible flicker or anything like that so far.
Try calling focus on the DOM element instead of the jQuery object.
var editor=$( '#editor' );
editor[0].focus();
// or
document.getElementById( 'editor' ).focus();
<div class="tabbable-line">
<ul class="nav nav-tabs">
<li class="active">
Xml 1
</li>
<li class="">
Xml 2
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tabXml1">
<textarea id="txtXml1" />
</div>
<div class="tab-pane" id="tabXml2">
<textarea id="txtXml2" />
</div>
</div>
</div>
<link rel="stylesheet" href="~/Content/codemirror.min.css">
<style type="text/css">
.CodeMirror {
border: 1px solid #eee;
max-width: 100%;
height: 400px;
}
</style>
<script src="~/Scripts/codemirror.min.js"></script>
<script src="~/Scripts/codemirror.xml.min.js"></script>
<script>
$(document).ready(function () {
var cmXml1;
var cmXml2;
cmXml1 = CodeMirror.fromTextArea(document.getElementById("txtXml1"), {
mode: "xml",
lineNumbers: true
});
cmXml2 = CodeMirror.fromTextArea(document.getElementById("txtXml2"), {
mode: "xml",
lineNumbers: true
});
// Refresh code mirror element when tab header is clicked.
$("#xmlTab2Header").click(function () {
setTimeout(function () {
cmXml2.refresh();
}, 10);
});
});
</script>
Something worked for me! :)
var sh = setInterval(function() {
agentConfigEditor.refresh();
}, 500);
setTimeout(function(){
clearInterval(sh);
},2000)
using refresh help solve this problem. But it seems not friendly
The reason:
CodeMirror won't update DOM content when it's DOM Node is unvisible.
For example:
when the CodeMirror's Dom is setted style to 'display: none'.
The way to fix:
when CodeMirror's Dom is visible, manual excute the cm.refresh() method.
For example in my application, the CodeMirror Dom will visible when the tab element clicked.
So the simple method is:
window.onclick = () => {
setTimeout(() => {
codeMirrorRef.refresh();
}, 10);
};
You can add event listener on more specific element to improve the performance.
chain this to the master codemirror object, make sure that nothing else is chained
.on('change', editor => {
globalContent = editor.getValue();
});;

Categories