I have used javascript to creat a scollable table on page load
The visibility of the table is hidden by default.
When i minimize/maximize the page in IE, the browser makes the hidden table visible.
Can any one help me in solving this issue.
The javascript to create scrollable table is as follows
/* Scrollable table */
function setScrollableTableHeight(name,maxrows)
{
var count;
var arrObj = document.getElementsByName(name);
for(count=0;count<arrObj.length;count++)
{
ScrollableTable(arrObj[0], maxrows);
}
}
// set Body width to screen width
function setBodyWidth()
{
objBody = document.getElementsByTagName('body');
objBody[0].style.width = screen.width - 40;
var objDivs = document.getElementsByTagName('div');
for(var i=0;i<objDivs.length;i++)
{
if(objDivs[i].className == "OuterPanel")
{
if(screen.width < 980)
objDivs[0].style.width = 980 - 42;
else
objDivs[0].style.width = screen.width - 42;
break;
}
}
}
function ScrollableTable (tableEl, maxRows, tableWidth) {
var tableHeight = 25 + maxRows * 25;
var numRows = 0;
this.initIEengine = function () {
if (this.tableEl.parentElement.clientHeight - this.tableEl.offsetHeight < 0) {
this.tableEl.style.width = this.newWidth - this.scrollWidth +'px';
}
if (this.thead) {
var trs = this.thead.getElementsByTagName('tr');
for (x=0; x<trs.length; x++) {
trs[x].style.position ='relative';
trs[x].style.setExpression("top", "this.parentElement.parentElement.parentElement.scrollTop + 'px'");
}
}
if (this.tfoot) {
var trs = this.tfoot.getElementsByTagName('tr');
for (x=0; x<trs.length; x++) {
trs[x].style.position ='relative';
trs[x].style.setExpression("bottom", "(this.parentElement.parentElement.offsetHeight - this.parentElement.parentElement.parentElement.clientHeight - this.parentElement.parentElement.parentElement.scrollTop) + 'px'");
}
}
eval("window.attachEvent('onresize', function () { document.getElementById('" + this.tableEl.id + "').style.visibility = 'hidden'; document.getElementById('" + this.tableEl.id + "').style.visibility = 'visible'; } )");
};
this.initFFengine = function () {
var headHeight = (this.thead) ? this.thead.clientHeight : 0;
var footHeight = (this.tfoot) ? this.tfoot.clientHeight : 0;
var bodyHeight = this.tbody.clientHeight;
this.tbody.setAttribute("id", "dynamicScrollParentfirefox");
var trs = this.tbody.getElementsByTagName('tr');
numRows = trs.length;
var tds;
if (bodyHeight >= (this.newHeight - (headHeight + footHeight))) {
for (x=0; x<trs.length; x++) {
tds = trs[x].getElementsByTagName('td');
tds[tds.length-1].style.paddingRight += this.scrollWidth + 'px';
}
}
var cellSpacing = (this.tableEl.offsetHeight - (this.tbody.clientHeight + headHeight + footHeight)) / 4;
this.tbody.style.height = (this.newHeight - (headHeight + cellSpacing * 2) - (footHeight + cellSpacing * 2)) + 'px';
};
this.tableEl = tableEl;
this.scrollWidth = 16;
this.originalHeight = this.tableEl.clientHeight;
this.originalWidth = this.tableEl.clientWidth;
/* modified by rmv */
if(parseInt(tableHeight) > this.originalHeight && this.originalHeight!=0)
tableHeight = this.originalHeight;
/* modified by rmv ends*/
this.newHeight = parseInt(tableHeight);
this.newWidth = tableWidth ? parseInt(tableWidth) : this.originalWidth;
this.tableEl.removeAttribute('height');
var loverflowParent = document.createElement('div');
loverflowParent.setAttribute("id","dynamicScrollParent");
this.containerEl = this.tableEl.parentNode.insertBefore(loverflowParent, this.tableEl);
this.containerEl.appendChild(this.tableEl);
this.containerEl.style.height = this.newHeight + 'px';
this.containerEl.style.width = this.newWidth + 'px';
var thead = this.tableEl.getElementsByTagName('thead');
this.thead = (thead[0]) ? thead[0] : null;
var tfoot = this.tableEl.getElementsByTagName('tfoot');
this.tfoot = (tfoot[0]) ? tfoot[0] : null;
var tbody = this.tableEl.getElementsByTagName('tbody');
this.tbody = (tbody[0]) ? tbody[0] : null;
if (!this.tbody) return;
if (document.all && document.getElementById && !window.opera) this.initIEengine()
if (!document.all && document.getElementById && !window.opera) this.initFFengine()
}
You can also try to force the table to scroll when the page height changes. You can apply in CSS this attribute to the container of the table: overflow-y:scroll;
Related
I am trying to replicate a mosaic that can be found on many webpages. While looking for solutions to my problem I came accross a very good implementation on squarespace seen at https://native-demo.squarespace.com/images-native/. I have hosted my website containing the mosaic at http://alexstiles.000webhostapp.com.
My issue is that when you resize the window the horizontal spacing between the images flucuates like it has an animation instead of staying consistient. Although it sorts itself out if you resize slowly, rapid movements can cause the margin to be to large or small. This behavior is not present in the squarespace template. How can I remove this and make the margin consistient when resizing? I have already tried using css margins instead of javascript. I have added the javascript below to help.
let mosaic = document.getElementsByClassName("mosaic")[0]; // For a single mosaic for now
let numImages = 12;
let imageTopic = "design";
let originalImageTopic = "design";
let rowWidth = 3;
let scale = 1;
let mosaicLoader = document.getElementsByClassName("loader-container")[0]
let search = document.getElementById("search");
let searchBtn = document.getElementById("search-button");
let form = document.getElementsByTagName("form")[0];
function rem(rems) {
return rems * (16 * scale);
}
searchBtn.addEventListener("click", function(event) {
event.preventDefault();
searchResult(search.value);
});
search.addEventListener("click", function() {
form.classList.add("focused");
});
search.addEventListener("blur", function() {
form.classList.remove("focused");
});
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '13' || e.which == '13' || e.key === "Enter") {
e.preventDefault();
searchResult(search.value);
}
}
if (window.location.hash) {
let hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
search.value = hash;
searchResult(hash);
}
function searchResult(query) {
// Get and set query
query = ((query != "" && query != originalImageTopic) ? search.value : imageTopic);
imageTopic = query;
if (imageTopic != originalImageTopic) {
parent.location.hash = imageTopic;
document.getElementById("search-term").textContent = imageTopic + " pictures";
}
// Put up loader while fetching images
mosaicLoader.style.display = "flex";
// Remove old images
let length = mosaic.children.length;
while (mosaic.lastChild && length > 1) {
mosaic.removeChild(mosaic.lastChild);
length--;
}
// Create new images
let loadedImageNum = 0
for (let i = 0; i < numImages; i++) {
let image = document.createElement("img");
image.src = `https://source.unsplash.com/random?${imageTopic}/sig${i}/`;
mosaic.appendChild(image);
}
// Wait for all images to load
let loadedImages = 0;
let image = mosaic.querySelectorAll("img");
imageCheck = setInterval(function() {
for (let i = 0; i < numImages; i++) {
if (image[i].naturalHeight !== 0 && image[i].complete) {
loadedImages++;
}
if (loadedImages == numImages) {
clearInterval(imageCheck);
// alert("Loaded!")
// Lay them out
setTimeout(imagesLoaded, 2000); // Needs some time before laying out
// Break loop
break;
}
}
}, 200)
}
searchResult(imageTopic); // Inital images with no search query
window.onload = function() {
windowResizeEvents();
}
window.onresize = function() {
windowResizeEvents();
}
function windowResizeEvents() {
imagesLoaded();
}
function mosaicCalibration() {
let images = document.querySelectorAll(".mosaic img");
if (window.innerWidth < 750) {
mosaic.classList.add("column");
} else if (window.innerWidth < 1100) {
rowWidth = 2;
} else {
rowWidth = 3 // Math.round(window.innerWidth/(426 + (2/3)));
}
if (window.innerWidth > 750) {
mosaic.classList.remove("column");
for (let i = 0; i < images.length; i++) {
images[i].style.width = `calc((100% - ${((rowWidth - 1) * 1)}rem) / ${rowWidth})`;
}
}
}
function imagesLoaded() {
// Find out row width, image width, etc
mosaicCalibration();
// Remove loader and set height to 0 so new height can be calculated
mosaicLoader.style.display = "none";
mosaic.style.height = 0;
// Define variables
let images = document.querySelectorAll(".mosaic img");
let row = 0;
let rowNum = 0;
let margin = rem(1.25);
let imageWidth = ((mosaic.scrollWidth - (2 * margin)) / rowWidth);
let column = [];
for (let i = 0; i < images.length; i++) {
images[i].style.top = i > rowWidth - 1 ? column[i-rowWidth] + margin : 0;
if (row < rowWidth) {
if (window.innerWidth > 1100) {
images[i].style.left = row * imageWidth + (row >= 1 ? row * margin : 0);
} else {
images[i].style.left = row * imageWidth + (row >= 1 ? (row + 0.5) * margin : 0);
}
row++
} else {
images[i].style.left = 0;
row = 1;
rowNum++;
}
if (rowNum > 0) {
column.push(column[i-rowWidth] + images[i].scrollHeight + margin);
} else {
column.push(images[i].scrollHeight);
}
}
mosaic.style.height = mosaic.scrollHeight;
}
I am having a problem defining a class method:
this.method = function(){...}
I get an error thrown at the "." after "this".
If I declare the method directly using method(){...}, I am unable to reference it in other methods as it shows that the method is undefined.
The method I want to deifne is shuffleBoard(). How do I do it?
class Board {
constructor(size,boardId){
this.boardId = boardId;
switch(size){
case "medium":
var boardSize = 560;
var tiles = 7*7;
break;
case "large":
boardSize = 720;
tiles = 9*9;
break;
default:
boardSize = 320;
tiles = 4*4;
break;
}
var container = $(this.boardId+" .tiles-container");
var row = 0;
var loopArray = [];
for(var i = 0;i < tiles; i++){
var tile = document.createElement("div");
loopArray.push(i);
var text = i+1;
tile.setAttribute("index",i+1);
tile.id = i+1;
if(i == tiles - 1){
var empty = "empty"
}
tile.setAttribute("class","tile "+empty);
tile.innerText = text;
container.append(tile);
(function(){
tile.onclick = function(){
var tileObject = new Tile(this.getAttribute("index"));
console.log(tileObject.move());
}
})()
var prevRow = row;
if(i%4 == 0 && i != 0){
row++
}
if(row > prevRow){
var positionX = 0;
}
else{
var positionX = (i%4)*80;
}
var positionY = row*80;
tile.style.top=positionY+"px";
tile.style.left=positionX+"px";
console.log(i+"---"+row+"////"+prevRow);
}
setTimeout(function(){this.shuffleBoard(loopArray);},4000);
return container;
}
this.shuffleBoard = function(arr){
var i = 0;
console.log(this.boardId);
$(this.boardId+" .tiles-container tile").forEach(function(el){
var shuffled = shuffle(arr);
el.innerText = shuffled[i];
arr.pop(arr[i]);
i++
});
}
}
It seems like you are using ES6 syntax. In ES6 write functions like
shuffleBoard() {
// rest of the code
}
and to access it use this keyword. like this.shuffleBoard().
To call it in setTimeout, use arrow functions
setTimeout(() => { this.shuffleBoard(loopArray); }, 4000);
1.You have to use an arrow function to keep the scope, because otherwise this would be pointing to the new function created in the timeout.
setTimeout(() => {
this.shuffleBoard(loopArray);
}, 4000);
2.The constructor mustn't return anything because it prevents it from returning the object it constructs
3.jQuery uses .each() to iterate over jQuery objects instead of .forEach().
I put the notes directly in the code as comments as well:
class Board {
constructor(size, boardId) {
this.boardId = boardId;
switch (size) {
case "medium":
var boardSize = 560;
var tiles = 7 * 7;
break;
case "large":
boardSize = 720;
tiles = 9 * 9;
break;
default:
boardSize = 320;
tiles = 4 * 4;
break;
}
var container = $(this.boardId + " .tiles-container");
var row = 0;
var loopArray = [];
for (var i = 0; i < tiles; i++) {
var tile = document.createElement("div");
loopArray.push(i);
var text = i + 1;
tile.setAttribute("index", i + 1);
tile.id = i + 1;
if (i == tiles - 1) {
var empty = "empty"
}
tile.setAttribute("class", "tile " + empty);
tile.innerText = text;
container.append(tile);
(function() {
tile.onclick = function() {
var tileObject = new Tile(this.getAttribute("index"));
console.log(tileObject.move());
}
})()
var prevRow = row;
if (i % 4 == 0 && i != 0) {
row++
}
if (row > prevRow) {
var positionX = 0;
} else {
var positionX = (i % 4) * 80;
}
var positionY = row * 80;
tile.style.top = positionY + "px";
tile.style.left = positionX + "px";
console.log(i + "---" + row + "////" + prevRow);
}
setTimeout(() => { //use arrow function to keep the scope
this.shuffleBoard(loopArray);
}, 4000);
//return container; returning the container here prevents the constructor from returning the constructed object
}
shuffleBoard(arr) {
var i = 0;
console.log(this.boardId);
$(this.boardId + " .tiles-container tile").each(function(el) { //jQuery uses .each instead of forEach
var shuffled = shuffle(arr);
el.innerText = shuffled[i];
arr.pop(arr[i]);
i++
});
}
}
let board = new Board("medium", "myboard");
console.log(board.shuffleBoard);
board.shuffleBoard([]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
shuffleBoard = function(arr){
// rest of code
})
Then you can use method as:
let board = new Board()
board.shuffleBoard()
way1:move this.propertyName to constructor
class Board{
constructor(size,boardId){
this.boardId = boardId;
switch(size){
case "medium":
var boardSize = 560;
var tiles = 7*7;
break;
case "large":
boardSize = 720;
tiles = 9*9;
break;
default:
boardSize = 320;
tiles = 4*4;
break;
}
var container = $(this.boardId+" .tiles-container");
var row = 0;
var loopArray = [];
for(var i = 0;i < tiles; i++){
var tile = document.createElement("div");
loopArray.push(i);
var text = i+1;
tile.setAttribute("index",i+1);
tile.id = i+1;
if(i == tiles - 1){
var empty = "empty"
}
tile.setAttribute("class","tile "+empty);
tile.innerText = text;
container.append(tile);
(function(){
tile.onclick = function(){
var tileObject = new Tile(this.getAttribute("index"));
console.log(tileObject.move());
}
})()
var prevRow = row;
if(i%4 == 0 && i != 0){
row++
}
if(row > prevRow){
var positionX = 0;
}
else{
var positionX = (i%4)*80;
}
var positionY = row*80;
tile.style.top=positionY+"px";
tile.style.left=positionX+"px";
console.log(i+"---"+row+"////"+prevRow);
}
setTimeout(function(){this.shuffleBoard(loopArray);},4000);
this.shuffleBoard = function(arr) {
var i = 0;
console.log(this.boardId);
$(this.boardId + " .tiles-container tile").forEach(function(
el
) {
var shuffled = shuffle(arr);
el.innerText = shuffled[i];
arr.pop(arr[i]);
i++;
});
}
return container;
}
}
way2:change this.propertyName to a method in className.prototype
class Board {
constructor(size, boardId) {
this.boardId = boardId;
switch (size) {
case "medium":
var boardSize = 560;
var tiles = 7 * 7;
break;
case "large":
boardSize = 720;
tiles = 9 * 9;
break;
default:
boardSize = 320;
tiles = 4 * 4;
break;
}
var container = $(this.boardId + " .tiles-container");
var row = 0;
var loopArray = [];
for (var i = 0; i < tiles; i++) {
var tile = document.createElement("div");
loopArray.push(i);
var text = i + 1;
tile.setAttribute("index", i + 1);
tile.id = i + 1;
if (i == tiles - 1) {
var empty = "empty";
}
tile.setAttribute("class", "tile " + empty);
tile.innerText = text;
container.append(tile);
(function() {
tile.onclick = function() {
var tileObject = new Tile(this.getAttribute("index"));
console.log(tileObject.move());
};
})();
var prevRow = row;
if (i % 4 == 0 && i != 0) {
row++;
}
if (row > prevRow) {
var positionX = 0;
} else {
var positionX = (i % 4) * 80;
}
var positionY = row * 80;
tile.style.top = positionY + "px";
tile.style.left = positionX + "px";
console.log(i + "---" + row + "////" + prevRow);
}
setTimeout(function() {
this.shuffleBoard(loopArray);
}, 4000);
return container;
}
shuffleBoard(arr) {
var i = 0;
console.log(this.boardId);
$(this.boardId + " .tiles-container tile").forEach(function(el) {
var shuffled = shuffle(arr);
el.innerText = shuffled[i];
arr.pop(arr[i]);
i++;
});
}
}
I've function JS for superimpose 2 blocs (without absolute position in CSS). So i add height + margin-bottom identical.
My function work, but on resize, i don't understand why it does not work. The value don't change ..
Do you have any idea ?
var visual = document.getElementById('js-visual');
function equalizerVisualPageHeader() {
var maxHeight = -1,
elems = document.getElementsByClassName('equalizer');
for (var i = 0; i < elems.length; i++) {
maxHeight = maxHeight > elems[i].offsetHeight ? maxHeight : elems[i].offsetHeight;
}
for (var i = 0; i < elems.length; i++) {
elems[i].style.height = maxHeight + 'px';
}
var visualHeight = visual.offsetHeight;
visual.style.marginBottom = '-' + visualHeight + 'px';
}
if (visual != undefined) {
equalizerVisualPageHeader();
}
window.addEventListener('resize', function() {
equalizerVisualPageHeader();
});
Thank you !
You can use this .
window.onresize = function () {
var w = window,
d = document,
e = d.documentelement,
g = d.getelementsbytagname('body')[0],
x = w.innerwidth || e.clientwidth || g.clientwidth,
y = w.innerheight || e.clientheight || g.clientheight;
$("#style-1").height(y);
}
I am trying to render child elements of an element if the element is in view or removing the content if not in view like below on scroll event like below
list.addEventListener('scroll', function () {
var elements = document.querySelectorAll('.aBox');
var toBe = counter - 1 - elements.length;
for (var i = 0; i < elements.length; i++) {
var inView = visibleY(elements[i]),
ele = elements[i].querySelector('.item');
if (inView === false && ele) {
console.log("Not in visible, keeping it none");
var height = elements[i].clientHeight;
elements[i].style.height = height + "px";
elements[i].innerHTML = "";
} else if(!ele){
console.log('Placing the content');
var minArray = arr[toBe + 1 + i],
str = "";
for (var j = 0; j < minArray.length; j++) {
str += "<div class='item'>" + minArray[j] + "</div>";
}
elements[i].innerHTML = str;
}
}
});
It seems working but if I have a look at the DOM this is not working as expected. Someone please help me to find the problem, fiddle.
Update
function updateData(callback) {
var elements = document.querySelectorAll('.aBox');
elements = Array.prototype.slice.call(elements);
var toBe = counter - 1 - elements.length;
async.each(elements, function (element, cb) {
var inView = $(element).is_on_screen(),
ele = element.querySelector('.item');
if (inView == false && ele) {
console.log("Not in visible, keeping it none");
var height = element.clientHeight;
element.style.height = height + "px";
element.innerHTML = "";
} else if (!ele && inView) {
console.log('Placing the content');
var minArray = arr[toBe + 1 + i],
str = "";
if (typeof minArray === "object") {
for (var j = 0; j < minArray.length; j++) {
str += "<div class='item'>" + minArray[j] + "</div>";
}
element.innerHTML = str;
}
}
cb();
}, function () {
callback()
});
}
Fiddle
Hi I have solved this problem. Posting here, so that it will be more helpful for people who want to work on mobiles to display very large lists with virtual scrolling
var arr = new Array(10000);
for (var i = 0; i < arr.length; i++) {
arr[i] = "Hello Dudes..." + i;
}
Array.prototype.chunk = function (chunkSize) {
var array = this;
return [].concat.apply([],
array.map(function (elem, i) {
return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];
}));
}
arr = arr.chunk(50);
var list = document.getElementById('longList');
var button = document.getElementById('loadMore');
var counter = arr.length,
aBoxLen = 1;
function appendBox() {
var div = document.createElement('div'),
str = "";
div.className = "aBox";
var minArray = arr[counter - aBoxLen];
for (var i = 0; i < minArray.length; i++) {
str += "<div class='item'>" + minArray[i] + "</div>";
}
div.innerHTML = str;
div.setAttribute('index', counter - aBoxLen);
var box = document.querySelector('.aBox');
if (box) {
list.insertBefore(div, box);
} else {
list.appendChild(div);
}
aBoxLen += 1;
}
appendBox();
button.addEventListener('click', function () {
appendBox();
});
$.fn.is_on_screen = function () {
var win = $(window);
var viewport = {
top: win.scrollTop(),
left: win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};
function updateData(callback) {
var elements = document.querySelectorAll('.aBox');
elements = Array.prototype.slice.call(elements);
var toBe = counter - 1 - elements.length;
async.each(elements, function (element, cb) {
var inView = $(element).is_on_screen(),
ele = element.querySelector('.item');
if (inView == false && ele) {
console.log("Not in visible, keeping it none");
var height = element.clientHeight;
element.style.height = height + "px";
element.innerHTML = "";
} else if (!ele && inView) {
console.log('Placing the content');
console.log(element.getAttribute('index'));
var minArray = arr[element.getAttribute('index')],
str = "";
for (var j = 0; j < minArray.length; j++) {
str += "<div class='item'>" + minArray[j] + "</div>";
}
element.innerHTML = str;
}
cb();
}, function () {
// callback()
});
}
var delay = false;
var timeout = null;
list.addEventListener('touchmove', function () {
clearTimeout(timeout);
timeout = setTimeout(function () {
updateData();
}
}, delay);
});
None of the solutions were specifically designed for mobiles, so I have implemented this.
I think there is lots of space for improvement in this. If anybody want to improve it, please feel free to make it
Demo
I got an error: e is undefined on my javascript slider code when running it on Firefox.
On Chrome it works like a charm.
I've looked for an answer and found some posts and answers (even this one: Windows.event is undefined -Javascript error in firefox)
However , I didn't succeed to implement that solution in my code and allways got more e is undefined errors.
Would like to get an advice of how to solve it.
My js code: (Focusing on the this.sliderMove function)
(function(){
function reallyNiceSlider(obj){
/* From how far the mouse starts affecting the item? in pixels */
this.range = {min: 2, max: 200};
/* how smooth would the transition be? Every step is another call of the interval function before getting to the final goal */
this.steps=5;
/* A variable to hold the index of our interval function */
this.t=-1;
/* 2 dimensional array: targets[i][0] = goal width of object; targets[i][1] = step size; targets[i][2] = the object; targets[i][3] = saving the width of the object; targets[i][4] = Width when mouse is out of range */
this.targets = new Array();
/* The object of the slider */
this.slider = obj;
/* max and min sizes */
this.values = {min: 80, max: 130}
/* safe range */
this.safe = 0;
this.sideMargin = 3;
this.init = function(){
var children = this.slider.getElementsByTagName('a');
var selectedObj = null;
for(var i = 0; i < children.length; i++){
if(children[i].className == 'selected')
selectedObj = children[i];
children[i].getElementsByTagName('img')[0].style.width = this.values.min + 'px';
this.targets[i] = Array(-1, 0, children[i], this.values.min, -1);
}
if(selectedObj)
this.sliderPick();
}
this.truePosition = function(obj){
var x=obj.offsetWidth/2, y=obj.offsetHeight/2;
do{
x += obj.offsetLeft;
y += obj.offsetTop;
}while(obj = obj.offsetParent);
return {x:x,y:y};
}
this.sliderMove = function(obj){
var e = window.event;
var range = obj.range;
var offset, cursor={x:0,y:0}, diff={x:0,y:0,total:0,ratio:0}, opacity, max = range.max+obj.safe, child;
var selectedObj = null;
if(e.pageX || e.pageY){
cursor.x = e.pageX;
cursor.y = e.pageY;
}
else{
cursor.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
cursor.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
for(var i=0; i < obj.targets.length; i++){
child = obj.targets[i];
offset = obj.truePosition(child[2].getElementsByTagName('img')[0]);
diff.x = cursor.x > offset.x ? cursor.x - offset.x : offset.x - cursor.x;
diff.y = cursor.y > offset.y ? cursor.y - offset.y : offset.y - cursor.y;
diff.total = Math.sqrt(diff.y*diff.y + diff.x*diff.x);
if(diff.total < max){
max = diff.total;
diff.ratio = diff.x / diff.total;
}
if(child[2].className == 'selected')
selectedObj = child[2];
}
if(max <= range.max){
for(var i=0; i < obj.targets.length; i++){
child = obj.targets[i];
offset = obj.truePosition(child[2].getElementsByTagName('img')[0]);
diff.x = cursor.x > offset.x ? cursor.x - offset.x : offset.x - cursor.x;
diff.y = cursor.y > offset.y ? cursor.y - offset.y : offset.y - cursor.y;
diff.total = Math.sqrt(diff.y*diff.y + diff.x*diff.x);
if(diff.total > range.max) diff.total = range.max;
if(diff.total < range.min) diff.total = 0;
child[0] = parseInt( obj.values.max - ((diff.total/range.max) * (obj.values.max - obj.values.min) ));
if(child[0] > obj.values.max) child[0] = obj.values.max;
child[1] = (child[0] - child[3])/this.steps
obj.targets[i] = child;
}
if(this.t < 0)
obj.makeInterval(obj);
}
else if(selectedObj && max >= range.max+(obj.safe * diff.ratio))
obj.sliderPick();
}
this.findSize = function(range_obj){
var range = this.range, values = this.values;
if(range_obj > range.max) return values.min;
var range_edge = range.max - range_obj;
var size_at_point = (values.max - values.min) * ( range_edge / range.max);
return (range_edge / ((range_edge / size_at_point) + 1)) + values.min;
}
this.sliderPick = function(){
var e = window.event;
var range = this.range;
var offset, cursor={x:0,y:0}, diff={x:0,y:0,total:0}, opacity, child;
var selectedObj;
var difference = {init: 0, cumulative: 0}, j;
if(this.safe == 0){
for(j=0; j < this.targets.length; j++){
child = this.targets[j];
if(child[2].className == 'selected'){
child[0] = this.values.max;
child[4] = child[0];
child[1] = (child[0] - child[3])/ this.steps;
difference.init = (child[0] / 2) + this.sideMargin;
this.safe = (child[0] - child[3]) / 2;
cursor = this.truePosition(child[2].getElementsByTagName('img')[0]);
break;
}
}
difference.cumulative = difference.init;
for(var i=j+1; i < this.targets.length; i++){
child = this.targets[i];
child[0] = parseInt( this.findSize(difference.cumulative) );
child[4] = child[0];
difference.cumulative += child[0] + this.sideMargin;
child[1] = (child[0] - child[3])/this.steps;
this.safe += (child[0] - child[3]) / 2;
}
difference.cumulative = difference.init;
for(var i=j-1; i >= 0; i--){
child = this.targets[i];
child[0] = parseInt( this.findSize(difference.cumulative) );
child[4] = child[0];
difference.cumulative += child[0] + this.sideMargin;
child[1] = (child[0] - child[3])/this.steps;
this.safe += (child[0] - child[3]) / 2;
}
}
else{
for(var i=0; i < this.targets.length; i++){
child = this.targets[i];
child[0] = child[4];
child[1] = (child[0] - child[3])/this.steps
this.targets[i] = child;
}
}
if(this.t < 0)
this.makeInterval(this);
}
this.makeStep = function(obj){
var target, diff, sliderOffset = this.slider.offsetHeight, done=0;
for(var i = 0; i < obj.targets.length; i++){
target = obj.targets[i];
if(target[0] < 0) continue;
done = 1;
if(target[1]*target[1] >= (target[0] - target[3])*(target[0] - target[3])){
target[3] = target[0];
target[0] = -1;
}
else
target[3] = target[3] + target[1];
target[2].getElementsByTagName('img')[0].style.width = Math.round(target[3]) + 'px';
target[2].getElementsByTagName('img')[0].style.marginTop = Math.round( ( sliderOffset - target[2].getElementsByTagName('img')[0].offsetHeight ) / 2 ) + 'px';
opacity = parseInt(100* (target[3] / this.values.max) );
target[2].style.opacity=opacity/100;
target[2].style.filter='alpha(opacity=' + opacity + ')';
}
if(done == 0){
clearInterval(obj.t);
obj.t = -1;
}
}
this.makeInterval = function(obj){
obj.t = setInterval(function(){obj.makeStep(obj)}, 40);
}
this.init();
}
function reallyNice_slider_init(){
jQuery('.reallyNice_slider').each(function(){
var slider = new reallyNiceSlider(this);
if(document.addEventListener)
document.addEventListener('mousemove', function(){slider.sliderMove(slider)}, false);
else
document.attachEvent('onmousemove', function(){slider.sliderMove(slider)});
this.style.visibility = 'visible';
});
}
if(window.addEventListener)
window.addEventListener('load', reallyNice_slider_init, false);
else
window.attachEvent('onload', reallyNice_slider_init);
})();
UPDATE 1: When using the Firefox error's interface it says e is undefined and points the next line:
if(e.pageX || e.pageY){
Thanks in advance.
Change your handlers to this...
jQuery('.reallyNice_slider').each(function(){
var slider = new reallyNiceSlider(this);
if(document.addEventListener)
document.addEventListener('mousemove',
function(e){
slider.sliderMove(e, slider)
}, false);
else
document.attachEvent('onmousemove',
function(){
slider.sliderMove(window.event, slider)
});
this.style.visibility = 'visible';
});
Then change your functions to receive the event object as the first argument.
this.sliderMove = function(e, obj){
//var e = window.event; // remove this
var range = obj.range;
var offset, cursor={x:0,y:0}, diff={x:0,y:0,total:0,ratio:0}, opacity, max = range.max+obj.safe, child;
var selectedObj = null;
Try this:
this.sliderMove = function (obj) {
var e = obj.event || window.event;
...