Image overlapping a span in another li element - javascript

EDIT: I have created a JS-Fiddle that shows you the code in action and you can see how the caption's text is being overlapped. https://jsfiddle.net/wj76sv1h/
So I have a list of divs that display images obtained from a Database. This list is created by PHP, but when I have attempted to add a caption, as you can see from the image (sorry I can't include the image directly in the post), it is being overlapped by another Li element's image. The caption is a span tag.
I have attempted to change the z-index of the images and the divs, however it seems like it has no effect. I am also using this code in order to create the grid system using the lis.
function createListStyles(rulePattern, rows, cols) {
var rules = [], index = 0;
for (var rowIndex = 0; rowIndex < rows; rowIndex++) {
for (var colIndex = 0; colIndex < cols; colIndex++) {
var x = (colIndex * 100) + "%",
y = (rowIndex * 100) + "%",
transforms = "{ -webkit-transform: translate3d(" + x + ", " + y + ", 0); transform: translate3d(" + x + ", " + y + ", 0); }";
rules.push(rulePattern.replace("{0}", ++index) + transforms);
}
}
var headElem = document.getElementsByTagName("head")[0],
styleElem = $("<style>").attr("type", "text/css").appendTo(headElem)[0];
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = rules.join("\n");
} else {
styleElem.textContent = rules.join("\n");
}
}
If anyone could help me, that would be great. Thanks. This is the html used for the item/caption.
<div class="item" id="item-covert"><span>Caption</span> <div id="item-price"> $54.36</div><img class="item-image" src="image.url"></div>
Css:
.item {
position: relative
}
.item span {
display: none;
position: absolute;
bottom: 0;
padding: 10px;
background: rgba(255,255,255,0.99);
/*top: 20px;
width: 300px;
height: 50px;*/
font-family: Open Sans;
/*margin-left: 110px;*/
left: 110px;
}
.item:hover span {
display: block
}

Your positioning of the span moves it onto the image. Move it ten pixels farther to the right, and it looks fine. https://jsfiddle.net/yak613/5p3uuzfg/
I've taken some liberties with the caption text :)
And some suggestions for cool caption colors :)
Live Example

Related

Hovering over pseudo after element to change the style

I'm trying to create a simple demo where rolling over a pseudo element will change the style of its parent. In other words, I want to be able to roll over the letter e in the top right corner of the image and then display the text content.
I've managed to get it working when rolling over the image itself, but not the pseudo element. I've commented out the working code for rolling over the image itself, and left the incorrect pseudo rollover code uncommented out.
I wonder whether you can actually select pseudo elements in JS as it shows null when trying to select any pseudo element.
Any ideas would be appreciated. Thanks for any help. The code is below:
Codepen: https://codepen.io/anon/pen/NZvdzr
/*document.querySelector('#img-wrap').onmouseover = function() {
document.querySelector('#caption-wrap').style.opacity = 1;
}
document.querySelector('#img-wrap').onmouseout = function() {
document.querySelector('#caption-wrap').style.opacity = 0;
}*/
document.querySelector('#img-wrap:after').onmouseover = function() {
document.querySelector('#caption-wrap').style.opacity = 1;
}
document.querySelector('#img-wrap:after').onmouseout = function() {
document.querySelector('#caption-wrap').style.opacity = 0;
}
#img-wrap {
width: 30%;
position: relative;
}
#caption-wrap {
position: absolute;
top: 0;
right: 0;
opacity: 0;
}
img {
width: 100%;
}
#img-wrap:after {
content: 'e';
position: absolute;
top: 0;
right: 0;
}
<div id='img-wrap'>
<img src='https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ-bCnPPMYp6QIfrCr2BR-imm_Sw9IHCXIXzE5fei7R8PTBKYGd'>
<div id='caption-wrap'>
<p>some text will appear</p>
</div>
</div>
You cannot listen to pseudo elements, but you can find out some interesting info via window.getComputedStyle(). Below is a demo.
I'm listening to mouse move on the image element and comparing the coords to see if they fall between the rectangle of the pseudo element.
There is a padding of 2px on each tolerance, you could change that to something else if you want to be more forgiving with the mouse over detection.
CanIUse.com says window.getComputedStyle() is supported by all browsers, but I haven't tested if they all return the proper coordinate information for this to work – you should cross browser test this before using.
var element = document.querySelector('#img-wrap')
element.onmousemove = function(event){
var elementRect = element.getBoundingClientRect()
var pseudo = window.getComputedStyle(element, ':after')
var pseudoRect = {
top: parseFloat(pseudo.top),
left: parseFloat(pseudo.left),
width: parseFloat(pseudo.width),
height: parseFloat(pseudo.height),
}
var mouseX = event.clientX
var mouseY = event.clientY
var yTolTop = elementRect.top + pseudoRect.top - 2
var yTolBot = elementRect.top + pseudoRect.top + pseudoRect.height + 2
var xTolLeft = elementRect.left + pseudoRect.left - 2
var xTolRight = elementRect.left + pseudoRect.left + pseudoRect.width + 2
//console.log(elementRect.top, yTolTop, mouseY, yTolBot, " | ", elementRect.left, xTolLeft, mouseX, xTolRight)
if(mouseY > yTolTop && mouseY < yTolBot && mouseX > xTolLeft && mouseX < xTolRight){
document.querySelector('#caption-wrap').style.opacity = 1;
}else{
document.querySelector('#caption-wrap').style.opacity = 0;
}
}
element.onmouseout = function(){
document.querySelector('#caption-wrap').style.opacity = 0;
}
#img-wrap {
width: 30%;
position: relative;
}
#caption-wrap {
position: absolute;
top: 0;
right: 0;
opacity: 0;
}
img {
width: 100%;
}
#img-wrap:after {
content: 'e';
position: absolute;
top: 0;
right: 0;
}
<div id='img-wrap'>
<img src='https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ-bCnPPMYp6QIfrCr2BR-imm_Sw9IHCXIXzE5fei7R8PTBKYGd'>
<div id='caption-wrap'>
<p>some text will appear</p>
</div>
</div>
Codepen: https://codepen.io/bergy/pen/YoxZBp
(edit: since the JS was getting the rects outside of the mouse move function, if the element was ever moved it would stop working. Now it looks for rects in mouse move so the bug is fixed)

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>

Create custom square grid using jquery

I am working on a project trying to make something resembling an etch-a-sketch. I have a 780x780px square, and I am trying to get a 16x16 grid, using a series of smaller square divs.
It is on this grid that I have the hover effect. I keep getting a 15x17 grid of square divs because the last square of the row won't fit. I have margins set to 1px and padding set to 0 so I figured that to fit 16 squares on a 780px wide row, it would require me to take into account the margins (15 1px margins) and from there I could divide (780-15) by 16, the number of squares I want.
That isn't working, and the next step of this project is to have a button where the user could input any number of squares for the row/column and have either a larger or smaller squared grid STILL ON the 780x780 square. Does anyone have any ideas? I'm pretty stumped.
$(document).ready(function() {
var original = 16;
for (var y = 0; y < original * original; y++) {
$(".squares").width((780 - 15) / original);
$(".squares").height((780 - 17) / original);
$("<div class='squares'></div>").appendTo('#main');
}
$('.squares').hover(
function() {
$(this).addClass('hover');
}
)
});
function gridq() {
$('.squares').removeClass('hover');
$('div').remove('.squares');
var newgrid = prompt("How many squares on each side?");
var widthscreen = 192;
if (newgrid > 0) {
for (var x = 0; x < newgrid * newgrid; x++) {
$(".squares").width(widthscreen / newgrid);
$(".squares").height(widthscreen / newgrid);
$("<div class='squares'></div>").appendTo('#main');
}
$('.squares').hover(
function() {
$(this).addClass('hover');
}
)
}
}
#main {
height: 780px;
width: 780px;
background-color: antiquewhite;
position: relative;
}
.squares {
margin: 1px;
padding: 0;
background-color: aquamarine;
display: inline-block;
float: left;
}
.hover {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id=main>
</div>
<button onclick="gridq()">Go Again!</button>
Try this snippet? Grid initialisation is set in the grid() function and then called later when necessary. The width is set dynamically to the 16th square's right side.and the remaining squares fill out as necessary.
var wide = (780 - 15) / 16,
tall = (780 - 17) / 16; // set the square dimensions. this can be incorporated into the grid() function with 16 replaced by 'original'
function grid(x, y) {
var original = x,
y = y;
$("#main").empty(); // empty and restart
$("#main").width(wide * (original + 1));
for (var i = 0; i < original * y; i++) {
$("<div class='squares'></div>").appendTo('#main');
}
var square = $(".squares");
square.width(wide);
square.height(tall);
var side = square.eq(original - 1).position().left + square.width() + 2; // tighten the #main width
$("#main").width(side);
$('.squares').hover(
function() {
$(this).addClass('hover');
}
)
}
grid(16, 16); // starting dimension
function gridq() {
$('.squares').removeClass('hover');
$('div').remove('.squares');
var newgrid = prompt("How many squares on each side?");
var widthscreen = 192;
if (newgrid > 0) {
grid(newgrid, newgrid);
}
}
#main {
background-color: antiquewhite;
position: relative;
}
.squares {
margin: 1px;
padding: 0;
background-color: aquamarine;
display: inline-block;
float: left;
}
.hover {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id='main'>
</div>
<button onclick="gridq()">Go Again!</button>
just got beat to it...ill post this as it answers the question slightly differently and I feel is a little cleaner. Also I added in a width and a height prompt.
see the codepen here
As a side note...its good practice to make the names of your variables make sense. Also I find that breaking down your code problems into smaller more manageable chunks makes it seem less overwhelming...one step at a time :)
Enjoy and good luck!
$(document).ready(function() {
//declare the variables at the top of your functions...it enables us to change them later
var columnWidthCount = 16;
var columnHeightCount = 16;
function makeBoxes() {
//boxcount lets us set how many times we want the for loop to run...when we change the columns/rows later this variable will be updated
var boxCount = columnWidthCount * columnHeightCount;
//
for (var i = 0; i < boxCount; i++) { //loop through each box
//any code you place in here will execute each time we loop around
$("<div class='squares'></div>").appendTo('#main');
}
//we only want to declare this once so we place it after the loop
$(".squares").width((780 / columnWidthCount) - 2);
$(".squares").height((780 / columnHeightCount) - 2);
$('.squares').hover(
function() {
$(this).addClass('hover');
}
);
}
//fire the initial function
makeBoxes();
// fire function after click
$('button').on("click", function() {
$('div').remove('.squares');
var squaresHigh = prompt("How many squares high? (must be a number)");
var squaresWide = prompt("How many squares wide? (must be a number)");
//prompt returns a string...use parseInt to turn that number string into an integer
columnWidthCount = parseInt(squaresWide);
columnHeightCount = parseInt(squaresHigh);
makeBoxes();
});
});
#main {
height: 780px;
width: 780px;
background-color: antiquewhite;
position: relative;
font-size:0;
white-space:nowrap;
}
.squares {
margin: 1px;
padding: 0;
background-color: aquamarine;
display: inline-block;
float: left;
}
.hover {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id=main>
</div>
<button>Go Again!</button>

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" />

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

Categories