My scroll handler JavaScript doesn't work in Internet Explorer - javascript

I have a script on my site that works in every browser, except Internet Explorer. Can someone explain why this doesn't work?
var header = document.getElementById('header');
var picturebg = document.getElementsByClassName('picturebg')[0];
var arrow = document.getElementsByClassName('toTop-transparent')[0];
var supportPageOffset = window.pageXOffset !== undefined;
window.onscroll = function() {
"use strict";
var y = window.scrollY;
if (y > 7) {
header.className = 'header-colored';
arrow.className = 'toTop';
picturebg.className = 'picturebgns';
} else {
header.className = 'header-transparent';
arrow.className = 'toTop-transparent';
picturebg.className = 'picturebg';
}
};
The console doesn't give any errors, it just doesn't work. I have another jQuery script that runs just fine.
I've seen the other question here about the same thing, but it didn't help in any way.

Certain properties used in your snippet are not supported by IE.
From the MDN page on scrollY:
For cross-browser compatibility, use window.pageYOffset instead of window.scrollY. Additionally, older versions of Internet Explorer (< 9) do not support either property and must be worked around by checking other non-standard properties.1
It appears you already have found the check for pageOffset support, so also check if non-standard properties are supported (e.g. CSS1 is compatible):
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
Try this sample, using addEventListener() instead of onscroll.
var header = document.getElementById('header');
var picturebg = document.getElementsByClassName('picturebg')[0];
var arrow = document.getElementsByClassName('toTop-transparent')[0];
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
header.addEventListener('scroll', function(event) {
"use strict";
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
console.log('y: ',y);
if (y > 7) {
header.className = 'header-colored';
arrow.className = 'toTop';
picturebg.className = 'picturebgns';
} else {
header.className = 'header-transparent';
arrow.className = 'toTop-transparent';
picturebg.className = 'picturebg';
}
});
<div id="header" style="height: 50px; overflow: scroll;">
<img class="picturebg" src="https://www.gravatar.com/avatar/684fa9ff80577cbde88ffbdebafac5b4?s=32&d=identicon&r=PG&f=1" />
<div id="arrow" class="toTop-transparent">↓</div>
</div>
1https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes

Related

Ruby on Rails 6 custom JavaScript file Uncaught ReferenceError: Rellax is not defined

Descriptions of issue
It supposes to add Parallax effect on .rellax elements according to https://github.com/dixonandmoe/rellax
If you are familiar with Ruby on Rails 6 and Webpacker, would you please explain why rails can't read rellax.js properly and what can I do to make it work? Thank you!
Terminal
$ rails s
=> Booting Puma
=> Rails 6.0.3.2 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.5 (ruby 2.6.6-p146), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop
Started GET "/" for ::1 at 2020-07-15 18:34:48 -0700
(1.0ms) SELECT sqlite_version(*)
Processing by WelcomeController#index as HTML
Rendering welcome/index.html.erb within layouts/application
[Webpacker] Everything's up-to-date. Nothing to do
Rendered welcome/index.html.erb within layouts/application (Duration: 4.8ms | Allocations: 2428)
[Webpacker] Everything's up-to-date. Nothing to do
Completed 200 OK in 47ms (Views: 39.7ms | ActiveRecord: 0.0ms | Allocations: 13263)
index.html.erb
<h1>Welcome#index</h1>
<p>Find me in app/views/welcome/index.html.erb</p>
<h4>data-rellax-speed = default</h4>
<section>
<div class="col">
<br>With Percentage (0.5) <br><br>
<div id="21" class="container"><div class="block">#1<span class="rellax" data-rellax-percentage="0.5">#1</span></div></div>
<div id="22" class="container"><div class="block">#2<span class="rellax" data-rellax-percentage="0.5">#2</span></div></div>
<div id="23" class="container"><div class="block">#3<span class="rellax" data-rellax-percentage="0.5">#3</span></div></div>
<div id="24" class="container"><div class="block">#4<span class="rellax" data-rellax-percentage="0.5" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#4</span></div></div>
<div id="25" class="container"><div class="block">#5<span class="rellax" data-rellax-percentage="0.5" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#5</span></div></div>
<div id="26" class="container"><div class="block">#6<span class="rellax" data-rellax-percentage="0.5" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#6</span></div></div>
</div>
<div class="col">
<br>Without Percentage <br><br>
<div id="21" class="container"><div class="block">#1<span class="rellax" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#1</span></div></div>
<div id="22" class="container"><div class="block">#2<span class="rellax" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#2</span></div></div>
<div id="23" class="container"><div class="block">#3<span class="rellax" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#3</span></div></div>
<div id="24" class="container"><div class="block">#4<span class="rellax">#4</span></div></div>
<div id="25" class="container"><div class="block">#5<span class="rellax">#5</span></div></div>
<div id="26" class="container"><div class="block">#6<span class="rellax">#6</span></div></div>
</div>
</section>
<!-- Scripts -->
<%= javascript_pack_tag 'rellax' %>
<script>
var rellax = new Rellax('.rellax');
</script>
app/javascript/packs/rellax.js
// ------------------------------------------
// Rellax.js
// Buttery smooth parallax library
// Copyright (c) 2016 Moe Amaya (#moeamaya)
// MIT license
//
// Thanks to Paraxify.js and Jaime Cabllero
// for parallax concepts
// ------------------------------------------
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.Rellax = factory();
}
}(typeof window !== "undefined" ? window : global, function () {
var Rellax = function(el, options){
"use strict";
var self = Object.create(Rellax.prototype);
var posY = 0;
var screenY = 0;
var posX = 0;
var screenX = 0;
var blocks = [];
var pause = true;
// check what requestAnimationFrame to use, and if
// it's not supported, use the onscroll event
var loop = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){ return setTimeout(callback, 1000 / 60); };
// store the id for later use
var loopId = null;
// Test via a getter in the options object to see if the passive property is accessed
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
}
});
window.addEventListener("testPassive", null, opts);
window.removeEventListener("testPassive", null, opts);
} catch (e) {}
// check what cancelAnimation method to use
var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
// check which transform property to use
var transformProp = window.transformProp || (function(){
var testEl = document.createElement('div');
if (testEl.style.transform === null) {
var vendors = ['Webkit', 'Moz', 'ms'];
for (var vendor in vendors) {
if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
return vendors[vendor] + 'Transform';
}
}
}
return 'transform';
})();
// Default Settings
self.options = {
speed: -2,
verticalSpeed: null,
horizontalSpeed: null,
breakpoints: [576, 768, 1201],
center: false,
wrapper: null,
relativeToWrapper: false,
round: true,
vertical: true,
horizontal: false,
verticalScrollAxis: "y",
horizontalScrollAxis: "x",
callback: function() {},
};
// User defined options (might have more in the future)
if (options){
Object.keys(options).forEach(function(key){
self.options[key] = options[key];
});
}
function validateCustomBreakpoints () {
if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
var isAscending = true;
var isNumerical = true;
var lastVal;
self.options.breakpoints.forEach(function (i) {
if (typeof i !== 'number') isNumerical = false;
if (lastVal !== null) {
if (i < lastVal) isAscending = false;
}
lastVal = i;
});
if (isAscending && isNumerical) return;
}
// revert defaults if set incorrectly
self.options.breakpoints = [576, 768, 1201];
console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
}
if (options && options.breakpoints) {
validateCustomBreakpoints();
}
// By default, rellax class
if (!el) {
el = '.rellax';
}
// check if el is a className or a node
var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
// Now query selector
if (elements.length > 0) {
self.elems = elements;
}
// The elements don't exist
else {
console.warn("Rellax: The elements you're trying to select don't exist.");
return;
}
// Has a wrapper and it exists
if (self.options.wrapper) {
if (!self.options.wrapper.nodeType) {
var wrapper = document.querySelector(self.options.wrapper);
if (wrapper) {
self.options.wrapper = wrapper;
} else {
console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
return;
}
}
}
// set a placeholder for the current breakpoint
var currentBreakpoint;
// helper to determine current breakpoint
var getCurrentBreakpoint = function (w) {
var bp = self.options.breakpoints;
if (w < bp[0]) return 'xs';
if (w >= bp[0] && w < bp[1]) return 'sm';
if (w >= bp[1] && w < bp[2]) return 'md';
return 'lg';
};
// Get and cache initial position of all elements
var cacheBlocks = function() {
for (var i = 0; i < self.elems.length; i++){
var block = createBlock(self.elems[i]);
blocks.push(block);
}
};
// Let's kick this script off
// Build array for cached element values
var init = function() {
for (var i = 0; i < blocks.length; i++){
self.elems[i].style.cssText = blocks[i].style;
}
blocks = [];
screenY = window.innerHeight;
screenX = window.innerWidth;
currentBreakpoint = getCurrentBreakpoint(screenX);
setPosition();
cacheBlocks();
animate();
// If paused, unpause and set listener for window resizing events
if (pause) {
window.addEventListener('resize', init);
pause = false;
// Start the loop
update();
}
};
// We want to cache the parallax blocks'
// values: base, top, height, speed
// el: is dom object, return: el cache values
var createBlock = function(el) {
var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
var dataSpeed = el.getAttribute( 'data-rellax-speed' );
var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
var dataMin = el.getAttribute( 'data-rellax-min' );
var dataMax = el.getAttribute( 'data-rellax-max' );
var dataMinX = el.getAttribute('data-rellax-min-x');
var dataMaxX = el.getAttribute('data-rellax-max-x');
var dataMinY = el.getAttribute('data-rellax-min-y');
var dataMaxY = el.getAttribute('data-rellax-max-y');
var mapBreakpoints;
var breakpoints = true;
if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
breakpoints = false;
} else {
mapBreakpoints = {
'xs': dataXsSpeed,
'sm': dataMobileSpeed,
'md': dataTabletSpeed,
'lg': dataDesktopSpeed
};
}
// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
// ensures elements are positioned based on HTML layout.
//
// If the element has the percentage attribute, the posY and posX needs to be
// the current scroll position's value, so that the elements are still positioned based on HTML layout
var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
if (self.options.relativeToWrapper) {
var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
}
var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
var posX = self.options.horizontal ? ( dataPercentage || self.options.center ? self.options.wrapper ? self.options.wrapper.scrollLeft : (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft) : 0 ) : 0;
var blockTop = posY + el.getBoundingClientRect().top;
var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
var blockLeft = posX + el.getBoundingClientRect().left;
var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
// apparently parallax equation everyone uses
var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
// Optional individual block speed as data attr, otherwise global speed
var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
// Optional individual block movement axis direction as data attr, otherwise gobal movement direction
var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
// ~~Store non-translate3d transforms~~
// Store inline styles and extract transforms
var style = el.style.cssText;
var transform = '';
// Check if there's an inline styled transform
var searchResult = /transform\s*:/i.exec(style);
if (searchResult) {
// Get the index of the transform
var index = searchResult.index;
// Trim the style to the transform point and get the following semi-colon index
var trimmedStyle = style.slice(index);
var delimiter = trimmedStyle.indexOf(';');
// Remove "transform" string and save the attribute
if (delimiter) {
transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
} else {
transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
}
}
return {
baseX: bases.x,
baseY: bases.y,
top: blockTop,
left: blockLeft,
height: blockHeight,
width: blockWidth,
speed: speed,
verticalSpeed: verticalSpeed,
horizontalSpeed: horizontalSpeed,
verticalScrollAxis: verticalScrollAxis,
horizontalScrollAxis: horizontalScrollAxis,
style: style,
transform: transform,
zindex: dataZindex,
min: dataMin,
max: dataMax,
minX: dataMinX,
maxX: dataMaxX,
minY: dataMinY,
maxY: dataMaxY
};
};
// set scroll position (posY, posX)
// side effect method is not ideal, but okay for now
// returns true if the scroll changed, false if nothing happened
var setPosition = function() {
var oldY = posY;
var oldX = posX;
posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
// If option relativeToWrapper is true, use relative wrapper value instead.
if (self.options.relativeToWrapper) {
var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
posY = scrollPosY - self.options.wrapper.offsetTop;
}
if (oldY != posY && self.options.vertical) {
// scroll changed, return true
return true;
}
if (oldX != posX && self.options.horizontal) {
// scroll changed, return true
return true;
}
// scroll did not change
return false;
};
// Ahh a pure function, gets new transform value
// based on scrollPosition and speed
// Allow for decimal pixel values
var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
var result = {};
var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
return result;
};
// Remove event listeners and loop again
var deferredUpdate = function() {
window.removeEventListener('resize', deferredUpdate);
window.removeEventListener('orientationchange', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
// loop again
loopId = loop(update);
};
// Loop
var update = function() {
if (setPosition() && pause === false) {
animate();
// loop again
loopId = loop(update);
} else {
loopId = null;
// Don't animate until we get a position updating event
window.addEventListener('resize', deferredUpdate);
window.addEventListener('orientationchange', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
}
};
// Transform3d on parallax element
var animate = function() {
var positions;
for (var i = 0; i < self.elems.length; i++){
// Determine relevant movement directions
var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
// Subtracting initialize value, so element stays in same spot as HTML
positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
var positionY = positions.y - blocks[i].baseY;
var positionX = positions.x - blocks[i].baseX;
// The next two "if" blocks go like this:
// Check if a limit is defined (first "min", then "max");
// Check if we need to change the Y or the X
// (Currently working only if just one of the axes is enabled)
// Then, check if the new position is inside the allowed limit
// If so, use new position. If not, set position to limit.
// Check if a min limit is defined
if (blocks[i].min !== null) {
if (self.options.vertical && !self.options.horizontal) {
positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
}
if (self.options.horizontal && !self.options.vertical) {
positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
}
}
// Check if directional min limits are defined
if (blocks[i].minY != null) {
positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
}
if (blocks[i].minX != null) {
positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
}
// Check if a max limit is defined
if (blocks[i].max !== null) {
if (self.options.vertical && !self.options.horizontal) {
positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
}
if (self.options.horizontal && !self.options.vertical) {
positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
}
}
// Check if directional max limits are defined
if (blocks[i].maxY != null) {
positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
}
if (blocks[i].maxX != null) {
positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
}
var zindex = blocks[i].zindex;
// Move that element
// (Set the new translation and append initial inline transforms.)
var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
self.elems[i].style[transformProp] = translate;
}
self.options.callback(positions);
};
self.destroy = function() {
for (var i = 0; i < self.elems.length; i++){
self.elems[i].style.cssText = blocks[i].style;
}
// Remove resize event listener if not pause, and pause
if (!pause) {
window.removeEventListener('resize', init);
pause = true;
}
// Clear the animation loop to prevent possible memory leak
clearLoop(loopId);
loopId = null;
};
// Init
init();
// Allow to recalculate the initial values whenever we want
self.refresh = init;
return self;
};
return Rellax;
}));
Error: Uncaught ReferenceError: Rellax is not defined
I just realized that the package you are trying to import is intended to be included as an AMD or as a node module, without entering in much detail what does that mean is that you should include your module either by using
import Rellax from 'rellax' or let Rellax = require('rellax'), the thing is that by using this kind of import, your packages are not included in the Window objcet, which is the main object where all the global modules and variables are attached, so if you try to access Rellax from outside of the scope where rellax is imported, you are not going to be able to access that object, getting the error message you mentioned:
Rellax is not defined
Because is actually not defined in that scope.
TLDR;
So in order to fix the issue, you have to include the library and use that library in the same scope, you can achieve that by creating a new js file within your pack directory for example:
parallax_init.js
import Rellax from 'rellax'
let rellax = new Rellax('.rellax');
And then include it in your html template using <%= javascript_pack_tag 'parallax_init' %>
Note:
As you are now using webpacker to handle the js dependencies, you have to use yarn to install the packages as webpacker works with yarn.
You can get more information about the JS scope stuff in the AMD documentation: https://requirejs.org/docs/whyamd.html and in the webpack documentation: https://webpack.js.org/concepts/module-federation/
I also recommend you to read the webpacker documentation, which has a bit more information than the rails guide for the moment(Until the rails guide gets updates): https://github.com/rails/webpacker#usage
You can have two approachs to achieve your goal. Install the library or add manually the js files.
If you want to install the library, use yarn (not npm) for that. yarn add rellax. Then just import it in application.js by doing: import 'rellax'; This file is located in app/javascript/packs.
If you want to add the files manually, put these js files in a folder called components or plugins inside app/javascript. Then import all js files in application.js. Having done this correctly, all js files will be available in your views.
It's highly recommended that you read the Rails Guide: The Asset Pipeline to understand how to deal with any kind of assets in rails applications.

Why wont this script work in Firefox?

I'm having this script, and it works fine in every browser except firefox.
var header = document.getElementById('header');
var arrow = document.getElementsByClassName('toTop-transparent')[0];
window.onscroll = function () {
"use strict";
if (document.body.scrollTop > 7) {
header.className = 'header-colored';
arrow.className = 'toTop';
} else {
header.className = 'header-transparent';
arrow.className = 'toTop-transparent';
}
};
The script doesn't seem to load at all. It's supposed to change the color of my header on scroll, and bring forth a 'back to top' button, but in firefox it does nothing. Any ideas on why this doesn't work?
I've tried updating browser to latest version, start in safe-mode without any add-ons.
Edit: I no longer have any errors in console on my site. The script still won't load, it seems like there is something in the script that firefox doesn't understand?
This code works in IE, Chrome and FF:
var header = document.getElementById('header');
var arrow = document.getElementsByClassName('toTop-transparent')[0];
var supportPageOffset = window.pageXOffset !== undefined;
window.onscroll = function() {
"use strict";
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
if (y > 7) {
console.log('here 1')
header.className = 'header-colored';
arrow.className = 'toTop';
} else {
console.log('here 2')
header.className = 'header-transparent';
arrow.className = 'toTop-transparent';
}
};
Fiddle: https://jsfiddle.net/zevane/zf8d4u36/
Documentation: https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY

jquery code does not work fine with differents urls

I have this jquery code:
$(function(){
var $win = $(window);
var $nav = $('.subnav');
var navTop = $('.subnav').length && $('.subnav').offset().top - 38;
var isFixed = 0;
processScroll();
$win.on('scroll', processScroll);
function processScroll() {
console.log('test');
var i, scrollTop = $win.scrollTop();
if (scrollTop >= navTop && !isFixed) {
isFixed = 1;
$nav.addClass('subnav-fixed');
} else if (scrollTop <= navTop && isFixed) {
isFixed = 0;
$nav.removeClass('subnav-fixed');
}
};
})
If I have this url for example:
http://mydomain.com/posts or http://mydomain.com or http://mydomain.com/post?utf8=✓&search=
the code does works fine, but if I have for example:
http://mydomain.com/post?utf8=✓&search=port or http://mydomain.com/post?utf8=✓&search=word
The code does not works fine...
Why if I pass a param for url with my search engine the code does not works fine?
Thank you very much!
Edited
I am using this sunspot solr for my as search engine
http://sunspot.github.com/
I found the fix in this question:
Replicating Bootstraps main nav and subnav
This is the code:
$(document).scroll(function(){
// If has not activated (has no attribute "data-top"
if (!$('.subnav').attr('data-top')) {
// If already fixed, then do nothing
if ($('.subnav').hasClass('subnav-fixed')) return;
// Remember top position
var offset = $('.subnav').offset()
$('.subnav').attr('data-top', offset.top);
}
if ($('.subnav').attr('data-top') - $('.subnav').outerHeight() <= $(this).scrollTop())
$('.subnav').addClass('subnav-fixed');
else
$('.subnav').removeClass('subnav-fixed');
});
Thank you

JavaScript script doesn't work in Firefox

I have an old function which is missing lines for Mozilla/Firefox and thus JavaScript is not working properly in it. The function tracks mouse-coordinates, so that I can position windows.
How to make the code work in Firefox as well?
Xoffset = -60; // modify these values to ...
Yoffset = 20; // change the popup position.
var old, skn, iex = (document.all),
yyy = -1000;
var ns4 = document.layers
var ns6 = document.getElementById && !document.all
var ie4 = document.all
if (ns4) skn = document.dek
else if (ns6) skn = document.getElementById("dek").style
else if (ie4) skn = document.all.dek.style
if (ns4) document.captureEvents(Event.MOUSEMOVE);
else {
skn.visibility = "visible"
skn.display = "none"
}
document.onmousemove = get_mouse;
function popup(msg, bak) {
var content =
"<TABLE WIDTH=150 BORDER=1 BORDERCOLOR=black CELLPADDING=2" +
"CELLSPACING=0 " + "BGCOLOR=" + bak + "><TD ALIGN=center>" +
"<FONT COLOR=black SIZE=2>" + msg + "</FONT></TD></TABLE>";
yyy = Yoffset;
if (ns4) {
skn.document.write(content);
skn.document.close();
skn.visibility = "visible"
}
if (ns6) {
document.getElementById("dek").innerHTML = content;
skn.display = ''
}
if (ie4) {
document.all("dek").innerHTML = content;
skn.display = ''
}
}
function get_mouse(e) {
var x = (ns4 || ns6) ? event.pageX : event.x + document.body.scrollLeft;
skn.left = x + Xoffset;
var y = (ns4 || ns6) ? event.pageY : event.y + document.body.scrollTop;
if (document.documentElement && // IE6 +4.01 but no scrolling going on
!document.documentElement.scrollTop) {
y = event.y + document.documentElement.scrollTop;
}
else if (document.documentElement && // IE6 +4.01 and user has scrolled
document.documentElement.scrollTop) {
y = event.y + document.documentElement.scrollTop;
}
else if (document.body && document.body.scrollTop) { // IE5 or DTD 3.2
y = event.y + document.document.body.scrollTop;
}
skn.top = y + yyy;
}
function kill() {
yyy = -1000;
if (ns4) {
skn.visibility = "hidden";
}
else if (ns6 || ie4) skn.display = "none"
}
I am getting this error:
"event is not defined"
Works ok in IE.
I'm not going to post code on how to rewrite your code #Ivo Wetzel's is pretty much what you need, but let meg give you some advice.
The world is changing fast, so does the computer industry. And while sometimes it's not as fast as we want (IE 6 fading slowly) there is no need to support Netscape 4.
Consult with a site like StatCounter to find out what browsers are in use (in your country/region). Also consult with YUI graded browser support. Yahoo is one of the biggest players on the internet, their site has to work for almost everyone, so they know what they're talking about.
Find a good DOM reference. MDC is pretty much what you need, but it's good to have MSDN for IE quirks. Talking about quirks, don't forget to bookmark QuirksMode compatibility tables.
Never use things like ie4 = document.all, because a single feature won't identify a whole browser. It's like saying: "Hey you've got blonde hair, you must be Brad Pitt". Use feature detection. Read these two excellent articles: Browser Detection (and What to Do Instead) and Feature Detection: State of the Art Browser Scripting
Don't use document.write because it's synchronous I/O which is awful. It blocks your page rendering and leads to bad user experience. The Web is all about being asynchronous.
"Synchronous programming is disrespectful and should not be employed in applications which are used by people." - Douglas Crockford
Oh my god... this must be the worst code I've seen in years, well let's try to clean it up then:
Xoffset = -60; // modify these values to ...
Yoffset = 20; // change the popup position.
var old, skn = document.getElementById("dek").style, yyy = -1000;
function popup(msg, bak) {
var content =
"<TABLE WIDTH=150 BORDER=1 BORDERCOLOR=black CELLPADDING=2" +
"CELLSPACING=0 " + "BGCOLOR=" + bak + "><TD ALIGN=center>" +
"<FONT COLOR=black SIZE=2>" + msg + "</FONT></TD></TABLE>";
yyy = Yoffset;
document.getElementById("dek").innerHTML = content;
skn.display = '';
}
document.onmousemove = function(e) {
e = e || window.event;
var x = e.pageX !== undefined ? e.pageX : e.clientX + document.body.scrollLeft;
var y = e.pageY !== undefined ? e.pageY : e.clientY + document.body.scrollTop;
skn.left = x + Xoffset;
skn.top = y + yyy;
}
function kill() {
yyy = -1000;
skn.display = "none";
}
It's still broken beyond repair, but it should work... somehow.... Well, unless you post the rest of them HTML there's no way I can test this.
Please, I beg you... get rid of all that crap and use jQuery.
Instead of testing for browsers, I would test to see if the object / property exists. For example:
var x = e.pageX ? e.pageX : e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
I think there may be an easier way to do this, such as
var x = e.pageX || e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
but I'm not sure that will work. Test it out and see what you get. Also, for more detail, review: quirksmode.org/js/events_properties.html
Also note that I changed "event" to "e", since the parameter you're passing into the function is "e". If you want to still use event, rewrite the parameter to:
function get_mouse(event)
While I don't believe "event" is a reserved word for JS, a lot of browsers use it, so I would suggest sticking to "e".
Looks like you need to change all your instances of 'event' to 'e'.
Firefox includes document.documentElement and document.documentElement.scrollTop and document.body and document.body.scrollTop so you're entering regions that were meant for IE with Firefox.
You should also start your function with something like
function get_mouse(e) {
e = e || window.event;
Then use e instead of event in all the places you use event.
Add var event = e on the first line of function body, if you are afraid of hassles
function get_mouse(e) { var event = e;

JQuery menu float and display submenus on page

This is my first time using JQuery in any of my projects.
I have implemented the superfish menu.
On some of my pages I have a horizontal scroll. I would like to make the menu float on the center of the page as the page is scrolled.
Also I need to make sure that the submenu on the far right hand side of the menu does not open up off the page. When I hover on the right most element it opens up half off the page.
Any ideas on how to fix these two things?
I'm perfectly willing to use a different Jquery menu if there is a better one that has these features built in...
Thanks!
javascrupt call in my page:
$(document).ready(function () {
$("ul.sf-menu").supersubs({
minWidth: 12, // minimum width of sub-menus in em units
maxWidth: 27, // maximum width of sub-menus in em units
extraWidth: 1 // extra width can ensure lines don't sometimes turn over
// due to slight rounding differences and font-family
}).superfish({ animation: { opacity: 'show', height: 'show' }, autoArrows: false }); // call supersubs first, then superfish, so that subs are
// not display:none when measuring. Call before initialising
// containing tabs for same reason.
I can post any more code that is needed, but there is quite a lot of code in the superfish files so i'm not sure what I should post.
I found this script and it works well, however when I scroll right the horizonal menu starts to stack so the menu items are side by side rather then vertical. I want to modify this to keep the menu horizonal...
<script type="text/javascript"><!--
var floatingMenuId = 'floatdiv';
var floatingMenu =
{
targetX: -1000,
targetY: 10,
hasInner: typeof (window.innerWidth) == 'number',
hasElement: document.documentElement
&& document.documentElement.clientWidth,
menu:
document.getElementById
? document.getElementById(floatingMenuId)
: document.all
? document.all[floatingMenuId]
: document.layers[floatingMenuId]
};
floatingMenu.move = function () {
if (document.layers) {
floatingMenu.menu.left = floatingMenu.nextX;
floatingMenu.menu.top = floatingMenu.nextY;
}
else {
floatingMenu.menu.style.left = floatingMenu.nextX + 'px';
floatingMenu.menu.style.top = floatingMenu.nextY + 'px';
}
}
floatingMenu.computeShifts = function () {
var de = document.documentElement;
floatingMenu.shiftX =
floatingMenu.hasInner
? pageXOffset
: floatingMenu.hasElement
? de.scrollLeft
: document.body.scrollLeft;
if (floatingMenu.targetX < 0) {
if (floatingMenu.hasElement && floatingMenu.hasInner) {
// Handle Opera 8 problems
floatingMenu.shiftX +=
de.clientWidth > window.innerWidth
? window.innerWidth
: de.clientWidth
}
else {
floatingMenu.shiftX +=
floatingMenu.hasElement
? de.clientWidth
: floatingMenu.hasInner
? window.innerWidth
: document.body.clientWidth;
}
}
floatingMenu.shiftY =
floatingMenu.hasInner
? pageYOffset
: floatingMenu.hasElement
? de.scrollTop
: document.body.scrollTop;
if (floatingMenu.targetY < 0) {
if (floatingMenu.hasElement && floatingMenu.hasInner) {
// Handle Opera 8 problems
floatingMenu.shiftY +=
de.clientHeight > window.innerHeight
? window.innerHeight
: de.clientHeight
}
else {
floatingMenu.shiftY +=
floatingMenu.hasElement
? document.documentElement.clientHeight
: floatingMenu.hasInner
? window.innerHeight
: document.body.clientHeight;
}
}
}
floatingMenu.doFloat = function () {
var stepX, stepY;
floatingMenu.computeShifts();
stepX = (floatingMenu.shiftX +
floatingMenu.targetX - floatingMenu.nextX) * .07;
if (Math.abs(stepX) < .5) {
stepX = floatingMenu.shiftX +
floatingMenu.targetX - floatingMenu.nextX;
}
stepY = (floatingMenu.shiftY +
floatingMenu.targetY - floatingMenu.nextY) * .07;
if (Math.abs(stepY) < .5) {
stepY = floatingMenu.shiftY +
floatingMenu.targetY - floatingMenu.nextY;
}
if (Math.abs(stepX) > 0 ||
Math.abs(stepY) > 0) {
floatingMenu.nextX += stepX;
floatingMenu.nextY += stepY;
floatingMenu.move();
}
setTimeout('floatingMenu.doFloat()', 20);
};
// addEvent designed by Aaron Moore
floatingMenu.addEvent = function (element, listener, handler) {
if (typeof element[listener] != 'function' ||
typeof element[listener + '_num'] == 'undefined') {
element[listener + '_num'] = 0;
if (typeof element[listener] == 'function') {
element[listener + 0] = element[listener];
element[listener + '_num']++;
}
element[listener] = function (e) {
var r = true;
e = (e) ? e : window.event;
for (var i = element[listener + '_num'] - 1; i >= 0; i--) {
if (element[listener + i](e) == false)
r = false;
}
return r;
}
}
//if handler is not already stored, assign it
for (var i = 0; i < element[listener + '_num']; i++)
if (element[listener + i] == handler)
return;
element[listener + element[listener + '_num']] = handler;
element[listener + '_num']++;
};
floatingMenu.init = function () {
floatingMenu.initSecondary();
floatingMenu.doFloat();
};
// Some browsers init scrollbars only after
// full document load.
floatingMenu.initSecondary = function () {
floatingMenu.computeShifts();
floatingMenu.nextX = floatingMenu.shiftX +
floatingMenu.targetX;
floatingMenu.nextY = floatingMenu.shiftY +
floatingMenu.targetY;
floatingMenu.move();
}
if (document.layers)
floatingMenu.addEvent(window, 'onload', floatingMenu.init);
else {
floatingMenu.init();
floatingMenu.addEvent(window, 'onload',
floatingMenu.initSecondary);
}
</script>
I'm not sure on how you mean centering, but if you mean horizontally centered:
Could you separate the main page (that horizontally overflows) and the menu into separate div's? e.g.
<div id="menu"><center><ul class="sf-menu">...</ul></center></div>
<div id="mainpage" style="overflow:auto;">Contents goes here</div>
(the <center> tag might have to be <div style="width:X;margin:0 auto;"> depending on how superfish works)
On the menu going over the page, sorry I'll have to defer to someone more knowable to answer that.

Categories