Unexpected NaN value when parsing the attribute on after content + z-index - javascript

I have a really weird issue, here it is :
i wanted to create a perspective shadow like this topic (::after instead in my case) How to create a perspective shadow with CSS?
div {
position: relative;
display: inline-block;
height: 150px;
width: 150px;
background: url(//placehold.it/150x150);
margin-left: 30px;
}
div::before {
content: "";
position: absolute;
z-index: -1;
bottom: 0;
left: 15px;
height: 10%;
width: 70%;
box-shadow: -25px -4px 4px 0 rgba(0,0,0,0.75);
transform: skewX(60deg);
}
and then when i load my webpage and then i click on "inspect element" from firefox and click on something in the code, i've got this issue "Unexpected NaN value when parsing the attribute", i searched on forum and people said that it may be a Qjery problem but when i delete this ::after everything is good.
here is my Javascript file:
function styleTabHover(tabButton){
tabButton.style.color= "#ff9900";
}
function styleTabOut(tabButton){
tabButton.style.color= "white";
tabButton.style.borderColor= "white";
}
function check_email(ev){
var champ = ev.currentTarget;
if(!champ.value.includes("#")){
champ.style.outline = "2px dotted red";
document.getElementById("champ_requis").style.opacity = "1";
}else{
champ.style.outline = "none";
document.getElementById("champ_requis").style.opacity = "0";
}
}
function changeTab(idbouton){
var tabs = document.getElementsByClassName("menu_bouton");
console.log(tabs,"changetab fonction lancé")
var i;
for (i=0;i<tabs.length;i++){
tabs[i].style.backgroundColor = "initial";
tabs[i].style.zIndex = "0";
tabs[i].onmouseover = function(){styleTabHover(this)};
tabs[i].onmouseout = function(){styleTabOut(this)};
}
var bouton = document.getElementById(idbouton);
bouton.style.background = "#ff9900";
bouton.style.color = "white";
bouton.onmouseover= function(){this.style.cursor = "default"};
}
var imgPositionMoins = 0;
function style_projet_slide(droite){
var lst_projetImg = document.getElementsByClassName("projets_img");
var i;
if(droite && (imgPositionMoins > (-100*(lst_projetImg.length-1)) ) ){
imgPositionMoins -= 100;
for(i=0;i<lst_projetImg.length;i++){
lst_projetImg[i].style.left = imgPositionMoins+"%";
}
}else if ( !droite && imgPositionMoins < 0){
imgPositionMoins += 100;
for(i=lst_projetImg.length-1; i>=0; i--){
lst_projetImg[i].style.left = imgPositionMoins+"%";
}
}
}
function projet_desc(indice){
var lst_desc=document.getElementById("projet_desc").children;
var i;
for (i=0;i<lst_desc.length;i++){
if (i==indice){
lst_desc[i].style.display = "block";
} else{
lst_desc[i].style.display = "none";
}
}
window.scroll({
top: 800,
left: 0,
behavior: 'smooth'
});
}
another problem i get, when i use z-index -1 when i load the webpage, i see the ::before content during 1 second which is supposed to be behind the main content. So, i tried to use a positive z-index as people said but it doesnt work when i put a higher z-index on the main content. I saw that i have to put position:relative but on the official doc. it shows that we can do an absolute position.
Can someone help me ? Thanks !

Related

DOM assign an id to child Javascript

I have created a grid with div, class and id. I want to randomly create a yellow square and I want to assign an id= 'yellowSquare' how do I do it?
var grid = document.getElementById("grid-box");
for (var i = 1; i <= 100; i++) {
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var playerOne = [];
while (playerOne.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerOne.indexOf(randomIndex) === -1) {
playerOne.push(randomIndex);
var drawPone = document.getElementById('square' + randomIndex);
drawPone.style.backgroundColor = 'yellow';
}
}
#grid-box {
width: 400px;
height: 400px;
margin: 0 auto;
font-size: 0;
position: relative;
}
#grid-box>div.square {
font-size: 1rem;
vertical-align: top;
display: inline-block;
width: 10%;
height: 10%;
box-sizing: border-box;
border: 1px solid #000;
}
<div id="grid-box"></div>
I am new to Javascript / jQuery. Any help will be much appreciated ! Thank you
There are two options to your question. You can either change the id of the yellow square which is already created from your code, or create a child element within the square, which looks the same as your current solution. Creating a new child element will let you keep the numeric id pattern for the grid:
Changing the ID :
var element = document.getElementById('square' + randomIndex)
element.id = "yellowSquare";
Adding new element inside:
var node = document.createElement("DIV");
node.id = "yellowSquare";
node.style = "background-color:yellow;height:100%;width:100%;";
var element = document.getElementById('square' + randomIndex)
element.appendChild(node);
I set the styling of the div child to 100% width and height, as it has no content, and would get 0 values if nothing was specified. This should make it fill the parent container.
There are also multiple other ways to achieve the same result, for instance with JQuery.
Use the HTMLElement method setAttribute (source);
...
var drawPone = document.getElementById('square' + randomIndex);
drawPone.style.backgroundColor = 'yellow';
drawPone.setAttribute('id', 'yellowSquare');
...
As you requested in your comment how to move the square i made an example how you can move it left and right using jQuery next() and prev() functions. However because your html elements are 1 dimensional it's not easy to move them up/down and check the sides for collisions. Better would be to create your html table like with rows and columns and this way create a 2 dimensional play field.
Also added a yellowSquery class for selection with $drawPone.addClass('yellowSquare');.
Also since you like to use jQuery I changed your existing code to jQuery function. Might help you learn the framework.
var $grid = $("#grid-box");
for (var i = 1; i <= 100; i++) {
var $square = $("<div>");
$square.addClass('square');
$square.attr('id','square' + i);
$grid.append($square);
}
var playerOne = [];
while (playerOne.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerOne.indexOf(randomIndex) === -1) {
playerOne.push(randomIndex);
var $drawPone = $('#square' + randomIndex);
$drawPone.addClass('yellowSquare');
}
}
$('#button_right').on('click', function(){
$yellowSquare = $('.yellowSquare')
$yellowSquareNext = $yellowSquare.next();
$yellowSquare.removeClass('yellowSquare');
$yellowSquareNext.addClass('yellowSquare');
});
$('#button_left').on('click', function(){
$yellowSquare = $('.yellowSquare')
$yellowSquarePrev = $yellowSquare.prev();
$yellowSquare.removeClass('yellowSquare');
$yellowSquarePrev.addClass('yellowSquare');
});
#grid-box {
width: 400px;
height: 400px;
margin: 0 auto;
font-size: 0;
position: relative;
}
#grid-box>div.square {
font-size: 1rem;
vertical-align: top;
display: inline-block;
width: 10%;
height: 10%;
box-sizing: border-box;
border: 1px solid #000;
}
.yellowSquare {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="grid-box"></div>
<button id="button_left">left</button>
<button id="button_right">right</button><br>

jQuery offset issues with div overflow: scroll

I am writing an HTML5 board game and I am having issues with jQuery's offset(). The grid of DIVs that make up the game board reside within a wrapper DIV that has CSS that sets overflow:scroll/width and height:100%. The game board itself is quite larger, so the scroll can be quite a bit horizontally and vertically.
The problem is that when I click on a DIV and try to move the player to that board piece, the player shifts around and is never in a consistent place relative to the board piece clicked.
Code:
$(".boardGridPiece").click(function(){
if(!$(this).hasClass("room") && $(this).hasClass("eligibleMove")){
playerStartX = $(this).offset().left;
playerStartY = ($(this).offset().top;
player.css("left", playerStartX);
player.css("top", playerStartY);
determineEligibleMoves($(this).attr("id"));
}
});
You can see that when a board piece is clicked, the offset of the board piece is grabbed and set to the player's X and Y.
CSS:
#boardWrapper {
position:relative;
width:100%;
height:80%;
overflow: scroll;
}
#theGame {
background-color: #fff;
height: 1080px;
width: 1920px;
}
Depending on where the player is relative to the current scroll view, when I click on a board piece he shifts around in a very inconsistent manner. Sometimes he's far left of where I click, or far up, etc.
What am I doing wrong? How do I take into account relative scroll position to get consistent positioning?
Here's a board for you to play with as an example. Also, my stab at the jquery is included as well. Basically, it finds where you clicked, calculated the px distance in float form, and animates the soldier to slide to his new position:
var black = '<td style="background-color:black"><div class="boardGridPiece"></div></td>';
var white = '<td style="background-color:white"><div class="boardGridPiece"></div></td>';
var squares = [black, white];
var grid = "";
for (var i = 0; i < 9; i++) {
grid += "<tr>";
for (var j = 0; j < 16; j++) {
grid += squares[(i + j) % 2];
}
grid += "<\tr>";
}
$('#gameboard').append(grid);
var gridSelected = $('#gameboard').find('tr:nth-child(2)').find('td:first').find('div');
gridSelected.toggleClass('position');
$('.boardGridPiece').click(function () {
$('.position').removeClass('position');
var gridSelected = $(this);
gridSelected.toggleClass('position');
var thisBox = $('.position');
var finalX = 0;
var finalY = 0;
for (var i = 0; i < 9.00; i++) {
for (var j = 0; j < 16.00; j++) {
var aBox = $('#gameboard').find('tr:nth-child(' + (i + 1) + ')').find('td:nth-child(' + (j + 1) + ')').find('div');
if (thisBox.get(0) == aBox.get(0)) {
finalX = j + 1;
finalY = i;
i = j = 16; // soft break
}
}
}
var overX = (finalX * parseFloat(1920))/16.00;
var downY = (finalY * parseFloat(1080))/9.00;
$('#player').animate({ left: overX, top: downY });});
html {
background-color:gray;
}
#gameboard {
margin: 100px;
height:1080px;
width:1920px;
border:1px solid black;
}
.boardGridPiece {
height: 110px;
width: 110px;
}
.position {
box-sizing:border-box;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
border: 1px solid red;
}
#player {
position: absolute;
top: 120px;
left: 125px;
height: 200px;
width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="gameboard" style=""></table>
<img id="player" src="http://img2.wikia.nocookie.net/__cb20110819034426/halo/images/7/74/ODST_Helljumper.png" />

How to remove flicking in IE?

I have created this fiddle where I have flicking problem in IE. Even Chrome isnt good, but in fiddle it looks more or less fine. I think problem is in "size of step" for one scroll, when you grab scroller manualy everything is smooth, but using your mousewheel leads to jumping/flicking in IE and Chrome.
window.addEventListener('scroll', function() { ...}, false);
This is my current HTML:
<div id="fakeBody">
<div id="spacer">scroll down</div>
<div class="niceBanner hide roller" id="niceBannerFrame">
<div id="bannerShadow"></div>
<div id="thumb0">
<div id="niceBannerOriginal" class="roller thumb1 thumb2"></div>
<div id="niceBannerBlur" class="roller deblur thumb1 thumb2"></div>
<div id="blackRow"></div>
</div>
</div>
</div>
Script:
window.addEventListener('scroll', function () {
var totalHeigth, currentScroll, visibleHeight;
var newResolutionBannerHeight = 0;
currentScroll = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop;
totalHeigth = (document.height !== undefined) ? document.height : document.getElementById("fakeBody").offsetHeight;
visibleHeight = document.documentElement.clientHeight;
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;
var curentWidth = x;
console.log('curent Width: ' + curentWidth);
if (curentWidth < 1070) {
var newBannerWidth = Math.round((curentWidth / 1070) * 1920);
var newMargin = Math.round((newBannerWidth - curentWidth) / 2);
newResolutionBannerHeight = Math.round((500 / 1920) * newBannerWidth);
} else {}
//now it is easy to recognize if visitor is at the bottom of page
if (visibleHeight + currentScroll >= totalHeigth) {
//do the magic with banner
document.getElementById("niceBannerFrame").className = "unhide";
var bannerHeight = visibleHeight + currentScroll - totalHeigth;
var style = document.createElement('style');
style.type = 'text/css';
var number = (curentWidth < 500) ? 10 + bannerHeight : 50 + bannerHeight; //not ideal solution, slower rolling for small screen, picture is realy small
if (curentWidth > 1070) {
number = (number > 500) ? 500 : number;
var opacityBlur = 1 - (number / 500);
style.innerHTML = '.roller {bottom:-' + number + 'px;} .deblur {opacity:' + opacityBlur + ';} .thumb2{height: 500px;} ';
} else {
number = (number > newResolutionBannerHeight) ? newResolutionBannerHeight : number;
var opacityBlur = 1 - (number / newResolutionBannerHeight);
style.innerHTML = '.roller {bottom:-' + number + 'px;} .deblur {opacity:' + opacityBlur + ';} .thumb2{height:' + newResolutionBannerHeight + 'px;} ';
}
document.head.appendChild(style);
} else {
//it is not good time for magic, scroll a bit more or I will hide already visible bilboard
document.getElementById("niceBannerFrame").className = "hide";
}
}, false);
and CSS:
#spacer {
height: 1000px;
background-color: whitesmoke;
}
#niceBannerOriginal {
background-image:url(http://nzworker.com/jakub-portfolio/justfiles/1920x500_original.jpg);
position: absolute;
z-index:-3;
}
#niceBannerBlur {
background-image:url(http://nzworker.com/jakub-portfolio/justfiles/1920x500_blur.jpg);
position: absolute;
z-index:-2;
}
#bannerShadow {
position:absolute;
background-image:url(http://nzworker.com/jakub-portfolio/justfiles/Stin.png);
background-repeat:repeat-x;
width:100%;
z-index:-1;
height:25px;
}
.hide {
display: none;
}
.unhide {
display: block;
}
#fakeBody {
height:1000px;
position:relative;
top:0;
left:0;
right:0;
}
#blackRow {
display:none;
}
#niceBannerFrame {
overflow: hidden;
}
#media (min-width: 1921px) {
#blackRow {
background-color: #000000;
display: block;
height:500px;
position: absolute;
width: 100%;
z-index: -6;
}
}
/*desktop resolution*/
#media (min-width: 1070px) and (max-width: 1920px) {
.thumb1 {
width: 100%;
height: 500px;
background-position: 50% 50%;
/*image centering*/
}
.thumb2 {
}
}
/*mobile and tablet resolution*/
#media (max-width: 1069px) {
.thumb2 {
width: 100%;
height: 500px;
background-repeat:no-repeat;
/*background-position: 50% 50%; image centering*/
}
#niceBannerOriginal {
background-image:url(http://nzworker.com/jakub-portfolio/justfiles/1920x500_original-thumb.jpg);
background-size: 100%;
}
#niceBannerBlur {
background-image:url(http://nzworker.com/jakub-portfolio/justfiles/1920x500_blur-thumb.jpg);
background-size: 100%;
}
}
My question is do you how to remove this flicking? Or do you know how to cut one mouse wheel step to more smaller ones?
PS: I can not use jQuery or other plugins.
I can't be 100% sure about this, but I think the flickering isn't from the amount you're scrolling, but due to the fact that you're changing the display mode, and pushing the view back up a tiny bit.
Essentially if you are just underneath the visibleHeight+currentScroll >= totalHeigth test by a couple of pixels, then currentScroll get's pushed up a tiny bit when whatever happens in there happens (I don't entirely understand what's going on, so I can't really give any better advice on that), so that it's no longer greater than totalHigth, and so it then fails the test immediately after, hence the flickering.
Worked this out by getting rid of the hide line at the end and it seems to work. Unfortunately I don't entirely understand the code, so I can't give you any better idea than that, though hopefully it points you towards a solution.

Adding incremental relative position to dynamically created divs

I am trying to create this shape using dynamically created divs. I have this code already in place:
var bgImg = ['ScreenShot.png', 'stars.jpg', 'ScreenShot.png', 'stars_1230_600x450.jpg'];
for (var i = 0, n = 12; i < n; i++) {
var port = document.createElement('div');
document.body.appendChild(port);
port.style.backgroundImage = "url('" + bgImg[3] + "')";
I would like to create this image: https://flic.kr/p/mSJm6G
which will eventually hold images from the array. (one image per slot on the grid.)
I have tried below, which only does not work, it doesn't do what i want, which is to add that amount each time a new div is created. I want a new object to raise by 40px each time it is created.
$(port).css('top','+=40n');
I think that i will have to create three divs/scripts,, one for each row, so that i can get the divs to align properly. the master css will set the divs with a negative margin-top so they can cascade properly.
for reference, my css looks like this:
div {
height: 190px;
width:230px;
background: red;
position: relative;
background: #ef4c4d;
background-position: center;
float: left;
margin: 8px;
top: 30px;
left: 10px;
}
div:before {
content: '';
position: absolute;
bottom: 0; right: 0;
border-bottom: 60px solid #0d1036;
border-left: 60px solid transparent;
width: 0;
}
div:after {
content: '';
position: absolute;
top: 0; left: 0;
border-top: 60px solid #0d1036;
border-right:60px solid transparent;
width: 0;
}
I think that i need to pull the integer from an array, but really not sure.
Some things I notice in your code:
for (var i = 0, n = 12; i < n; i++) {
var port = document.createElement('div');
document.body.appendChild(port);
// <- end "}" of for loop is missing here
port.style.backgroundImage = "url('" + bgImg[3] + "')"; // <- will just be applied on the last created div
I guess you want something like this:
for (var i = 0, n = 12; i < n; i++) {
var port = document.createElement('div');
port.style.backgroundImage = "url('" + bgImg[3] + "')";
document.body.appendChild(port);
}
To update the "top" property, you can use this code with jQuery:
for (var i = 0, n = 12; i < n; i++) {
var port = $('<div></div>');
port.css("background-image", "url('" + bgImg[3] + "')");
port.css("top": 40 * i + "px"); // <- set "top" +40px for each div
$("body").append(port);
}

Javascript animation only works in one direction

The webpage I'm trying to create has a bidirectional sliding animation on it. However the animation is only partially working. To be more precise, the animation slides up, but it only slides down partway. Here's my JavaScript:
function showLayer() {
var hiddenLayer = document.getElementById("mainmenu");
var layerPosition = parseInt(hiddenLayer.style.top);
if (layerPosition > 315) {
hiddenLayer.style.top = (layerPosition - 5) + "px";
setTimeout("showLayer()", 20);
}
}
function hideLayer() {
var hiddenLayer = document.getElementById("mainmenu");
var layerPosition = parseInt(hiddenLayer.style.top);
if (layerPosition <= 315) {
hiddenLayer.style.top = (layerPosition + 5) + "px";
setTimeout("hideLayer()", 20);
}
}
Notice on the fourth line of the hideLayer function, I have the condition set to <= 315, this is due to the fact that setting it equal to 315 causes the element to move only a few pixels in either direction after clicking the trigger element. Here's the HTML elements I have dedicated to the animation:
<div id="mainbutton" onclick="showLayer('mainmenu'); hideLayer('mainmenu')"></div>
<div id="mainmenu" style="position: absolute; top: 690px; left: 9px;"
onclick="showLayer('mainmenu')"> </div>
And here are the styles for them:
div#mainmenu { width: 600px; height: 350px; border-style: solid; background-color:
rgb(0, 0, 0) ; border-width: 3px; border-top-right-radius: 7px; border-top-left-
radius: 7px; }
div#mainbutton { position: absolute; top: 674px; left: 12px; width: 28px; height:
28px; border-style: solid; border-color: rgb(255, 255, 255); border-width: 1px; border-
radius: 4px; }
And the fiddle : http://jsfiddle.net/JAtLA/
I had to put some of the styles inline with the HTML because the animation wouldn't work any other way. At first I thought the problem had solely lain in the if conditional of the hideLayer function. But after tweaking it I'm not so sure now.
I don't know if it's what you want but here is my answer :
There is a problem of logic in your code. You wrote
if(layerPosition<=315){
hiddenLayer.style.top = (layerPosition + 5) + "px";}
It means that if the top is 315 or less, the top will increase until it arrives to 316. But in the first function, you say it to stop at 315. So the function hideLayer will just get it moving from 1 pixel.
The solution is to tell him <400 instead of <=315 (or something higher than 400).
Here is a modified fiddle : http://jsfiddle.net/7egr7/2/
It looks like "hideLayer" will stop if (layerPosition <= 315). Is that really what you want? It happens after 1 iteration.
Note that the y axis goes down the screen (i.e. zero is at the top).
Clicking the button will call showLayer, and then hideLayer.
If the menu is open (i.e. layerPosition > 315), showLayer will not do anything (i guess that is what you intend), and hideLayer will make the menu go up by 5 (from 315 to 320).
On the next iteration of hideLayer (layerPosition <= 315) will be false, so it will not do anything.
Try this:
var open = false;
function showLayer() {
if (open)
return;
var hiddenLayer = document.getElementById("mainmenu");
var layerPosition = parseInt(hiddenLayer.style.top);
if (layerPosition > 315) {
hiddenLayer.style.top = (layerPosition - 5) + "px";
setTimeout("showLayer()", 20);
}
else {
open = true;
}
}
function hideLayer() {
if (!open)
return;
var hiddenLayer = document.getElementById("mainmenu");
var layerPosition = parseInt(hiddenLayer.style.top);
if (layerPosition <= 685) {
hiddenLayer.style.top = (layerPosition + 5) + "px";
setTimeout("hideLayer()", 20);
}
else {
open = false;
}
}
In the html, I would like to check if the thing is open or closed before doing anything.
<div id="mainbutton" onclick="if (!open) { showLayer('mainmenu'); } else { hideLayer('mainmenu'); }">
but layerPosition <= 685 is the only change that really matters.

Categories