Vue lazyloading gets triggered when adding dynamic class to <main> - vue.js

I am adding a 'sticky-header' class to my dynamically, but when its sticky i obviously also need to add padding to my so the content doesnt go behind the header.
The problem is that when adding the padding via class-binding(v-bind:class="{'fixed-header': stickyHeader}")on scroll, this reloads all the lazy-loaded images (that are lazy loaded using vue lazy)
This makes all images go from loading to loaded in a split second, but its very noticable.
stickyHeaderis a boolean that gets recalculated on scroll, if the window is scrolled past a certain element (with a eventlistener on scroll: checkHeader())
checkHeader() {
var elementTarget = document.getElementById("notice");
if(window.scrollY > (elementTarget.offsetTop + elementTarget.offsetHeight)){
this.stickyHeader = true;
}
else{
this.stickyHeader = false;
}
}
Anyone know what exactly triggers the images to go back to 'loading' for a split second?

To solve this instead of dynamically binding the class with v-bind i simply add it in the scroll listener method with basic javascript, now it doesnt rerender :) !

Related

zooming the page will reset the carousel

Is there a way to avoid reset the carousel after the user zoom in/out the browser page?
I found pages with similar carousel and this behaviour doesn't happens.
Go to spartacus demo website https://spartacus-demo.eastus.cloudapp.azure.com/electronics-spa/en/USD/, in the carousel navigate to the next block of slide, then zooming the page, you should see the carousel reset to the first block of slides.
This behaviour of the CarouselComponent is expected. Its service depends on window.resize event to adjust the number of items on carousel page whenever the window got resized.
If you consider it as a bug, please create an issue in the Spartacus GitHub repository. Team will take your proposal into consideration.
There is one way this can be handled.
In DOM, instead of using Spartacus's activeSlide variable for rendering the UI, use one tempVariable named say tempActiveSlide
Reassign the tempActiveSlide only if the items per slide are changing. This count will change whenever the window resizes and which is as per the functionality of CarouselService.
Ref - https://sap.github.io/spartacus/injectables/CarouselService.html#source
This way, the carousel on UI will only reset if the number of items per slide have changed. Otherwise it wont reset.
TS code:
tempActiveSlide;
itemsPerSlide = 0;
ngOnInit(): void {
super.ngOnInit();
this.tempActiveSlide = this.activeSlide;
this.size$.subscribe((items) => {
if (items !== this.itemsPerSlide) {
this.itemsPerSlide = items;
this.tempActiveSlide = this.activeSlide;
}
});
}

vuejs : how to preload image inside a component

I have images inside a component not displayed at launch.
When i show my component, my images are not displayed instantly, but are loaded.
I would like to preload my images on the root app, to be instantly displayed when the component is active.
How would you do that?
components are bind to dom only when they are created. images will be loaded only when dom sent request. you can try something
let image = new Image();
image.src = 'something.png'.
this will trigger a network request. you can use the image variable as props to component
You can also do it with css background images. Simply add this css to your global styles:
html {
background-image: url('url1.jpg'),
url('url2.jpg'),
url('url3.jpg'); // list all images here
background-size: 0;
}
This might be a little bit hacky, but all images get preloaded asynchronously. From here on you can optimize it by going more specific on where to apply the styles e.g. scoped in child components or wherever you want.
If you have a lot of images you could also write a simple webpack plugin which generates this code dynamically.

Scroll to an element given in the location hash, when said element is loaded asynchronously on page load

I am passing an element ID using the location hash like so:
https://example.com/object/id#sub-object
However, the list of sub-object elements is loaded dynamically from an api after page load.
How can I scroll the viewport to the given element once the async request completes? Given that it's location is not available in the DOM on page load.
I solved this myself, I used jquery for the scroll animation because, easy.
if(window.location.hash && !this.hasScrolled){
var hash = location.hash.substring(1);
$('html, body').animate({scrollTop: this.$refs[hash][0].offsetTop -200} ,800);
this.hasScrolled = true;
}
This had to happen in the updated() hook on the component as this is the point when the element's offset is known. I added a hasScrolled property (initially set to false) so I can make sure it only does the scroll on initial page load.

DojoX Mobile ListItem load HTML via AJAX and then remove from DOM

Let's say in a view I have a DojoX Mobile ListItem that is pulling an HTML view fragment into the DOM via AJAX and then transitioning to that view. Assume this is all working fine.
Now, I go back to the initial view that had that ListItem on it and click some other button that destroys that view node from the DOM. If I now click on that ListItem that previously loaded that view node into the DOM (which has now been removed), it will try to transition to a view that doesn't exist. It doesn't know that it has been removed.
Is there some type of way to tell a ListItem that it needs to fetch the HTML again because what was previously fetched no longer exists? I am not seeing anything about doing this in any documentation anywhere. I don't think a code sample is really necessary here, but I can provide a minimal one if necessary.
I went a different route and left the view exist in the DOM, and simply made a function that clears all sensitive data out of the view.
Okay, in this case, i guess you could hook the onShow function of your ListItem container(or any other onchange event). Create a listener for said handle to evaluate if your item needs reloading. Following is under the assumtion that it is the item.onclick contents showing - and not the label of your item which contains these informations
Or better yet, do all this during initialization so that your ListItem container will be an extended with custom onClick code.
Seems simple but may introduce some quirks, where/when/if you programatically change to this item, however here goes:
function checkItem() {
// figure out if DOM is present and if it should be
if( isLoggedIn() ) {
this.getChildren().forEach(function(listitem) {
if( dojo.query("#ID_TO_LOOK_FOR", listitem.domNode).length == 0 ) {
// this references the listItem, refresh contents.
// Note: this expects the listitem to be stateful, have no testing environment at time being but it should be
listitem.set("url", listitem.url);
}
});
}
}
Preferably, set this in your construct of the container for your ListItems
var listItemParent = new dojox.mobile.RoundRectList({
onShow : checkItem,
...
});
Or create listener
var listItemParent = dijit.byId('itemRegistryId');
// override onClick - calling inheritance chain once done
dojo.connect(listItemParent, "onClick", listItemParent, checkItem);

making iscroll to work when loading a div dynamically

can anyone please explain, with an example if possible, how to load dynamic content inside an iscroll div and assign a new height to it?
I can get it to work but I can't control the height of the scroll for the new content.
I'm new to all this and have no clue were to start.
here's what I'm working on:
http://homepage.mac.com/jjco/test/index7.html
when the page is loaded you see the scroll bar where there's no content...
clicking on print/damm (shows the height I originally set for this content)
clicking on print/fcbarcelona (maintains the same height and position of the scroll you used before) as you see it's not working as it should.
obviously, I don't want the scroll to be there when it's not necessary.
any help would be greatly appreciated.
It's better to use the refresh() method in iScroll, which will recalculate the height.
myScroll.refresh();
I had a similar problem, and just refresh() didn't help, so didn't help destroying and recreating iScroll. In my case I was loading a lot of elements into iScroll div. What did solve the problem is setTimeout(). As MASTERING THE REFRESH() METHOD said adding even 0ms to a setTimeout() would solve a lot of problems. In my case it was 500ms. =
here is code sample:
var myScroll;
function createIScroll(){
myScroll = new iScroll('wrapper');
}
function iScrollRefresh(){
setTimeout(function(){
myScroll.refresh();
}, 500);
}
$ajax(){
//receiving data
}
function someFunction(){
//dynamic content is created
iScrollRefresh();
}
My problem was that refresh() function was executed before content was inserted into DOM, so increasing timeout helped. I hope it helps to beginners like me.
try this, when you insert your new data into iScroll do these steps
//myScroll is a global variable you initialize iScroll on
myScroll.destroy();
myScroll = null;
loaded();//this is a functions where you have have your iScroll initializer
To watch height changes:
setInterval(function () {
var newScrollerHeight = $scroller.innerHeight();
if (newScrollerHeight !== prevScrollerHeight) {
prevScrollerHeight = newScrollerHeight;
myScroll.refresh();
}
}, 500);
Take a look at iScroll4
In iscroll.js, I see experimental option: checkDOMChanges: false,// Experimental You can enable and use it.