I have been banging my head against this for a few hours and am no closer to a solution than I was before. I am dynamically generating <img> tags, each with their own unique ID, via an AJAX call and JavaScript and giving them certain border colors upon generation (marking whether they are 'good' or 'bad`).
// the div that the screenshots go in
<div id ="screenshots_holder"> </div>
// the JS that is generating the screenshots
var screenshots_holder = document.getElementById("screenshots_holder");
var x = "";
for(i in data.screenshots) {
var image_name = data.screenshots[i].split("/")
x += '<img id="' + image_name[2] +'"src="/static/';
x += data.screenshots[i];
x += '" style = "height: auto; border-style: solid; border-width: 5px; border-color: #1ebe1e; max-width: 10%; margin-right: 10px; margin-bottom: 10px; "';
x += 'onclick="blueifyScreenshot(this.id)" >'; <-- the problem is here!!
}
screenshots_holder.innerHTML = x;
This above code worked just fine... minus the very last part where I add the onclick attribute!
I am trying to make it so that when I click on a screenshot, its border changes color, it scales just a bit, and adds a box-shadow, all of which is done through a JavaScript function called blueifyScreenshot(id) which takes the unique id of the image as a parameter so it can be grabbed through jQuery.
Right now, I can get the screenshot to do that when I hover over it but that's not permanent. Unfortunately, I cannot get any of my CSS changes to go through.
Right now I am grabbing each image element by a jQuery id selector. I know that this is working and updated_id is what it should be because I've verified it through HTML/JS breakpoints in the debugger and matched it to the screenshot that I want to change the border of. blueifyScreenshot IS being called, but none of the CSS is changing no matter what I do.
I have tried using the .css method, which I know only works on existing elements, which my screenshots are.
function blueifyScreenshot(id) {
console.log("#" + id);
var updated_id = "#" + id;
// this isn't changing anything
$(updated_id).css({
"border-color": "#0614d1 !important",
"cursor" : "pointer" ,
"transform": "scale(1.1)",
"box-shadow": "0 0 12px #0614d1" });
}
I have tried adding a class with .addClass() and defining it in my .css sheet.
function blueifyScreenshot(id) {
console.log("#" + id);
var updated_id = "#" + id;
// this isn't changing anything either..
$(updated_id).addClass('selected_screenshot');
}
/* CSS */
.selected_screenshot {
border-color: #0614d1 !important;
cursor : pointer;
transform: scale(1.1);
box-shadow: 0 0 12px #0614d1;
}
I have even tried updating the style attribute of the image with the .attr() method.
function blueifyScreenshot(id) {
console.log("#" + id);
var updated_id = "#" + id;
// and THIS wont change anything.
$(updated_id).attr('style', "height: auto; border-style: solid; border-width: 5px; border-color: #0614d1; max-width: 10%; margin-right: 10px; margin-bottom: 10px;");
}
None of this has worked and my screenshots do not change when I click on them. I've tried browsing through StackOverflow to see if other people had this issue and it looks like everyone was able to resolve their problems through the methods I've tried.
Anyone able to assist, or maybe spot something I have not?
Just reference the element
onclick="blueifyScreenshot(this)"
and toggle a class
function blueifyScreenshot(elem) {
elem.classList.toggle('active')
}
Personally I would just use a dom method
var images = [
'http://placekitten.com/100/300',
'http://placekitten.com/200/200',
'http://placekitten.com/200/300',
'http://placekitten.com/100/200'
]
var outElem = document.getElementById('out')
images.forEach(function(src) {
var img = document.createElement('img');
img.className = 'example'
img.src = src
img.addEventListener('click', function() {
this.classList.toggle('selected')
})
outElem.appendChild(img)
})
img.example {
height: auto;
border-style: solid;
border-width: 5px;
border-color: #1ebe1e;
max-width: 10%;
margin-right: 10px;
margin-bottom: 10px;
}
img.example.selected {
border-color: #0614d1 !important;
cursor: pointer;
transform: scale(1.1);
box-shadow: 0 0 12px #0614d1;
}
<div id="out"></div>
Related
I have problem with this code because it works. Well, partially. My idea is to change background color of button on which user has clicked but data-line attributes increments only once and by that changing background color only once. (it enters in else and changes data-line value from 0 to 1 but my idea is to increment its value further and then by concluding whether value is odd or even to remove or add bg-danger class). All buttons (all with trashCan class) initially have data-line attribute with value zero and neutral background color. What is wrong with this code?
$(".trashCan").click(function(){
let trashCan = $(this);
let trash = parseInt(trashCan.data('line'))+1;
trashCan.attr('data-line',trash);
if(trash%2==0){
trashCan.removeClass("bg-danger");
}
else {
trashCan.addClass("bg-danger");
}
});
The issue is because you're accessing the data-line attribute with a mix of attr() and data(). The former reads from the DOM, while the latter reads from jQuery's internal cache. If you get the value with one of them you need to also set the value using the same method.
In the example below I've amended the logic to use data() only, which is the preferred choice where possible. If you absolutely have to update the DOM, then you would use attr() instead.
$(".trashCan").click(function() {
let trashCan = $(this);
let trash = parseInt(trashCan.data('line')) + 1;
trashCan.data('line', trash);
if (trash % 2 == 0) {
trashCan.removeClass("bg-danger");
} else {
trashCan.addClass("bg-danger");
}
});
.trashCan {
background-color: #CCC;
color: #000;
border-radius: 5px;
padding: 10px 30px;
border: 0;
}
.trashCan.bg-danger {
background-color: #C00;
color: #FFF
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="trashCan" data-line="0">Trash</button>
However, it's worth noting that this logic is not necessary. It seems that your goal is simply to toggle the class on successive clicks, in which case just use toggleClass() and remove the data attribute entirely:
$(".trashCan").click(function() {
$(this).toggleClass('bg-danger');
});
.trashCan {
background-color: #CCC;
color: #000;
border-radius: 5px;
padding: 10px 30px;
border: 0;
}
.trashCan.bg-danger {
background-color: #C00;
color: #FFF
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="trashCan">Trash</button>
I'm trying to show an image when a path on the site is hovered.
The hover part works well. However, when I "mouseout" the path, the image is removed but a red vertical line is always there.
This is my css :
.imgElu {
height: 23%;
width: auto;
position: absolute;
bottom: 33.1%;
left: 36.7%;
border-radius: 50%;
border: 3px solid #ac2c2d;
}
When not hovered :
When hovered :
I tried to use DOM to set display : "none" when the event "mouseout" is triggered. But the line is always briefly displayed before showing what you can see in the second photo.
Any help is appreciated.
UPDATE : I understood why I got this red line briefly when hovering a path : it's because the image is an url and is loading. And until it's not load, the css is "bordering" nothing. Now I'm searching to show nothing until it's not loaded, how can I do that ?
UPDATE 2 : this is my js code :
siege[0].addEventListener("mouseover", function() { //when mouseover
var actualImg = siege.Vignette; //gets the url Image
document.getElementById("photoElu").src = siege.Vignette; //puts the url on the img div
if (eluPresent == false) {
$('<p class="tooltip"></p>').text("Siège non occupé").appendTo('body').fadeIn('slow');
} else { //If there is something to show :
$('<p class="tooltip"></p>').text("Siège n°"+siege.Seat+" "+siege.Name).appendTo('body').fadeIn('slow');
document.getElementById('photoElu').style.border = "3px solid #ac2c2d"; //sets the css to the img div
}
siege.animate(hoverStyle, animationSpeed);
}, true);
siege[0].addEventListener("mouseout", function() { //when mouseout
$('.tooltip').remove();
document.getElementById("photoElu").src = ""; //remove the url
siege.animate(style, animationSpeed);
document.getElementById('photoElu').style.border = "0px solid #ac2c2d"; //sets the css to remove the border
}, true);
It's a border which is 3px in width that is being displayed, give your image style of box-shadow as an alternative to this problem.
Initially hide the content.
.imgElu {
height: 23%;
width: auto;
position: absolute;
bottom: 33.1%;
left: 36.7%;
border-radius: 50%;
border: none;
display: none;
}
You need to set border property when the div is hovered.
.imgElu:hover {
border: 3px solid #ac2c2d;
display: /*your display setting*/
}
Use
border: 0px solid #3c2c2d;
In your normal state, and
border: 3px solid #3c2c2d;
in your hover state.
If you are adding hover style using jquery, use jquery .css() method.
Hope this help
I'm working on some type of simple notification system.
Here is the jsfiddle: https://jsfiddle.net/t9pvmzhh/3/
I don't know why, but jsfiddle wont display all 4 of the notifications although it works just fine on my page. I'm probably doing something wrong, you can also help me correct the jsfiddle code...
I have started working on clearing each notification after 1000ms, but got stuck at the end of the JS code. The "id" var returns clear0(), clear1(), just as intended, but now I have to call a function and function id { } isn't working. Is that even possible? Can I call a function like this, or I need to find another workaround (I am probably gonna add an X to close the notification, but auto-closing would be nicer)
HTML
<div class="notificontainer" id="notificontainer">
</div>
CSS
.notificontainer {
position: fixed;
border: 1px solid blue;
width: 40vw;
height: 20px;
left: 30%;
bottom: 10px;
}
.notification {
display: none;
transition: visibility .5s;
position: absolute;
border: 1px solid #44DDFF;
background-color: rgb(0, 0, 0);
width: 50%;
height: auto;
padding: 0;
left: 25%;
bottom: 0px;
color: #ffffff;
}
.tooltipheader {
margin: 0px;
padding: 2%;
text-align: center;
border-bottom: 1px groove #949494;
background-color: rgba(165,165,175, .1);
}
JS
notification("Hi world1");
notification("Hi world2");
notification("Hi world3");
notification("Hi world4");
var counted = 0;
function notification(what) {
counted++;
var elem = document.getElementById("notificontainer");
elem.innerHTML += "<div class=\"notification\" id=\"noty" + counted + "\"><div class=\"tooltipheader\"" + what + "</div></div>";
document.getElementById("noty" + counted).style.bottom = counted * 40 + "px";
document.getElementById("noty" + counted).style.display = "initial";
var id = "clear" + counted + "()";
window.setTimeout("clear" + counted, 1000);
}
You can pass parameters to the setTimeOut()'s function callback.
How can I pass a parameter to a setTimeout() callback?
setTimeout(function(param){
console.log("noty"+param);
document.getElementById("noty" + param).style.display = "none";
}.bind(null,counted), 3000);
Updated Fiddle:
https://jsfiddle.net/t9pvmzhh/5/
function clear(id) {
document.getElementById("noty"+id).parentElement.removeChild(document.getElementById("noty"+id));
}
Basically, you haven't defined the clear function, so the call wasn't successfull.
Also, to "remove" an item with pure js, you can't remove the item directly, only his parent can:
As James said, the DOM does not support removing an object directly. You have to go to its parent and remove it from there. Javascript won't let an element commit suicide, but it does permit infanticide... – Mark Henderson Aug 1 '10 at 23:36
Remove element by id
Try to always work with the debug window open, so you can check this kind of stuff.
I am making a comma separated "tag" type system, and I want the tags to scroll left to right, then go to the next line if the next tag would cause that line to be wider than the max width of the container.
I get different results if I use <span> or <div>
<span class="tag"><span class="tagspan" ></span></span>
<div class="tag"><span class="tagspan" ></span></div>
but neither one correctly wraps to the next line. ( If I use span it WILL wrap to next line, but it will break the tag in half and place the rest of it on the next line ).
Surely there must be an easy fix for this. I am trying to avoid having to calculate the width of each line and compare its current width to the width it would be if the next tag were added, then deciding if there needs to be a line break or not.
Any suggestions would be greatly appreciated.
JS Bin Here
jQuery:
$('document').ready( function() {
var value;
var tag;
var cloned;
$('#tag').on( 'change keyup', function(){
value = $('#tag').val();
tag = value.split(',');
if (tag[1] != null && tag[0] !== ''){
cloned = $('.tag').first().clone().appendTo('#container');
$(cloned).find('span').html(tag[0]);
$(cloned).css({'opacity' : '1', 'width' : $(cloned).find('span').width() + 'px'});
$('#tag').val('');
}
if (tag[1] != null && tag[0] === ''){
$('#tag').val('');
}
console.log($('.tagspan').width() + 'px');
});
});
You can use float:left to your tag elements instead of the container and drop the display:inline-flex attribute which results in a line break if your tags reach the end of the line. Edit: change the outer span elements to divs for that effect.
// thanks Gary ;)
This is more related to CSS styling than JavaScript code, I think I got it working just tweaking two classes in your CSS code:
span {
vertical-align:middle;
display: inline-flex;
word-break: keep-all;
}
#container {
text-align: left;
display: block;
min-width:400px;
max-width:400px;
height:100px;
border:1px solid;
}
This is how it looks like:
The thing is, span elements must fit into its parent element, that's why you should make children display inline and not its parent.
Working example: Wrap span tags into DIV
Given that you were working with flexbox, you might want to try add to your .container class flex-wrap:wrap; This acheives a similar effect.
There are a few styles that are causing problems for you (referencing the JSBin you posted). The following should fix your problems:
.tag {
border: 3px ridge #336699;
height: 20px;
background: rgba(0, 0, 170, .25);
border-radius: 20px;
text-align: center;
font-family: arial;
font-size: 15px;
color: #336699;
font-weight: bold;
padding: 2px 8px;
margin: 2px;
opacity: 0.0001;
float: left;
display: none;
}
#container {
width: 400px;
height: 100px;
border: 1px solid;
}
then adjust your JavaScript to the following:
$(function() {
var value,
tag,
cloned;
$('#tag').on('change keyup', function(e) {
value = $('#tag').val();
tag = value.split(',');
if (tag[1] != null && tag[0] !== '') {
cloned = $('.tag').first().clone().appendTo('#container');
$(cloned).find('span').html(tag[0]);
$(cloned).css({'opacity' : '1', 'min-width' : $(cloned).find('span').width() + 'px', 'display': 'inline-block'});
$('#tag').val('');
}
if (tag[1] != null && tag[0] === '') {
$('#tag').val('');
}
});
});
I've posted a functioning JSFiddle if you'd like to see it in action here: http://jsfiddle.net/autoboxer/opqcxm9k/
Cheers,
autoboxer
I wrote an alert bar like this:
alertmsg{
font-family:Arial,Helvetica,sans-serif;
font-size:135%;
font-weight:bold;
overflow: hidden;
width: 100%;
text-align: center;
position: fixed;
top: 0px;
left: 0px;
background-color: #fff;
height: 56px;
color: #000;
font: 20px/40px arial, sans-serif;
display:none;
padding-top:12px;
-webkit-box-shadow: 3px 3px 5px #888;
-moz-box-shadow: 3px 3px 5px #888;
box-shadow: 3px 3px 5px #888;
}
function alertbar(m, timeout){
if(!timeout){
var timeout = 3000;
}
var $alertdiv = $('<div id = "alertmsg"/>');
$alertdiv.text(m);
$alertdiv.bind('click', function() {
$(this).slideUp(200);
});
$(document.body).append($alertdiv);
$("#alertmsg").slideDown("slow");
setTimeout(function() { $alertdiv.slideUp(200) }, timeout);
return false
}
Pretty simple. I call alertbar("Go go go!"); to have this alert drop down.
However, it covers the body's page. I want it to sort of "push down" on the entire page (all the elements)....sort of like StackOverflow does it I guess.
I think it's the position: fixed that is your problem. This will place your element relative to the window and take it out of the normal flow.
Use position:static (or relative) and make sure the alertmsg element is at the top of the markup.
There's a couple things you must do:
Change the position CSS attribute of the "alert bar" to not be fixed and just be normal (remove that property).
Change your JavaScript to prepend the alertdiv, rather than append it. This will make it the first thing in the body.
$('body').prepend($alertdiv);
Slide your $alertdiv down normally.
Now something that you didn't take into account in your code is what happens when you run alertbar more than once. You'll append more than one to the body. If this is a concern, try doing something like this:
var exists = $('#alertmsg').length > 0;
var $alertdiv = exists ? $('#alertmsg') : $('<div id="alertmsg" />');
Now only prepend to the body if it doesn't exist already.
if (!exists)
$('body').prepend($alertdiv);
If you want to keep the position: fixed then just expand the body's top padding to the size of the alertbox.
$("#alertmsg").slideDown("slow", function() {
var paddingTopStr = "+" + $(this).outerHeight().toString() + "px";
$('body').css({ paddingTop: paddingTopStr });
});
You will also have to return the padding after:
setTimeout(function() {
var paddingTopStr = "-" + $(this).outerHeight().toString() + "px";
$('body').css({ paddingTop: paddingTopStr });
$alertdiv.slideUp(200) }, timeout);
}
Same for the click event.
You could wrap the rest of your content (to be pushed down) in a separate div and then insert your alert bar before it