# Mixin stuff with magento
Recently I was tasked to make magento product gallery "sticky", but it had to be sticky to some point, after it gets to product details it has to stop. Ease right 😃 shoud be, so I decided to not spend to much time for this and just use what's already there in magento. So I used magento widget "sticky" for this, but there was one problem, it doesn't have this functionality out of the box. So I decided to extend upon what's already there, and create mixin functionality.
Some steps I folowed: Since this was specifically for one custom theme, I created requirejs-config.js in theme root with following content.
var config = {
config: {
mixins: {
"mage/sticky": {
"js/sticky-mixin": true,
},
},
},
};
Then it's time to create mixin file under src/app/design/frontend/[Vendor name]/[Theme name]/web/js/sticky-mixin.js
And we will override just the method that we need to change _stick and since we are adding new setting for sticky we will add two new options as well
options: {
/**
* Extending sticky by adding additional option for scrolling STOP
*/
scrollToEl: '',
/**
* Turn on/off on mobile view
*/
activOnMobile: ''
}
activOnMobile is another option that we will add to turn on/off this new "functionality" on mobile view ...so finally our mixin file should look something like this
define(["jquery"], function ($) {
"use strict";
var stickyMixin = {
options: {
/**
* Extending sticky by adding additional option for scrolling STOP
*/
scrollToEl: "",
/**
* Turn on/off on mobile view
*/
activOnMobile: "",
},
/**
* float Block on windowScroll
* @private
*
* this.options.scrollToEl - is CONTROLLING if STOP functionality is active
*/
_stick: function () {
var offset, isStatic, stuck, stickAfter;
isStatic = this.element.css("position") === "static";
if (!isStatic && this.element.is(":visible")) {
offset =
$(document).scrollTop() -
this.parentOffset +
this._getOptionValue("spacingTop");
offset = Math.max(0, Math.min(offset, this.maxOffset));
stuck = this.element.hasClass(this.options.stickyClass);
stickAfter = this._getOptionValue("stickAfter");
if (offset && !stuck && offset < stickAfter) {
offset = 0;
}
if (this.options.activOnMobile && this._checkScreenSize() < 1024) {
return;
}
if (this.options.scrollToEl) {
var stopElement = $(this.options.scrollToEl).offset(),
stopCalculation =
stopElement.top -
(this.element.outerHeight() + 20) -
this.parentOffset;
if (offset < stopCalculation) {
console.log(offset);
this.element
.toggleClass(this.options.stickyClass, offset > 0)
.css("top", offset);
}
} else {
this.element
.toggleClass(this.options.stickyClass, offset > 0)
.css("top", offset);
}
}
},
_checkScreenSize: function () {
var width =
window.innerWidth ||
document.documentElement.clientWidth ||
document.body.clientWidth;
return width;
},
};
return function (targetWidget) {
$.widget("mage.sticky", targetWidget, stickyMixin);
return $.mage.sticky;
};
});
I have some explaining here to do: activOnMobile with help of method _checkScreenSize will be used to check if the screen size is mobile, and if it this function need to be turned off.
stopCalculation =
stopElement.top - (this.element.outerHeight() + 20) - this.parentOffset;
stopCalculation is place where correct offset of stopElement is calculated