Ionic 3 Infinite Scroll fire event only fire once - javascript

I am doing an app in Ionic 3 and using infiniteScroll inside a and . I see common issues in github and even here in SO. But most of it has no solution.
The problem is when the page is loaded and render all the data that is paginated from the backend when I get an API request. Now I had a infiniteScroll event when I scroll to the bottom part of my page. But the problem is that it only trigger once and load my data. If I want to load a new one I have to go back at the top of the content and go down again to load some data.
Here is my code in my typescript file below:
I used a viewChild for Scroll native element of Ionic inside my <ion-slide>
Here is the structure of my html below:
<ion-slide *ngIf="!preloader">
<ion-scroll #scrollWeb scrollY="true">
<! -- Content Part for loop of an array with data from a server -->
<!-- Load more for following -->
<ion-infinite-scroll *ngIf="selectedSegment == 'first' && !pulling" (ionInfinite)="loadMorePost($event)">
<ion-infinite-scroll-content
loadingSpinner="crescent"
loadingText="Loading more post..."
>
</ion-infinite-scroll-content>
</ion-infinite-scroll>
<small *ngIf="noMorePostToShowForExplore">No more post to show</small>
</ion-scroll>
</ion-slide>
And the typescript
loadMorePost(infiniteScroll? :any) {
console.log('Async operation begun')
setTimeout(() => {
if (this.selectedSegment == 'first') this.loadMoreExplore()
else this.loadMoreFollowing()
infiniteScroll.complete();
}, 1000);
}
As I have said earlier about the viewChild I tried to trigger the y-axis scroll and only allow to refresh if it is at the most bottom part of the page. Which is still not working.
this.scrollWeb.addScrollEventListener((ev) => {
if ((ev.target.offsetHeight + ev.target.scrollTop) >= ev.target.scrollHeight) {
// this.loadMorePost(InfiniteScroll)
console.log('Loading post')
}
})
Appreciate if someone could help.
Thanks in advance.

Related

How can I load next page and run animation on that page with one click?

So the thing is that I want to click a button on ./page.html so it opens ./index.html and the animation starts.
Pages are same domain
I don't want animation to start every time I open the ./index.html only when I click the button
I'd like it to be vanilla JS solution but jquery is ok
the main problem I can't solve is that I trigger button with specific id and the console says "Cannot read properties of null (reading 'addEventListener')"
In other words in ./index.html I have a nav bar with links but one of the sections mentioned in nav bar is already present in ./index.html so I decided to highlight it with animation when I click that link. On ./page.html I still have same nav bar with same links (surprise) but this time I want when I click that button to open ./index.html first and then play the animation to highlight that section
I tried different solutions including setting a delay, using localStorage and iframe but none of these worked for me (or I was using them wrong)
Here's the minimization of the code
./index.html (section with class skills is the element where I want the animation to play)
<nav>
<a id="skills-button-main" class="buttons corner-nav" href="#">skills</a>
</nav>
<section class="skills" id="skills-panel">
</section>
./page.html (button that I want to click so the animation on ./index.html plays)
<nav>
<a id="skills-button-projects" class="buttons" href="./index.html">skills</a>
</nav>
JS (this is how I make animation play every time I click on #skills-button-main in ./index.html)
if(document.getElementById("skills-button-main")){
$("#skills-button-main").click(function() {
const el = $("#skills-panel").addClass("skills-animation");
setTimeout(function() {
el.removeClass("skills-animation");
}, 2000);
})};
}
JS (this is one of the variation I tried to do same thing but with loading ./index.html page first)
if (document.getElementById("skills-button-projects")){
document.getElementById("skills-button-projects").addEventListener("click", function() {
window.location.href = "./index.html";
if(document.getElementById("skills-button-main")){
$("#skills-button-main").click(function() {
const el = $("#skills-panel").addClass("skills-animation");
setTimeout(function() {
el.removeClass("skills-animation");
}, 2000);
})};
});
}
I'm using if statement at start because it's the same .js file so the script runs even if ID's doesn't exist on current html
Please somebody help
i hope this answer could help you.
with document.referrer you can get previous page that refer you to current page.
and with performance.navigation.type you can check that page was not reloaded.
window.performance.navigation property is deprecated and you can use this answer to improve your code if you want . i did not use it for a simpler answer.
window.addEventListener('load', ()=>{
const section = document.getElementById('skills-panel');
if(!performance.navigation.type && document.referrer.includes('/page.html')){
section.classList.add('add')
section.addEventListener('animationend', ()=>{
section.classList.remove('add')
})
}
})
i put the whole codes on animateafterload.w3spaces.com

How to scroll a Ionic-Page via JavaScript Test-code

I'm working on an Ionic 6 Webapp based on Angular 13. The client's QA-department want's to perform regression-testing via Selenium test-automatization. For other project's they used window.scrollBy(0, window.innerHeight) to systematically scroll over the page and take screenshots to find regression issues. But this is not possible on Ionic pages, since the HTML body is not scrollable, only the content of the ion-content element. Is there any way to trigger scrolling within the ion-content element via simple JavaScript? I created a Stackblitz where you can see the basic structure of my ionic-page.
So far I tried different things but none worked:
document.getElementsByTagName("ion-content")[0].scrollTo(0, 300);
document.getElementsByTagName("ion-content")[0].scrollToBottom();
document.getElementsByTagName("ion-content")[0].shadowRoot.childNodes[1].scrollTo(0, 300); //tried to access the inner-scroll div
document.getElementsByTagName("ion-content")[0].shadowRoot.childNodes[1].scrollToBottom(); //tried to access the inner-scroll div
why do you want JavaScript to scroll when ionic and angular have a better way to scroll. please check the stackblitz link I have done some code in it.
HTML
<ion-app>
<ion-header>Demo Header</ion-header>
<ion-content>
<div class="large-content-div"></div>
<p id="scrollMe">Scroll to find me</p>
</ion-content>
<ion-footer>Demo footer</ion-footer>
</ion-app>
TS File
export class AppComponent {
name = 'Ionic 6 Angular ' + VERSION.major;
constructor() {
setTimeout(() => {
this.scrollToBottom();
}, 5000);
}
scrollToBottom(): void {
try {
document.querySelector('#scrollMe').scrollIntoView({
behavior: 'smooth',
});
} catch (err) {}
}
}
Here, I have given both the solution if you want to scroll to the bottom scrollToBottom() method or you want to scrollTo some division points scrollTo() method, use it as per the requirement.
This is the best way to call scroll Event in Ionic/Angular

Accessibility Ionic 4 routing focus is at the bottom of the page

i have this really annoying problem in my Ionic 4 application that when I change page the screen reader focus is at the bottom of the page which means that my users will have to reverse through the content to get to my main content section.
i did some research and this seems to be a problem with Angular Angular accessibility documentation
Here they suggest that you should set focus on the main content.
However when I attempt this using:
ionViewDidEnter() {
const mainHeader = document.querySelector('#mainContent');
if (mainHeader) {
(mainHeader as HTMLElement)?.focus();
}
}
it doesn't really do anything.
Has anyone had a similar issue and know how I might fix it?
Edit
I have also tried with the viewChild:
#ViewChild('mainPage') mainContent: ElementRef;
ngOnInit() {
this.router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {
this.mainContent.nativeElement.focus();
});
}
And setting the mainPage element's tabIndex=0:
<div #mainPage tabindex="0"><ion-router-outlet main></ion-router-outlet></div>
Yet still no focus.

backbone marionette incorrect rendering of element

I'm working on implementing a QR reader in a web based app that uses the PC's webcam. This is currently working correct.
The framework that I use (barcode.js) has a function render(element).
I have 2 different files, ScannerView.html and ScannerView.js. See their code below:
ScannerView.html
<!-- Content Header (Page header) -->
<section class="content-header has-background-image">
<div class="background">
<img src="/assets/temp/header.png" />
</div>
<h1><div class="icon"><i class="fa fa-wrench"></i></div> <%=name%></h1>
</section>
<section class="content">
// Withing the following div, the canvas element should be placed
<div id="scanner"></div>
</section>
ScannerView.js
var YookrApp = require("../../setup");
var scanner = null;
var ScannerView = Backbone.Marionette.CompositeView.extend({
template: require("./ScannerView.html"),
className: "scannerView",
ui: {
scannerDiv: "#scanner"
},
name: "Yookr Code Scanner",
initialize: function(options) {
},
onRender: function() {
w69b.qr.decoding.setWorkerUrl("assets/w69b.qrcode.decodeworker.js");
scanner = new w69b.qr.ui.ContinuousScanner();
// Called when a qr code has been decoded.
scanner.setDecodedCallback(function(result) {
console.log("Decoded qr code:", result);
});
scanner.setStopped(false);
// Render component in element with id "scanner".
console.log("Start rendering");
scanner.render(this.ui.scannerDiv);
console.log("Rendering done");
},
close: function() {
// We have to dispose the scanner object.
// If we don"t do this, the webcam will
// always be enabled
scanner.dispose();
}
});
module.exports = ScannerView;
When I run my app, the scanner.render() function should add a <canvas> element inside <div id="scanner"></div> in ScannerView.html
Problem
I'm not able to render the canvas using scanner.render() properly withing the <div id="scanner"></div> that is located in my html file. I tried to use document.getElementById and this.ui.scannerDiv with different, but not correct result.
Because I defined an UI element in the ScannerView.js file, I should be able to call scanner.render(this.ui.scannerDiv); This should use the div with id scanner in my html view, but instead the canvas is not rendered at all. In my console, I can see the following warnings:
[.Offscreen-For-WebGL-0000020AB57365B0]GL ERROR :GL_INVALID_FRAMEBUFFER_OPERATION : glDrawArrays: framebuffer incomplete
and
[.Offscreen-For-WebGL-0000020AB57365B0]RENDER WARNING: texture bound to texture unit 2 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.
When I use scanner.render(document.getElementById("scanner"));, I can see that the canvas is rendered, but not in the correct location. Please see my added screenshot for the result:
At this point I'm stuck. I dont know how I can achieve that the canvas is rendered in the correct div.
After searching Google for a while longer, I found a solution.
The onRender: function() { } "gets triggered when the View's DOM subtree is prepared for insertion into the DOM but before those elements are viewable", according to this webiste.
after changing onRender to onShow in my javascript file, the canvas element is rendered in the correct location.

Using pace.js on loading appended images

I wanted to use pace.js to show a progress bar while the appended images are being loaded, they provided an API but I have no idea how it works.
$('#loadImg').click(function() {
Pace.start();
var $con = $('#content');
$con.append('<img src="http://lorempixel.com/500/500/">').imagesLoaded(function() {
console.log('done!');
Pace.stop();
});
});
I used it with desandro/imagesloaded to call Pace.stop() but I don't see any progress bars.
I made a demo plunk for your convenience.
You first need to disable pace on page load using:
"startOnPageLoad" : false
Also quoting from pace documentation:
Elements being rendered to the screen is one way for us to decide that the page has been rendered.
So we can say that loading of 'image' should successfully complete the pace progress:
"elements": {
"selectors": ["#image"] // assign id="image" to img
}
Load the pace with these options provided in script tag:
data-pace-options='{ "elements": { "selectors": ["#image"] }, "startOnPageLoad": false }'
Now just call Pace.restart() every time click on link 'Load Image'.
No need to call Pace.stop(). (it automatically detects that #image is done loading)
Updated plunk

Categories