I'm looking to hide my "Load More" button when I'm on the last page, but it seems to be refusing to hide the button when scrolling to the last page.
I am using infinitescroll.js
I have the current script to infinite scroll X pages, then show a load more button. Though I think this is causing conflict with checking if it's the last page. I've tried numerous ways, but I can't seem to make it work with both.
I have the following script code.
<script>
let $container = $('.article-feed').infiniteScroll({
path: '.nav-next a',
append: '.card',
history: 'push',
button: '.view-more-button',
hideNav: '.pagination',
status: '.page-load-status'
});
let $viewMoreButton = $('.view-more-button');
// get Infinite Scroll instance
let infScroll = $container.data('infiniteScroll');
$container.on( 'load.infiniteScroll', onPageLoad );
$container.on( 'last.infiniteScroll', onPageLoad, function( event, body, path ) {
console.log(`Last page hit on ${path}`);
$viewMoreButton.attr("style", "display: none !important");
});
function onPageLoad() {
if ( infScroll.loadCount == 1 ) {
// after 2nd page loaded
// disable loading on scroll
$container.infiniteScroll( 'option', {
loadOnScroll: false,
});
// show button
$viewMoreButton.show();
// remove event listener
$container.off( 'load.infiniteScroll', onPageLoad );
}
}
</script>
Any help with this would be great. The console.log reports that it has hit the last page properly, but the button does not hide itself.
Related
I have a cookie warning banner on my site that I want to show for users who have not seen it already (check for cookieInformation cookie and if no, show the banner). The issue is that this used to work with a window.onload function, however recently the window.onload never fires. If I use a document.ready, the banner flashes at the top of the screen before sticking to the bottom where it's supposed to be.
I would set a timeout for the function, however, if this is a foundation loading issue, the flash will still occur on slow loading.
Is there a foundation callback function like foundation.ready that I can use to invoke this function?
.container#cookieTin(data-sticky-container)
.cookiebanner.is-hidden.sticky(in-view="$inview == false ? cookieAccept() : '' ", data-sticky='', data-stick-to="bottom", data-options="stickyOn: small;", data-margin-bottom="0", data-closable )
.small-12.medium-6.columns
strong !{ __("cookie.line_1")}
br
span !{ __("cookie.line_2")}
.small-12.medium-6.columns
a.cookieButton.button !{ __("cookie.line_3")}
button.close-button.cookieButton(aria-label='Close alert', type='button', data-close)
span(aria-hidden='true') ×
The JS:
function showCookieBanner() {
$('.cookiebanner').removeClass("is-hidden");
}
$(document).ready(function () {
$(".cookieButton").click(function () {
closePopup();
});
var closePopup = function () {
$('.cookiebanner').css("display", "none");
createCookie('cookieInformation', 'seen', '15');
return false;
}
if (getCookie('cookieInformation') == null) {
showCookieBanner();
}
});
I've tried adding a .no-js class to no avail as well as eventListeners.
Html is here (note - this part is nested in an iframe):
<div data-reactroot="">
<div class="src-scenes-authenticated-components-sign-in-form-styles__main--I0vWu">
<div class="src-scenes-authenticated-components-sign-in-form-styles__featureList--2RQdY"></div>
<button class="src-components-button-styles__defaultButtonTheme--2-m2n src-components-button-styles__button--2hZHd">
<div class="src-components-button-styles__content--28F4J">
<div class="src-scenes-authenticated-components-sign-in-form-styles__signInButton--3AQAr">Sign In</div>
</div>
</button>
<div class="src-scenes-authenticated-components-sign-in-form-styles__footer--1kMhz"></div>
</div>
</div>
Here is how I've tried targeting the <button> element:
.elementByXPath('/html/body/div[2]/div/div') // parent div of button
.elementByXPath('/html/body/div[2]/div/div/div[1]') // first child
.elementByXPath('/html/body/div[2]/div/div/div[2]') // sibling AFTER button
.elementByXPath('/html/body/div[2]/div/div/button') // error - NoSuchElement
I've tried finding that button using child::button, and following-sibling::button...still no luck. I've also tried finding the <div> elements nested within the button. Still can't find it. I have also tried finding the button element after finding the first child (since it is the second child), still get the same error (NoSuchElement).
Another thing I tried was .moveTo()...which does work, but when I click on it nothing happens.
What am I missing?
Full test code here:
import wd, { asserters } from 'wd';
import configureLogging from './helpers/logging';
import { setup, config } from './helpers/config.js';
const {
capabilities,
testTimeout } = config;
export default function owaChromeLogin() {
describe('Login flow via OWA for Chrome', function() {
this.timeout(testTimeout);
let driver;
setup();
before(function() {
driver = wd.promiseChainRemote();
configureLogging(driver);
let desired = {
...capabilities.owa.chrome
};
return driver.init(desired);
});
after(function() {
return driver;
.quit();
});
// this is all to log into OWA AND the plugin
it('should go to OWA and log in', function() {
return driver
.get('https://outlook.office365.com/owa/')
.elementById('i0116') // username
.type('****#****.onmicrosoft.com')
.elementById('idSIButton9') // 'next' button
.click()
.waitForElementById('i0118', asserters.isDisplayed, 10000, 500) // password field...flaky - StaleElementReference
.type('****')
.elementById('idSIButton9') // 'sign in' button
.click()
.elementById('idSIButton9') // 'yes' button to stay signed in
.click()
.waitForElementByXPath('//*[#id="primaryContainer"]/div[4]/div/div[1]/div/div[4]/div[1]/div/div[1]/div/div/div[2]/div/button', asserters.isDisplayed, 5000, 300)
.should.eventually.exist;
});
it('should click New Email', function() {
return driver
.elementByXPath('//*[#id="primaryContainer"]/div[4]/div/div[1]/div/div[4]/div[1]/div/div[1]/div/div/div[1]/div/button[1]')
.click()
.waitForElementByXPath('//*[#id="primaryContainer"]/div[4]/div/div[1]/div/div[4]/div[3]/div/div[5]/div[1]/div/div[3]/div[4]/div/div[1]/div[2]/div[3]/div[2]/div[1]/button[1]', asserters.isDisplayed, 5000, 300)
.should.eventually.exist;
});
it('should be able to open the Outreach plugin', function() {
return driver
// wait for AND click on Outreach logo button (bottom RH)
.waitForElementByXPath('//*[#id="primaryContainer"]/div[4]/div/div[1]/div/div[4]/div[3]/div/div[5]/div[1]/div/div[3]/div[4]/div/div[1]/div[2]/div[3]/div[2]/div[2]/div/div/div/div/div[1]/div/div/button', asserters.isDisplayed, 5000, 300)
.click()
.waitForElementByXPath('/html/body/div[12]/div/div/div/div/div/div/ul/li[5]', asserters.isDisplayed, 5000, 300) // "Open Outreach"
.click()
// need to target items within iframe
.waitForElementById('exttsp0', asserters.isDisplayed, 10000, 300) // iframe (parent)
.elementByXPath('/html/body/div[2]/div/div') // parent div of button
.elementByXPath('/html/body/div[2]/div/div/div[1]') // first child
.elementByXPath('/html/body/div[2]/div/div/button') // error - NoSuchElement
});
});
}
resolved! After watching my auto test run for the hundredth time, I realized the output of the .waitForElementByXPath('xpath of parent element') was providing several elements instead of just one. This was occurring before the iframe it exists in is loaded. So, I needed to add a time delay (sleep) before trying to target the iframe - .frame(0)...because its all in the first iframe for me), then I was able to target the button by id. I know using .sleep() isn't ideal, but I plan on circling back to that later.
Overall, here is what the test methods look like:
wd.addPromiseChainMethod('getSignInButton', function() {
return this
.sleep(3000)
.frame(0)
.waitForElementById('parentDiv', asserters.isDisplayed, 10000, 300)
.elementById('signInButon')
.click()
});
Just adding the bootstrap-confirmation extension for Bootstrap popover to some buttons on a project. I'm having issues with the options not being respected. I'm trying to get the popups to work as singletons and dismiss when the user clicks outside of them singleton and data-popout options, respectively - both set to true. I'm also not seeing any of my defined callback behavior happening.
I defined the options both in the HTML tags and in a function and neither works. Still getting multiple boxes and they don't dismiss as expected.
My JS is loaded after all other libraries and is in my custom.js file in my footer.
JS is as follows:
$(function() {
$('body').confirmation({
selector: '[data-toggle="confirmation"]',
singleton: true,
popout: true
});
$('.confirmation-callback').confirmation({
onConfirm: function() { alert('confirm') },
onCancel: function() { alert('cancel') }
});
});
An example of the box implemented on a button in my HTML is the following:
<a class="btn btn-danger" data-toggle="confirmation" data-singleton="true" data-popout="true"><em class="fa fa-trash"></em></a>
Any pointers would be appreciated. I even changed the default options in the bootstrap-confirmation.js file itself to what I want and still no luck.
Turns out I needed to rearrange a couple things to get this to work. I've left in the last_clicked_id etc stuff as I needed to add that to get the id value of what I'd just clicked.
// Product removal popup logic
var last_clicked_id = null;
var last_clicked_product = null;
$('.btn.btn-danger.btn-confirm').click(function () {
last_clicked_id = $(this).data("id");
last_clicked_product = $(this).data("product");
});
$('.btn.btn-danger.btn-confirm').confirmation({
singleton: true,
popout: true,
onConfirm: function () {
alert("DEBUG: Delete confirmed for id : " + last_clicked_product);
// TODO: Add AJAX to wipe entry and refresh page
},
onCancel: function () {
alert("DEBUG: Delete canceled for id : " + last_clicked_product);
}
});
I was a step ahead of myself with the callback logic which was not getting executed. Fixed by simply adding it to onConfirm: and onCancel: key values in the .confirmation() function. A bit of a RTFM moment there but this was unfortunately not very clear in the documentation.
I am using MVC Razor - The overall goal is to create a "print view" pop-up page.
The print view button is on the parent page, when clicked, an ajax event is fired which will populate an empty div with the contents that are to be included in the print preview:
//from the view
#Ajax.ActionLink("prntPreview", "Display", new { ID = Model.Detail.ID }, new AjaxOptions { UpdateTargetId = "modal" }, new { #class = "btnPreview" })
then, using JavasScript/jQuery I clone the contents of that newly populated div and create a new window with the contents:
//in the scripts file
$('.btnPreview').on('click', function () {
$(document).ajaxStop(function () {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
}, 300);
});
});
function PopupPrint(data) {
var mywindow = window.open('', '', 'height=500,width=800,resizable,scrollbars');
mywindow.document.write(data);
mywindow.focus();
//do some other stuff here
}
This is where I run into difficulty. The first time I click, everything is working as expected - however, if you do not navigate away from the parent page and try to use the print preview button a second time, the popup will be created twice, then three times etc. with each additional click.
I think that the problem is because each time the .btnPreview is clicked, a new $(document).ajaxStop event is being created, causing the event to fire multiple times.
I have tried to create the ajaxStop as a named function which is declared outside the scope of the click event and then clear it but this produces the same result:
var evnt = "";
$('.btnPreview').on('click', function () {
evnt =
$(document).ajaxStop(function () {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
evnt = "";
}, 300);
});
});
I also have other ajaxStop events initialised so don't want to completely unbind the ajaxStop event. Is it possible to get the name or something from each ajax event so that I can clear just that event or similar?
You can prevent adding additional triggers by checking with a variable outside of scope like this:
(function() {
var alreadyAdded = false;
$('.btnPreview').on('click', function() {
if (!alreadyAdded) {
$('.eventTrigger').click(function() {
console.log('printing!');
});
alreadyAdded = true;
}
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btnPreview">Add Event</button>
<button class="eventTrigger">Trigger</button>
Please note that the variable and function are encapsulated in a self-executing anonymous function and do not pollute global space.
The output of the sample can be seen in the developer console. If you remove the if-check then every click on the "Add Event" button produces an additional print statement on the "Trigger" button each time it is clicked (which is your problem). With the if, there will ever only be one event on the trigger button.
There were 2 issues which I needed to address.
The answer is to unbind the ajax event after it has checked that the request had completed and to unbind and reattach the button click trigger.
This is how I did it:
//in the scripts file
$('.btnPreview').off('click').on('click', function () {
$(document).ajaxComplete(function (e) {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
}, 300);
$(this).off(e);
});
});
I unbound the click event by adding .off('click') before the .on. this is what stopped it popping up multiple times.
The other issue was that anytime any ajax event completed (triggered by something else) that would also create the popup - to get around that, I added $(this).unbind(e); to the end of the code block which removed the ajaxComplete binding which was being triggered each time any ajax event completed.
I am using pretty photo jquery plugin to display slide show, last slide is 'Enter site', when user click on this slide, slide show should stop and user will be redirected to home page of website. How can I implement this.
I tried to use onclick event of and tag but none of them are getting called. I even tried to register onclick event from jQuery using 'on' function but no luck.
Thanks in advance.
Since the callback function is called when prettyPhoto is closed, you need to use:
changepicturecallback, which is called everytime an item is shown/changed.
In this function you have to read the current item and evaluate if it's the last one.
Try this piece of code:
$("a[rel^='prettyPhoto']").prettyPhoto({
animationSpeed:'normal',
slideshow:5000,
show_title: true,
allow_resize: true,
autoplay_slideshow: true,
social_tools: false,
deeplinking: false,
callback: function(){
console.log('pretty photo is closed')
},
image_markup: '<img id="fullResImage" class="fullResImage" src="{path}" />',
changepicturecallback: function(){
var currentSlide = ($('.pp_gallery').find('li').index($('.selected'))+1);
var myArray = jQuery('.currentTextHolder').text().split('/');
if(currentSlide == myArray[1]){
/* Make redirect to your HP */
}
}
});