changing link image on hover - javascript

my question today probably has an easy answer, however I have found a few working examples but can't seem to transfer it to my web page.
I am trying to use an image for a link, and would like the image to change when you hover over it. The link below is what I am trying to accomplish, but for whatever reason when I substitute my code from my page to it, it doesn't work.
EXAMPLE http://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_ev_onmouseover
I am completely lost now and just need a little help. Here is my code.
DEMO
function hoverImg(x) {
x.style.backgroundImage = "url(image/arrowBtnHover.png)"
x.style.transition = "ease 0.5s"
}
function normalImg(x) {
x.style.backgroundImage = "url(image/arrowBtn.png)"
}
#header {
background-color: #473D39;
height: 100%;
width: 100%;
display: table;
position: absolute;
z-index: 10;
}
#wrapper {
display: table-cell;
vertical-align: middle;
}
#header h1 {
text-align: center;
margin: 0px;
font-size: 80px;
padding-top: 5%;
font-weight: normal;
color: #FFF;
letter-spacing: 18px;
text-transform: uppercase;
}
#header h5 {
text-align: center;
color: #FFF;
margin: 15px 15px 50px;
font-weight: normal;
text-transform: uppercase;
font-size: 14px;
letter-spacing: 2px;
}
<div id="header">
<div id="wrapper">
<h1>Premier Webster</h1>
<h5>Local Web Design For The Profesional In You</h5>
<img onmouseover="hoverImg(this)" onmouseout="normalImg(this)" src="image/arrowBtn.png" />
</div>
</div>

Please take a look at https://jsfiddle.net/avzfdc2j/3/
It has been done using css with background image and transition
div.smile {
background-image: url("http://images.clipartpanda.com/stupidity-clipart-1320682287266972230curius_face.svg.hi.png");
background-size: 60px 60px;
height: 60px;
width: 60px;
cursor: pointer;
}
div.smile:hover {
background-image: url("http://images.clipartpanda.com/straight-face-clipart-black-and-white-smiley-face-hi.png");
transition: ease 0.5s;
}
<div class="smile"></div>

You should be changing the src attribute instead:
function hoverImg(x) {
x.src = "image/arrowBtnHover.png"
x.style.transition = "ease 0.5s"
}
function normalImg(x) {
x.src = "image/arrowBtn.png"
}
But I don't think that the transition will work with this.

Since it's an image, you need to change it's src property, not it's CSS.
function hoverImg(x) {
x.src = "image/arrowBtnHover.png"
x.style.transition = "ease 0.5s"
}
function normalImg(x) {
x.src = "image/arrowBtn.png"
}

Related

Why does a bit of my background gradient show at certain screen sizes?

I can't figure out why I'm getting this little bit of green when the window is an odd number of pixels wide. I think it has something to do with sub-pixel rendering, but I'm just not sure where the green is coming from. It's just the 2nd div too which is weird.
I have some script that is animating the BG of this div. I'm sure this is part of the issue, but I can't figure out why it's only happening to my 2nd div.
I tried to manually set the width of this div, but I was hoping it would be responsive and scale with the window size.
let currentStage = 1
function performAction(selectedStage) {
currentStage = selectedStage
let stages = document.body.getElementsByClassName('stage-flow-item')
let stageLines = document.body.getElementsByClassName('stage-flow-line')
console.log("selectedStage: " + selectedStage)
for (let stage of stages) {
if (stage.id > currentStage) {
stage.classList.remove('completed')
stage.classList.add('active')
} else {
stage.classList.remove('active')
stage.classList.add('completed')
}
}
for (let stageLine of stageLines) {
if (stageLine.id > currentStage) {
stageLine.classList.remove('lineCompleted')
stageLine.classList.add('lineActive')
} else {
stageLine.classList.remove('lineActive')
stageLine.classList.add('lineCompleted')
}
}
}
.stage-flow-container {
display: flex;
justify-content: space-between;
align-items: center;
height: 70px;
padding: 0 30px;
}
.stage-flow-item {
width: 70px;
height: 70px;
min-width: 70px;
border-radius: 50%;
background-color: #ddd;
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
color: #fff;
cursor: pointer;
}
.stage-flow-item.active {
background-color: #ddd;
}
.stage-flow-item.completed {
background-color: #6ab04c;
}
.stage-flow-line {
width: calc(100vw);
height: 6px;
background-color: #ddd;
/* default color */
background: linear-gradient(to left, #ddd 50%, #6ab04c 50%) right;
position: relative;
background-size: 200%;
transition: .5s ease-out;
}
.stage-flow-line.lineCompleted {
background-position: left;
background-color: #6ab04c;
}
.stage-flow-line.lineActive {
background-position: right;
background-color: #ddd;
}
<div class="stage-flow-container">
<div id=1 class="stage-flow-item" onclick="performAction(1)">1</div>
<div id=1 class="stage-flow-line"></div>
<div id=2 class="stage-flow-item" onclick="performAction(2)">2</div>
<div id=2 class="stage-flow-line"></div>
<div id=3 class="stage-flow-item" onclick="performAction(3)">3</div>
</div>
I'm not sure if this is on the right track, but I'd eliminate the odd 100vw width on the connectors and instead make them flex. I'd then remove the 200% background size multiplier. By setting the gradient points to 100% the problem is gone. I really don't know if this covers your use case, though.
I converted from background gradient to a pseudo-element solution for the color transition. I think it's simpler. You'd probably have to use CSS animations (as opposed to simple transitions) to make it work otherwise. Of course, you could apply the same principle to the stage items as well, implementing a delay to crate a consistent animation across the item and the line.
Note that duplicated ID values are invalid in HTML. They must be unique. I've refactored to use data attributes instead and an event listener instead of inline JavaScript.
const stageEls = document.querySelectorAll('.stage-flow-item')
const lineEls = document.querySelectorAll('.stage-flow-line')
let currentStage = 1
stageEls.forEach(el => {
el.addEventListener('click', () => {
performAction(el.dataset.stage)
})
})
function performAction(selectedStage) {
currentStage = selectedStage
for (let el of stageEls) {
if (el.dataset.stage > currentStage) {
el.classList.remove('completed')
el.classList.add('active')
} else {
el.classList.remove('active')
el.classList.add('completed')
}
}
for (let el of lineEls) {
if (el.dataset.stage > currentStage) {
el.classList.remove('lineCompleted')
el.classList.add('lineActive')
} else {
el.classList.remove('lineActive')
el.classList.add('lineCompleted')
}
}
}
.stage-flow-container {
display: flex;
align-items: center;
height: 70px;
padding: 0 30px;
}
.stage-flow-item {
width: 70px;
height: 70px;
min-width: 70px;
border-radius: 50%;
background-color: #ddd;
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
color: #fff;
cursor: pointer;
}
.stage-flow-item.active {
background-color: #ddd;
}
.stage-flow-item.completed {
background-color: #6ab04c;
}
.stage-flow-line {
flex: 1;
height: 6px;
background: #ddd;
position: relative;
}
.stage-flow-line::after {
position: absolute;
content: '';
top: 0;
left: 0;
width: 0;
height: 100%;
background: #6ab04c;
transition: all 0.5s ease-out;
}
.stage-flow-line.lineCompleted::after {
width: 100%;
}
<div class="stage-flow-container">
<div data-stage=1 class="stage-flow-item">1</div>
<div data-stage=1 class="stage-flow-line"></div>
<div data-stage=2 class="stage-flow-item">2</div>
<div data-stage=2 class="stage-flow-line"></div>
<div data-stage=3 class="stage-flow-item">3</div>
</div>

Css animation doesn't move object

I have a problem with a css animation im trying to add to each child inside a nav tag
I'm trying to create a moving stock panel
The weird thing about it is that if I add another css attribute like color it does work
Does anyone knows how to solve this
function DoAnimation(animation, a) {
var parent = a.parentElement
if (animation != null) {
parent.removeChild(a);
parent.appendChild(a);
console.log(1);
a.style.animationName = animation;
a.style.animationDuration = "2s";
}
}
#keyframes MoveStockTORIght {
from {
left: 0;
}
to {
transform: translateX(100px);
}
}
.SiteNav {
overflow: hidden;
text-align: center;
margin: auto;
text-align: center;
}
.SiteNav a {
gap: 10%;
padding: 1%;
}
<nav class="SiteNav" id="siteNavigantion">
MSFT 294.23
CLOV 8.06
LCID 22.87
SAVA 51.08
AAL 20.13
AMZN 3246.3
NFLX 627.04
GOOG 2776.95
AAPL 142.81
NVDA 206.95
</nav>
Why not just use Marquee?
.SiteNav {
overflow: hidden;
text-align: center;
margin: auto;
text-align: center;
}
.SiteNav a {
gap: 10%;
padding: 1%;
}
marquee a { text-decoration: none; color:green; }
<marquee class="SiteNav" id="siteNavigantion">
MSFT 294.23
CLOV 8.06
LCID 22.87
SAVA 51.08
AAL 20.13
AMZN 3246.3
NFLX 627.04
GOOG 2776.95
AAPL 142.81
NVDA 206.95
</marquee>

Console terminal with HTML

So far I managed to make this working fiddle. My problem now is that after I press enter to send the data to the server, i need to disable the edit on the current input and pass the focus to the next.
Also does anyone have any idea how do I make that text bliking thing in the project? https://bootsnipp.com/snippets/yNgQ1
PS: you need to press enter to start the console
var terminal = $('#terminal');
$(document).keypress(function(e) {
if (e.which === 13) {
e.preventDefault();
var stdin = $('.stdin').last().text();
console.log(stdin);
consoleInteration(stdin);
}
});
function consoleInteration(stdin) {
//RESULT FROM AJAX POST
result = "This is the output from the shell";
terminal.append('<br><div class="static">' + result + '</div><br>');
terminal.append('<div class="static"><span class="fa fa-arrow-right console-arrow"></span> ~ </div>');
terminal.append('<div class="stdin" id="stdin" contenteditable="true"></div>');
}
.terminal {
width: 100%;
padding: 4px;
background-color: black;
opacity: 0.7;
height: 650px;
color: #fff;
font-family: 'Source Code Pro', monospace;
font-weight: 200;
font-size: 14px;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
overflow-y: auto;
}
.terminal div {
display: inline-block;
}
.terminal .static {
color: #5ed7ff;
font-weight: bold;
}
.console-arrow {
color: #bde371;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="terminal" class="terminal">
</div>
You can disable edition by doing :
$('.stdin').last().removeAttr("contenteditable")
Then append the next line :
terminal.append('<div class="stdin" id="stdin" contenteditable="true"></div>')
Then select the last (newly added) line and set focus on it :
$('.stdin').last().focus()
What you need
First, .attr(): this allow you to change the contenteditable attribute (true/false).
Secondly .focus(): focus the desired element (just get the last .stdin with .last()).
Handling the cursor
In your div (the one that works like an input), you will make the text color as transparent with color: transparent, this way you will hide the cursor.But you need the text to show, so you will add text-shadow to help: text-shadow: 0 0 0 black.
To create the cursor, you will need one <div> after the other with editable content.
With everything set, you make use of .setInterval() with .css() to change the visibility and, at every change, .remove() the last cursor <div>.
var terminal = $('#terminal');
window.setInterval(function () {
if ($('#cursor').css('visibility') === 'visible') {
$('#cursor').css({
visibility: 'hidden'
});
} else {
$('#cursor').css({
visibility: 'visible'
});
}
}, 500);
$(document).keypress(function(e) {
if (e.which === 13) {
e.preventDefault();
var stdin = $('.stdin').last().text();
console.log(stdin);
consoleInteration(stdin);
}
});
function consoleInteration(stdin) {
$("#cursor").remove();
$(".stdin").last().attr("contenteditable", "false");
//RESULT FROM AJAX POST
result = "This is the output from the shell";
terminal.append('<br><div class="static">' + result + '</div><br>');
terminal.append('<div class="static"><span class="fa fa-arrow-right console-arrow"></span> ~ </div>');
terminal.append('<div class="stdin" id="stdin" contenteditable="true"></div>');
terminal.append('<div id="cursor"></div>');
$(".stdin").last().focus();
}
.terminal {
width: 100%;
padding: 4px;
background-color: black;
opacity: 0.7;
height: 650px;
color: #fff;
font-family: 'Source Code Pro', monospace;
font-weight: 200;
font-size: 14px;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
overflow-y: auto;
}
.terminal div {
display: inline-block;
}
.terminal .static {
color: #5ed7ff;
font-weight: bold;
}
.console-arrow {
color: #bde371;
}
.stdin{
color: transparent;
text-shadow: 0 0 0 white;
}
#cursor {
top: 10px;
width: 7px;
height: 15px;
margin-bottom: 0;
background: #5ed7ff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="terminal" class="terminal">
</div>

JavaScript induced style changes are not permanent

Okay, I change the appearance of links using JavaScript. When I change the content of a hard-coded link, it sticks in that the changed color and underlining remains when the cursor is not hovering above it. However, when the content of a DIV has been changed using JavaScript, the style changes do not stick.
Here is the HTML code:
<!doctype html>
<html>
<head>
<title>Bla bla</title>
<meta charset="UTF-8">
<link href="style/kim.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="scripts/Kim.js"></script>
</head>
<body>
<div class="wrapper">
<div class="main">
<div class="nav">
<div class="topNav">
<ul>
<li onClick="changeNav('design')">Design</li>
<li onClick="changeNav('code')">Programming</li>
<li onClick="changeNav('science')">Science</li>
<li onClick="changeNav('Kim')">Kim</li>
</ul>
</div>
<div id="subNav">
<script>changeNav("design");</script>
</div>
</div>
<div class="content">
<p id="mainText">Test</p>
</div>
</div>
</div>
</body>
</html>
Here is the JS code:
var topNavNames = ["design", "code", "science", "Kim"];
var subNavCode = ["<ul><li onClick=\"loadPHP('design/websites.php', 'sub0')\">Websites</li><li onClick=\"loadPHP('design/graphics.php', 'sub1')\">Graphics</li><li onClick=\"loadPHP('design/flash.php', 'sub2')\">Flash</li></ul>",
"<ul><li onClick=\"loadPHP('code/interactive.php', 'sub0')\">Interactive applets</li><li onClick=\"loadPHP('code/statistics.php', 'sub1')\">Statistics</li><li onClick=\"loadPHP('code/wings.php', 'sub2')\">Wings</li><li onClick=\"loadPHP('code/3D.php', 'sub3')\">3D</li></ul>",
"<ul><li onClick=\"loadPHP('science/3D.php', 'sub0')\">3D</li><li onClick=\"loadPHP('science/ssd.php', 'sub1')\">Sexual Size Dimorphism</li><li onClick=\"loadPHP('science/shape.php', 'sub2')\">Wing shape</li><li onClick=\"loadPHP('science/phylogenetics.php', 'sub3')\"><i>Drosophila</i> phylogenetics</li><li onClick=\"loadPHP('science/communitygenetics.php', 'sub4')\">Community Genetics</li><li onClick=\"loadPHP('science/biodiversity.php', 'sub5')\">Biodiversity</li></ul>",
"<ul><li onClick=\"loadPHP('Kim.php', 'sub0')\">Who is Kim?</li><li onClick=\"loadPHP('animals/horses.php', 'sub1')\">Horses</li><li onClick=\"loadPHP('animals/birds.php', 'sub2')\">Birds</li><li onClick=\"loadPHP('private/outdoors.php', 'sub3')\">Outdoors</li><li onClick=\"loadPHP('contact.php', 'sub4')\">Contact</li></ul>"];
function changeNav(target) {
for (var i = 0; i<topNavNames.length; i++) {
if (target == topNavNames[i]) {
document.getElementById("subNav").innerHTML=subNavCode[i];
document.getElementById(topNavNames[i]).style.color="#F7EDAA";
document.getElementById(topNavNames[i]).style.borderBottom="thin solid #F7EDAA";
}
else {
document.getElementById(topNavNames[i]).style.color="#EEE";
document.getElementById(topNavNames[i]).style.borderBottom="thin solid #111";
}
}
}
function loadPHP(url, target) {
for (var i = 0; i<10; i++) {
if(document.getElementById(target)!=null) {
if (("sub"+i) == target) {
document.getElementById(target).style.color="#F7EDAA";
document.getElementById(target).style.borderBottom="thin solid #F7EDAA";
}
else {
document.getElementById(target).style.color="#EEE";
document.getElementById(target).style.borderBottom="thin solid #111";
}
}
}
}
if I subsequently remove the:
else {
document.getElementById(target).style.color="#EEE";
document.getElementById(target).style.borderBottom="thin solid #111";
}
from the loadPHP function, it changes the style, but does not reset it when the next link is clicked.
I observed this behavior in FireFox, Internet Exploder and Chrome.
Added: CSS code:
body {
background-color: #111111;
color: #DDD;
font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif;
}
.wrapper {
overflow: auto;
}
.banner {
float: left;
position: relative;
width: 100px;
}
.main {
position: relative;
width: 80%;
left: 25px;
font-size: 14px;
font-weight: normal;
}
a {
text-decoration: none;
color: #EEE;
}
a:hover {
border-bottom: thin solid #F7EDAA !important;
color: #F7EDAA !important;
}
.topNav {
height: 45px;
position: relative;
left: 100px;
font-size: large;
border: thin solid #111;
}
#subNav {
height: 45px;
position: relative;
left: 100px;
top: 2px;
border: thin solid #111;
}
.topNav li, #subNav li {
float: left;
margin: 10px 15px;
}
.topNav ul, #subNav ul {
list-style: none;
padding: 0px 0px;
margin: 0px 0px;
position: relative;
left: -100px;
}
.content {
position: relative;
left: 15px;
padding: 0px 0px;
margin: 0px 0px;
}
.content p {
padding: 5px 5px;
margin: 10px 15px;
left: -100px;
}
In my opinion you´re using the wrong technology to achieve your goal. What you need to do is to write your styles in a css stylesheet, and then add or remove classes to your elements using js if you want. (You can also do this through something called specificity, a little far ahead from the scope of your question)
Also think that if there is some bug in your script, or a third party script called in your page, JS may break and it won´t process your styling changes.
So, add the basic styling to your elements through css in the initial markup, so you will be sure that your elements will have always a basic styling, and then if you want use the equivalent to .addClass or removeClass jQuery methods.
In that way you will be always sure that your frontend will have always a safe styling, won´t break if js is not loaded, and separation of concerns will be properly implemented.
Regards.
I figured it out. The following code does not do the right thing:
function loadPHP(url, target) {
for (var i = 0; i<subNavNames.length; i++) {
if (target == subNavNames[i]){
document.getElementById(target).className="selected";
} else {
document.getElementById(target).className="notSelected";
}
}
While this code does produce the right result:
function loadPHP(url, target) {
for (var i = 0; i<subNavNames.length; i++) {
if (target == subNavNames[i]) {
document.getElementById(subNavNames[i]).className="selected";
} else {
document.getElementById(subNavNames[i]).className="notSelected";
}
}
The difference is that in the first example, and in the example of the original question, I use the variable passed on in the method (target), to find the element. In the second, I use the appropriate element from a array that I have added to the list. I am not sure WHY this behaves differently, but it does.

Optimize jQuery code

I've written this jQuery code that fades in a overlay with some links over an image. What i found out is that it is painfully slow when I add like 10 of these images. I would really appreciate some tips and tricks on how to make this code faster.
If you have some tips for my HTML and CSS that would be great too ;)
jQuery code
$(document).ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").hover(
function () {
$(this).children(".download").fadeTo("fast", 1);
$(this).children(".hud").fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
All the code
<style type="text/css">
a:active {
outline:none;
}
:focus {
-moz-outline-style:none;
}
img {
border: none;
}
#backgrounds {
font: 82.5% "Lucida Grande", Lucida, Verdana, sans-serif;
margin: 50px 0 0 0;
padding: 0;
width: 585px;
}
.thumb {
margin: 5px;
position: relative;
float: left;
}
.thumb img {
background: #fff;
border: solid 1px #ccc;
padding: 4px;
}
.thumb div {
display: none;
}
.thumb .download {
color: #fff;
position: absolute;
top: 0;
left: 0;
z-index: 999;
padding: 0 10px;
}
.thumb .download h3 {
font-size: 14px;
margin-bottom: 10px;
margin-top: 13px;
text-align: center;
}
.thumb .download a {
font-size: 11px;
color: #fff;
text-decoration: none;
font-weight: bold;
line-height: 16px;
}
.thumb .download a:hover {
text-decoration: underline;
}
.thumb .download .left, .thumb .download .right {
width: 44%;
margin: 0;
padding: 4px;
}
.thumb .download .left {
float: left;
text-align: right;
}
.thumb .download .right {
float: right;
text-align: left;
}
.thumb img, .thumb .hud {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.thumb .hud {
width: 100%;
height: 110px;
position: absolute;
top: 0;
left: 0;
background: #000;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").hover(
function () {
$(this).children(".download").fadeTo("fast", 1);
$(this).children(".hud").fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
</script>
<div id="backgrounds">
<div class="thumb">
<div class="download">
<h3>Download wallpaper</h3>
<p class="left">
1024x768
1280x800
1280x1024
</p>
<p class="right">
1440x900
1680x1050
1920x1200
</p>
</div>
<div class="hud"></div>
<img alt="image" src="thumb.jpg"/>
</div>
</div>
I got it to respond a little better by simply changing the following within the hover(..):
function () {
$(".download", this).fadeTo("fast", 1);
$(".hud", this).fadeTo("fast", 0.7);
},
function () {
$(".download, .hud", this).fadeTo("fast", 0);
}
The biggest difference comes from only applying the hoverout effect to the event target, no need to reapply to all your divs on the page.
I've put your code into a test page and to be perfectly honest, even with thirty or so .thumb divs it seemed ok - certainly responsive enough to use from my end. Sliding the mouse over a bunch of them means I have to wait for the rollover effect to go through them all which takes a while until it gets to the one I've actually stopped on, but surely that was what you wanted given that you're using 'hover' rather than 'click' (which would certainly remove any speed issues).
I'm not using actual images in my test page, just getting the alt text, so my best current guess would be to make sure all images you're loading are as small filesize as you can possibly make them.
Pre-Select MORE
Good job preselecting the div. Try this way so that it pre-selects the fade in elements as well instead of doing it on hover:
$().ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").each(function() {
var download = $(this).children(".download");
var hud = $(this).children(".hud");
$(this).hover(
function () {
download.fadeTo("fast", 1);
hud.fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
});
try removing the
:focus {
-moz-outline-style:none;
}
and see what happens

Categories