Javascript object required (IE8) - javascript

javascript for elements re-size works fine on my tumblr theme, but I get the object required error on the following line in IE8:
fschildren = $("fs_wrapper").childNodes;
Thanks for help
Peter
<script type="text/javascript">
function resizedivs() {
$ = function(id) { return document.getElementById(id); }
fschildren = $("fs_wrapper").childNodes;
postc = 0;
thedivs = new Array();
for(i = 0; i < fschildren.length; i++) {
if(fschildren[i].tagName == "DIV") {
thedivs[postc] = fschildren[i];
postc++;
}
}
newwidth = 0;
for(i = 0; i < thedivs.length; i++) {
if(newwidth <= document.body.clientWidth) {
newwidth = newwidth + (thedivs[i].clientWidth)+15;
}
if(newwidth >= document.body.clientWidth || newwidth >= 1300) { // 100 for padding minus 15 extra
newwidth = newwidth - (thedivs[i].clientWidth+15);
break;
}
}
$("fs_wrapper").style.width = newwidth-0+"px";
$("fs_wrapper").style.position = "relative";
$("fs_wrapper").style.left = "0px";
$("sec2").style.width = newwidth-0+"px";
$("sec2").style.position = "relative";
$("sec2").style.left = "0px";
$("sec3").style.width = newwidth-0+"px";
$("sec3").style.position = "relative";
$("sec3").style.left = "0px";
}
window.onresize = function() {
resizedivs();
}
window.onload = function() {
resizedivs();
}
</script>

Does object really exist?
myObj = document.getElementById('myObj');
if(!myObj) {
alert("4004 not found");
return;
}
You are missing the right selector . for class or # for id
see this http://www.w3schools.com/jquery/jquery_ref_selectors.asp

Related

How to make horizontal margin between images constant in mosaic

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;
}

Javascript class method declaration throwing token error

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++;
});
}
}

Running the animation after scrolling to the block

I have function that works after window.onload, but how to run it just after scrolled to the needed . I understand that using jQuery is easier, but I need to do in native JS.
window.onload = function move() {
var width = 1;
var elem = document.getElementsByClassName("myBar");
var maxValue = document.getElementsByClassName('max-value');
for(var i = 0; i < elem.length; i++) {
var params = {
elem: elem[i],
maxElem: maxValue[i],
width: width,
interval: null
};
params.interval = setInterval(frame, 20, params);
}
function frame(aParams) {
if (aParams.width >= aParams.maxElem.dataset.max) {
clearInterval(aParams.interval);
} else {
aParams.width++;
aParams.elem.style.backgroundColor = 'blue';
aParams.elem.style.width = aParams.width + '%';
aParams.maxElem.innerHTML = aParams.width + '%';
}
};
};
https://codepen.io/Slava91/pen/PjpGGr
Try this, it will trigger the animation again when you will scroll near to the ul element. #percentage is the id I have given to the ul element in your html.
window.onload = move();
function move() {
var width = 1;
var elem = document.getElementsByClassName("myBar");
var maxValue = document.getElementsByClassName('max-value');
for(var i = 0; i < elem.length; i++) {
var params = {
elem: elem[i],
maxElem: maxValue[i],
width: width,
interval: null
};
params.interval = setInterval(frame, 20, params);
}
function frame(aParams) {
if (aParams.width >= aParams.maxElem.dataset.max) {
clearInterval(aParams.interval);
} else {
aParams.width++;
aParams.elem.style.backgroundColor = 'blue';
aParams.elem.style.width = aParams.width + '%';
aParams.maxElem.innerHTML = aParams.width + '%';
}
};
}
isScrolled = false;
window.onscroll = function loadItBack(){
var rec = document.getElementById("percentage").getBoundingClientRect();
if(window.scrollY > 600 && !isScrolled){
isScrolled = true;
move();
}else if(window.scrollY < 600){
isScrolled = false;
}
};
For your every li, you can use getBoundingClientRect to execute your animation.
Don't forget to set a flag once animation completed, else, it will execute on every scroll.

jQuery animate scrollLeft stops working after several clicks in FF and Chrome (but not Safari)

I have a very strange problem with some jquery code that scrolls a group of images. It seems to work in all browsers for the first several clicks, advancing the images by a number. And in Safari, it will work perfectly all the way to the end of the slideshow. But in FF and Chrome it will stop after a certain number of images. And this number is NOT always the same for some reason.
For example, on this page FF/Chrome will stop after clicking the next arrow 7 times.
And on this page, FF/Chrome will stop after clicking the next arrow 6 times.
Yet on this page, FF/Chrome will work all the way to the end as expected (and as Safari does all the time).
This is the code that controls the clicking:
<script>$(window).load(function(){
var currentElement = $("#ngg-gallery-list > div:nth-child(2)");
var onScroll = function () {
//get the current element
var container = $("#ngg-galleryoverview");
var wrapper = $("#ngg-gallery-list");
var children = wrapper.children();
var position = 0;
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
var childLeft = container.offset().left < child.offset().left;
if (childLeft) {
currentElement = child;
return;
}
}
}
var scrollToElement = function ($element) {
var container = $("#ngg-galleryoverview");
var wrapper = $("#ngg-gallery-list");
var children = wrapper.children();
var width = 0;
console.log(children.length);
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
if (child.get(0) == $element.get(0)) {
if (i == 0) {
width = 300;
}
container.animate({
scrollLeft: width
}, 300);
onScroll();
}
if (child.next().length > 0) {
//make sure we factor in borders/padding/margin in height
width += child.next().offset().left - child.offset().left
} else {
width += child.width();
}
}
}
var next = function(event) {
event.preventDefault();
scrollToElement(currentElement);
}
var prev = function(event) {
event.preventDefault();
var container = $("#ngg-galleryoverview");
if (currentElement.prev().length > 0) {
if (container.offset().left == currentElement.prev().offset().left) {
currentElement = currentElement.prev().prev().length > 0 ? currentElement.prev().prev() : currentElement.prev();
} else {
currentElement = currentElement.prev();
}
}
scrollToElement(currentElement);
}
$("#ngg-galleryoverview").on('scroll', onScroll);
$("#nexty").click(next);
$("#prevy").click(prev);
});
</script>
I'm stumped.
Well, making my code look more like what I found here fixed the problem. (Even if I am not entirely sure why). Hoping it helps someone else, here is the final code:
<script>
$(document).ready(function () {
var currentElement = $("#ngg-galleryoverview > div:nth-child(1)");
var onScroll = function () {
var container = $("#ngg-galleryoverview");
var children = $(".list");
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
var childLeft = container.offset().left < child.offset().left;
if (childLeft) {
currentElement = child;
//console.log(currentElement);
return;
}
}
};
var scrollToElement = function ($element) {
var container = $("#ngg-galleryoverview");
var children = $(".list");
var width = 0;
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
if (child.get(0) == $element.get(0)) {
if (i === 0) {
width = 0;
}
container.animate({
scrollLeft: width
}, 500);
onScroll();
}
if (child.next().length > 0) {
width += child.next().offset().left - child.offset().left;
} else {
width += child.width();
}
}
};
var buttonright = function (e) {
scrollToElement(currentElement.next());
};
var buttonleft = function (e) {
var container = $("#ngg-galleryoverview");
if (currentElement.prev().length > 0) {
if (container.offset().left == currentElement.prev().offset().left) {
currentElement = currentElement.prev().prev().length > 0 ? currentElement.prev().prev() : currentElement.prev();
} else {
currentElement = currentElement.prev();
}
}
scrollToElement(currentElement);
};
onScroll();
$("#ngg-galleryoverview").scroll(onScroll);
$("#nexty").click(buttonright);
$("#prevy").click(buttonleft);
});</script>

IE8 show hide issue for scrollable table

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;

Categories