I have the following js code:
<style>
<!--
body
{
font-family: "century schoolbook", serif;
font-size: 20px;
}
.hidden
{
display: none;
color: #000;
background: #FFFFFF;
}
.unhide
{
display: block;
color: #000;
}
a.unhide
{
text-decoration: none;
}
a.unhide:hover
{
text-decoration: underline;
}
.unhide:hover
{
background: #FFE5B4;
padding: 3px 8px;
display: table-row;
transition: background .25s ease-in-out;
-moz-transition: background .25s ease-in-out;
-webkit-transition: background .25s ease-in-out;
}
-->
</style>
<script type="text/javascript">
function unhide(divID) {
var item = document.getElementById(divID);
if (item) {
item.className = (item.className == 'hidden') ? 'unhide' : 'hidden';
}
}
</script>
...
<div class="conBoxcities">
<class id="info">
<a href="javascript:unhide('cityname');" class="unhide">
This is really a js link with a city name. Clicking brings down information about
that city.
</a>
</class>
<class id="info">
<div id="cityname" class="hidden">
This is where the content of the above link appears. It is just an info blurb,
basically.
This js script works here. On the other page it does not. I believe I messed up
somewhere in my classes...please help
</div>
</class>
</div>
The above code works perfectly well on a "bare" php page
When I incorporate it into my main page, the js links no longer function. I believe i may have a mistake in my arrangement (admittedly, classes and ids still confuse me).
This is the page where the link appears, but does not work.
Please help...
The problem is that in your "live" page you have redefined the function unhide with this code:
function unhide(divID) {
var item = document.getElementsByClassName(divID)[0];
console.log(item);
console.log(item.className == divID + ' hide');
if (item) {
item.className = (item.className == divID + ' hide') ? divID + ' unhide' : divID + ' hide';
}
}
If you remove, our comment out that code, everything works as expected.
Related
I have This simple website that i need to make it change from light theme to dark theme, the light theme works fine, but the dark theme only changes its button properly because when i click in the button to change the "body" elements should change its class from "light-theme" to "dark-theme", instead it changes to "light-theme dark-theme"
here's HTML
`
<body class="light-theme">
<h1>Task List</h1>
<p id="msg">Current tasks:</p>
<ul>
<li class="list">Add visual styles</li>
<li class="list">add light and dark themes</li>
<li>Enable switching the theme</li>
</ul>
<div>
<button class="btn">Dark</button>
</div>
<script src="app.js"></script>
<noscript>You need to enable JavaScript to view the full site</noscript>
Heres CSS
:root {
--green: #00FF00;
--white: #FFFFFF;
--black: #000000;
}
.btn {
position: absolute;
top: 20px;
left: 250px;
height: 50px;
width: 50px;
border-radius: 50%;
border: none;
color: var(--btnFontColor);
background-color: var(--btnBg);
}
.btn:focus {
outline-style: none;
}
body {
background: var(--bg);
}
ul {
font-family: helvetica;
}
li {
list-style: circle;
}
.list {
list-style: square;
}
.light-theme {
--bg: var(--green);
--fontColor: var(--black);
--btnBg: var(--black);
--btnFontColor: var(--white);
}
.dark-theme{
--bg: var(--black);
--fontColor: var(--green);
--btnBg: var(--white);
--btnFontColor: var(--black);
}
and heres JavaScript
'use strict';
const switcher = document.querySelector('.btn');
switcher.addEventListener('click', function () {
document.body.classList.toggle('dark-theme')
var className = document.body.className;
if(className == "light-theme") {
this.textContent = "Dark";
} else {
this.textContent = "Light";
}
console.log('current class name: ' + className);
});
`
I tried to change some things in css but later found that the problem might be in the javascript, but my code is exactly as the code in my course is.
when i click in the button to change the "body" elements should change its class from "light-theme" to "dark-theme", instead it changes to "light-theme dark-theme"
That's indeed true - your JS code is only toggling the class "dark-theme" and does nothing with the "light-theme" class.
So a simple fix would be to toggle both classes:
switcher.addEventListener('click', function () {
document.body.classList.toggle('dark-theme')
document.body.classList.toggle('light-theme'); // add this line
var className = document.body.className;
if(className == "light-theme") {
this.textContent = "Dark";
} else {
this.textContent = "Light";
}
console.log('current class name: ' + className);
});
But you could simplify your code because you really don't need 2 classes here. If light theme is the default, just remove the light-theme class and all its CSS rules, and apply those to body instead. The .dark-theme rules will override these when the class is set, but not otherwise.
So I have been working on a dropdown menu to select a language. Thats the code:
HTML
<div class="language_section">
<span id="select-lang-btn"><img class="language_flag" src="en.svg"><a id="selected-lang">English</a></span>
<ul class="language_dropdown" id="language_dropdown">
<li onclick="show('English')"><img class="language_flag" src="en.svg">English</li>
<li onclick="show('Germany')"><img class="language_flag" src="de.svg">German</li>
<li onclick="show('Spanish')"><img class="language_flag" src="es.svg">Spanish</li>
</ul>
</div>
CSS
<style>
body {
background-color: #339699;
}
#select-lang-btn {
outline: none;
cursor: pointer;
}
.language_dropdown {
display: none;
align-items: center;
background-color: white;
width: 300px;
}
li {
cursor: pointer;
list-style: none;
}
.language_text {
color: black;
text-decoration: none;
}
.language_flag {
width: 32px;
}
</style>
JS
<script>
var button = document.getElementById('select-lang-btn');
button.onclick = function() {
var div = document.getElementById('language_dropdown');
if (div.style.display === 'block') {
div.style.display = 'none';
}
else {
div.style.display = 'block';
}
};
function show(anything) {
document.getElementById("selected-lang").innerHTML = anything
document.getElementById('language_dropdown').style.display = 'none';
}
</script>
However there is one problem with my code. When I select a new language, the selected language appears as a text, but the image does not change. That is because I created a function called show which only manages to change the text. Now I have been researching and thinking a lot but still didnt find a solution. Then I had an Idea if i could change the image by the innertext -> For Example if Germany is visible then the image automatically changes to Germanys Flag. But it seems like there is nothing about that methode online. Is that possible or is there a cleaner way to solve this issue?
I have the following Quiz written using Vue.js where everything works like a charm...
except one thing, which I can't find a solution,
is it my code causing this bug? or I need approach it differently?
Update: now that I have added unique names for each element, as one of the answers suggest, The second menu item is always selected by default on page load... any hint on how to overcome this issue?
<script>
// Create a quiz object with a title and two questions.
// A question has one or more answer, and one or more is valid.
var quiz = {
"title":"Quizorama",
"questions":[
{
"text":"Lalala",
"audio":"TextTo-1-1.mp3",
"responses":[
{
"text":"Incorrect"
},
{
"text":"Incorrect"
},
{
"text":"Correct",
"correct":true
}
]
},
{
"text":"Something",
"audio":"57633709.mp3",
"responses":[
{
"text":"Correct",
"correct":true
},
{
"text":"Incorrect"
},
{
"text":"Incorrect"
}
]
},
{
"text":"Question",
"audio":"57633709.mp3",
"responses":[
{
"text":"Correct",
"correct":true
},
{
"text":"Incorrect"
},
{
"text":"Incorrect"
}
]
}
]
};
</script>
<div class="wrapper" id="page-wrapper">
<div class="centered-content " id="content" tabindex="-1">
<div class="row">
<main class="site-main" id="main">
<div id="app">
<h1>{{ quiz.title }}</h1>
<!-- index is used to check with current question index -->
<div v-for="(question, index) in quiz.questions">
<!-- Hide all questions, show only the one with index === to current question index -->
<transition name="slide-fade">
<div v-show="index === questionIndex">
<h2>{{ question.text }}</h2>
<audio width="450" controls :src="question.audio"></audio>
<ul>
<li v-for="response in question.responses"
v-bind:correctOrNot="response.correct"
v-bind:class="{ active: isActive }">
<label>
<input type="radio"
v-bind:value="checkResponse(response.correct)"
v-bind:name="nameMethod(index ,response.text,
questionIndex)"
v-model="userResponses[index]"
> {{response.text}}
</label>
</li>
</ul>
<!-- The two navigation buttons -->
<!-- Note: prev is hidden on first question -->
<!-- <button v-if="questionIndex > 0" v-on:click="prev">
otra oportunidad?
</button> -->
<button v-on:click="next">
Next pleeeeease!
</button>
</div>
</transition>
</div>
<transition name="slide-fade">
<div v-show="questionIndex === quiz.questions.length">
<h3>
yer results are da following bro:
</h3>
<p class="puntaje">
{{ score() }}
</p>
</div>
</transition>
</div>
<script>
new Vue({
el: '#app',
data: {
quiz: quiz,
// Store current question index
questionIndex: 0,
// An array initialized with "false" values for each question
// It means: "did the user answered correctly to the question n?" "no".
userResponses: Array(quiz.questions.length).fill(false),
isActive: false,
},
// The view will trigger these methods on click
methods: {
checkResponse: function(response){
let checkResponseValue = response;
if (response == true){
return true;
} else {
return false;
}
},
nameMethod: function(index, responseText, questionIndex){
var index = index;
var questionIndexValue = questionIndex
var responseText = responseText;
var name = index + responseText+'_'+ questionIndexValue;
return name;
},
next: function() {
console.log(this);
this.isActive = true;
setTimeout(() => {
// move to next question
this.questionIndex++;
this.isActive = false;
}, 3000);
},
updateMessage: function () {
this.message = 'updated';
},
// Go to previous question
prev: function() {
this.questionIndex--;
},
editModal: function(id){
console.log(id);
},
// Return "true" count in userResponses
score: function() {
let scorePercent = Math.round(this.userResponses.filter(function(val) { return val }).length * 100 / this.questionIndex);
let newResult;
if(scorePercent == 0 ){
newResult = "you suck , not even one good response mate ";
return newResult
}
if(scorePercent < 30){
newResult = scorePercent + "% Was Good, so you need to practice more mate";
return newResult
}
if(scorePercent < 70){
newResult = scorePercent + "% yar a ducking star but there is more to improve";
return newResult
}
if(scorePercent == 100){
newResult = scorePercent + "% you are a godlike creature made flesh";
return newResult
}
}
}
});
</script>
<style>
p.puntaje {
font-size: 25px;
color: #333333;
margin-bottom: 40px;
background: #fce373;
padding: 13px;
border-radius: 100px;
text-align: center;
}
main#main {
margin: auto;
}
#app h1 {
font-size: 66px;
font-weight: 900;
color: #b1b1b1;
}
#app h2 {
font-size: 125px;
color: #a282bb;
}
#app ul {
list-style: none;
padding: 0;
}
/* Enter and leave animations can use different */
/* durations and timing functions. */
.slide-fade-enter-active {
transition: all 0.5s ease;
transition-delay: 2s;
}
.slide-fade-leave-active {
transition: all 0.5s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter
/* .slide-fade-leave-active below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
transition: all 0.5s ease;
}
#app button {
background: #00BCD4;
width: 200px;
margin-bottom: 30px;
border-radius: 100px;
font-size: 17px !important;
padding: 7px 17px;
border: none;
}
#app li label {
font-size: 25px;
background: #fff2b6;
border-radius: 100px;
padding-left: 17px;
padding-right: 17px;
margin-top: 16px;
padding-top: 5px;
transition: all 0.5s ease;
}
#app li label:hover{
background: #fce372;
cursor:pointer;
transition: all 0.5s ease;
}
li.active label {
background: #ee734c !important; transition: all 0.5s ease;
}
li[correctOrNot="true"].active label {
background: #9ad18b !important; transition: all 0.5s ease;
}
.slide-fade-leave-to
/* .slide-fade-leave-active below version 2.1.8 */ {
transform: translateX(50px);
opacity: 0;
transition: all 0.5s ease;
}
</style>
This is a simple HTML problem. You define the radio buttons with the response.correct value, which is undefined for the incorrect options and also identical for both (no matter if it is null or false).
Your output might be like this:
<input type="radio" name="index">Incorrect
<input type="radio" name="index">Incorrect
<input type="radio" name="index" value="true">Correct
If you have a group of radio buttons and several have the same value (or none), these are basical the same input. Try to define a unique value for each radio button with the same name.
I have this sidebar which expands or collapses on a button click. Now I've successfully stored it's state in localStorage and it's working fine except there's a slight issue.
When the page loads and there is no state saved in localStorage, the sidebar collapses for a split second and expands. Expand is supposed to be the default state when there is no state stored in localStorage. I don't want it to collapse first and then expand. I just want the page to load with the sidebar expanded.
I have been trying to solve the issue with my own code. But it didn't work then I combined my code with of of SO's posts. It still doesn't work.
Full Code: Codepen
Here's the code(please note that localStorage won't work in SO):
$('document').ready(function() {
if (typeof window.isMinified === "undefined") {
window.isMinified = false;
}
const body = $('#body');
$("#sidebar-toggler").on("click", function () {
if (window.isMinified === false) {
// localStorage.setItem('menu-closed', !$(body).hasClass("sidebar-minified"));
body.removeClass("sidebar-minified-out").addClass("sidebar-minified");
window.isMinified = true;
} else {
// localStorage.setItem('menu-closed', !$(body).hasClass("sidebar-minified"));
body.removeClass("sidebar-minified").addClass("sidebar-minified-out");
window.isMinified = false;
}
});
const state = // localStorage.getItem('menu-closed');
if (state === null) {
$(body).removeClass('sidebar-minified');
} else {
const closed = state === "true" ? true : false;
if (!closed) {
$(body).removeClass('sidebar-minified');
}
}
});
#body {
background: #fff;
transition: all 0.3s;
}
aside.left-sidebar{
background-color: #2c0963;
height: 100vh;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
transition: width .3s ease-in;
}
.sidebar-minified .left-sidebar {
width: 75px;
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body id="body" class="sidebar-minified sidebar-minified-out">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
You can minimize the the flashing effect, by telling the browser to repaint just only one time, in one shot. BUT there will be always one initial size for Your sidebar: the size which has been defined inside Your markup.
In my example, I am using two Observers to track the style and size changes. Please, note the initial sidebar width. You may set the initial sidebar width equal to 0, or let it unassigned, or maybe You can style it the same size as Your expanded sidebar, but there will be always an initial repaint.
Finally, I strongly believe You need to remove the two initial classes from the body.
$(function() {
/* avoid SO unsecure operation error */
var storage = (function () {
return {
setItem: function(k,v){try{return localStorage.setItem(k,v)}catch(e){return !1}},
getItem: function(k){try{return localStorage.getItem(k)}catch(e){return null}}
};
})();
log("jQuery DOM Ready");
$("#sidebar-toggler").on("click", function() {
var isMinified = !$("body").hasClass("sidebar-minified-out");
$("body")
.toggleClass("sidebar-minified", !isMinified)
.toggleClass("sidebar-minified-out", isMinified);
storage.setItem('menu-closed', +!isMinified);
});
var closed = +storage.getItem('menu-closed');
log('Closed: ' + !!closed);
$("body")
.addClass(closed ? "sidebar-minified" : "sidebar-minified-out")
.css({"visibility": "visible"});
});
body {
background: #fff;
transition: all 0.3s;
}
aside.left-sidebar{
background-color: #2c0963;
height: 100vh;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
transition: width .3s ease-in;
}
.sidebar-minified .left-sidebar {
width: 75px;
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sidebar State</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body style="visibility: hidden;">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
<div id="log" style="position:absolute;top:0;right:0;padding:1em;"></div>
<script>
/* only debug functions inside this script block */
function log(msg) {
$("<div>").appendTo("#log").text(msg);
}
var mo = new MutationObserver(function (ml){
for(var m of ml) {
if (m.type == 'attributes') log('Body ' + m.attributeName + ' changed');
}
});
mo.observe(document.getElementsByTagName('body')[0], {attributes: true});
var ro = new ResizeObserver(function (rl){
for(var r of rl) {
var w = r.contentRect.width;
if(w<=75 || w>=180) log('Sidebar width: ' + r.contentRect.width);
}
});
ro.observe(document.getElementsByClassName("left-sidebar")[0]);
</script>
</body>
</html>
EDIT:
If You look at the messages logged by the Observers, You will notice that there is always a repaint, as mentioned above.
After reading this solution of Your previous question: Dark mode flickers a white background for a millisecond on reload I believe You can implement Your Sidebar toggler the same way.
Instead of applying the CSS class to the body, You can apply it to the html. Here is the full code:
HTML
<!DOCTYPE html>
<html>
<head>
<script>
/* Render blocking script */
var c = +localStorage.getItem('menu-closed');
document.documentElement.classList.add(c ? 'sidebar-minified' : 'sidebar-minified-out');
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
</html>
JS
$(function() {
$("#sidebar-toggler").on("click", function (e) {
var isMinified = !$("html").hasClass("sidebar-minified-out");
$("html")
.toggleClass("sidebar-minified", !isMinified)
.toggleClass("sidebar-minified-out", isMinified);
localStorage.setItem('menu-closed', +!isMinified);
});
});
Your CSS will remain untouched beside of a small change (I just only removed the #body id).
Now, if You compare the Observed changes, You will notice that the second solution, which is using the blocking JS script in head, is showing only the initial Sidebar size, i.e.: the initial repaint is gone:
1st solution 2nd solution
==============================================================
Sidebar width: 601 Closed: false
jQuery DOM Ready Sidebar width: 180
Closed: false jQuery DOM Ready
Body class changed
Body style changed
Sidebar width: 180
(Credits: Roko C. Buljan):
More information:
The debug functions in my first example are used just only to depict the sequence of the resize and restyle events inside the browser.
Here is some documentation about that Observers:
MutationObserver
ResizeObserver
It is the transition from the css that let the sidebar expand. If you remove the transistion you will see that the sidebar ist immediately expanded on page load. So for the first time you should set CSS classes without transitions.
You could disable the transition via Javascript and enable it again for the click event:
jsfiddle demo
First remove the classes in the body tag:
<body id="body" class="">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
Just a few lines to change in the javascript:
$('document').ready(function() {
if (typeof window.isMinified === "undefined") {
window.isMinified = false;
}
const body = $('#body');
$("#sidebar-toggler").on("click", function () {
document.querySelector('.left-sidebar').style.transition = 'inherit';
if (window.isMinified === false) {
localStorage.setItem('menu-closed', !body.hasClass('sidebar-minified'));
body.removeClass('sidebar-minified-out').addClass('sidebar-minified');
window.isMinified = true;
} else {
localStorage.setItem('menu-closed', !body.hasClass('sidebar-minified'));
body.removeClass('sidebar-minified').addClass('sidebar-minified-out');
window.isMinified = false;
}
});
const state = localStorage.getItem('menu-closed');
if (state === null) {
body.addClass('sidebar-minified');
} else {
const closed = state === "true" ? true : false;
if (!closed) {
body.addClass('sidebar-minified-out');
document.querySelector('.left-sidebar').style.transition = 'none';
}
else {
body.addClass('sidebar-minified');
}
}
});
The important changes in above code are two things:
// in the clickevent section: change the transistion to default behaviour
document.querySelector('.left-sidebar').style.transition = 'inherit';
Set the right class depending on state and disable transition:
// ...
if (state === null) {
body.addClass('sidebar-minified');
} else {
// ...
if (!closed) {
body.addClass('sidebar-minified-out');
document.querySelector('.left-sidebar').style.transition = 'none';
}
else {
body.addClass('sidebar-minified');
}
}
*** Update ***
I refactored the code and optimized it a bit. fiddle
HTML:
<body id="body">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
CSS:
#body {
background: #fff;
transition: all .3s;
}
aside.left-sidebar {
background-color: #2c0963;
height: 100vh;
width: 75px;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
}
.sidebar-transitions .left-sidebar {
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
JS:
$('document').ready(function() {
$("#sidebar-toggler").on("click", function () {
localStorage.setItem('menu-closed', $('#body').hasClass('sidebar-minified-out'));
$('#body').addClass('sidebar-transitions').toggleClass('sidebar-minified-out');
});
localStorage.getItem('menu-closed') === "true" ? $('#body').removeClass('sidebar-minified-out') : $('#body').addClass('sidebar-minified-out');
});
How about moving the animation to a separate class lets say
.sidebar-animated{
transition: width: 0.3s ease-in;
}
and removing it from anywhere else and then adding that class via timeout, so it gets added after the transition is done, you can use useTimeout with 0 seconds, like so,
setTimeout(() => {
$('aside').addClass('sidebar-animated')
},0)
Plus CSS uses Specificity to reach its element, so
.sidebar-minified-out .left-sidebar {
width: 180px;
}
.sidebar-minified .left-sidebar {
width: 75px;
}
Should be changed to this.
.sidebar-minified .left-sidebar {
width: 75px;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
}
because when you have both on the same element, it will take the later because they have the same specificity rule, give it a last shot, thats the last resort for me :D.
thats enough to make it work
https://codepen.io/menawer_cpe/pen/qBZbEdw
here is a working example,
Note: you have an issue with managing state when the sidebar collapsed at first, but thats something related to how you deal with the state.
Why useTimeout with 0? because it pushes the execution to what is called "event loop" making sure it executes after all javascript normal code is executed.
You can try this :
$('document').ready(function() {
if (window.isMinified === undefined) {
window.isMinified = false;
}
const body = $('#body');
$("#sidebar-toggler").on("click", function() {
$('#body .left-sidebar').removeAttr("style");
if (window.isMinified === false) {
body.removeClass("sidebar-minified-out").addClass("sidebar-minified");
window.isMinified = true;
} else {
body.removeClass("sidebar-minified").addClass("sidebar-minified-out");
window.isMinified = false;
}
});
var firstTime = true;
var sidebar = $('#body aside.left-sidebar');
const state = !(null); //localStorage.getItem('menu-closed');
if (state === null) {
$(body).removeClass('sidebar-minified');
} else {
if (firstTime) {
sidebar.css('transition', 'none');
firstTime = false;
}
const closed = state === "true" ? true : false;
if (!closed) {
$(body).removeClass('sidebar-minified');
}
}
});
#body {
background: #fff;
transition: all 0.3s;
}
aside.left-sidebar {
background-color: #2c0963;
height: 100vh;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
transition: width .3s ease-in;
}
.sidebar-minified .left-sidebar {
width: 75px;
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body id="body" class="sidebar-minified sidebar-minified-out">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
I have an image inside of a DIV. When a user hovers over the image I would like a white box with 65% opacity to come up from the bottom of the image that would only cover a about 30% of the bottom of the image. In that box would be text that say something like "+ Order Sample" and when the user clicks on that box it would be added to the cart.
Easy enough to handle the adding to cart part it's the css and possibly javascript necessary to make this happen that I'm struggling with. Can someone get me started? Here's what I have so far. This includes edits from first answer.
foreach($array as $key => $value) {
$imgsrc = $value['option_value']. ".jpg" ;
$option_name = $value['option_name'] ;
$fullname = $value['quality'] . " " . $value['color'] ;
$cbpg = $value['cbpg'] ;
$space = $value['space'] ;
print "<div class='colorbook-color-guide-div' onmouseover='showOrderSample();'>" ;
print "<img class='colorbook-color-guide-image js-color-option js-tooltip' nopin='nopin' data-tooltip-content='$option_name' src='/images/uploads/colors/$imgsrc' alt='$option_name' >" ;
print "<div id='orderSample' onclick='hideOrderSample();alert(\"order sample\");' ><b>+ Order Sample</b></div>" ;
print "<p class='colorbook-color-subtitle'>$fullname</p>" ;
//print "<p class='colorbook-color-subtitle'>$cbpg $space</p>" ;
print "</div>" ;
}
And here's the CSS I have.
.colorbook-color-guide-div {
width: 176px;
min-height: 107px;
margin-bottom: 2px;
margin-right: 21px;
cursor: pointer;
float:left;
text-align:center;
}
.colorbook-color-guide-image {
width: 176px;
min-height: 86px;
}
.colorbook-color-subtitle {
font-family: HelveticaNeueLT-Light, Museo-500, Helvetica, Arial, sans-serif;
font-style: normal ;
font-weight:600 ;
font-size: 13px ;
font-size: 1.3rem ;
color: #929496 ;
margin-top: -3px;
}
#orderSample {
height:0px;
top:100px;
width:176px;
display:block;
overflow:hidden;
background:white;
opacity:.65;
}
And the JavaScript
function showOrderSample() {
var element = document.getElementById("orderSample");
element.style.height = "30px";
element.style.top = "70px";
}
function hideOrderSample() {
setTimeout(function () {
document.getElementById("orderSample").style.height = "0px";
}, 500);
}
My example uses just JavaScript, html and fixed sizes but it does what was asked for.
Look at the Fiddle here:
https://jsfiddle.net/ag7to93q/9/
<script>
function showOrderSample(element) {
element.children[1].style.height = "30px"; // access the second child of the div element
element.children[1].style.top = "70px";
}
function hideOrderSample(element, event) {
if (event && event.target.classList.contains("hoverDiv")) {
alert("buy buy buy!");
setTimeout(function () {
element.children[1].style.height = "0px";
}, 200);
}
else {
// do something here
}
}
</script>
<div style="position:absolute;top:50px;left:50px;width:200px;height:100px;background:green;" onmouseenter="showOrderSample(this);" onclick="hideOrderSample(this, event);" onmouseleave="hideOrderSample(this, event);" >
<img style="position:absolute;height:100px;width:200px;" src="https://jsfiddle.net/img/logo.png" ></img>
<div id="orderSample" class="hoverDiv" style="position:absolute;height:0px;top:100px;width:200px;display:block;overflow:hidden;background:white;opacity:.65;"><b>+ Order Sample<b>
</div>
</div>
Look at the following jsFiddle. Keep in mind accurate answers require more detail, so based on your question I came up with an approximate (hopefully as accurate as possible) response. Let me know if it helped in getting you closer to where you want to be, we can work on something closer if needed.
HTML:
<div class="popup-overlay--gray">a</div>
<a class="popup-btn__open" href="#">Open Popup</a>
<div>
<a class="popup-btn__close" href="#">Close Popup</a>
<img class="popup" src="http://placehold.it/300x300"/>
</div>
CSS
[class*="popup-btn"] { text-decoration: none; color: white; background-color: gray; }
.popup-btn__close { top: 0; right: 0; }
.popup { display: none; }
.popup-overlay--gray { position: absolute: width: 100%; height: 100%; background-color: #333; opacity: 0.7; z-index: 1000; }
jQuery 2.1.3
var timer,
delay = 500;
$(".show-popup").hover(function(){
// on mouse in, start a timeout
timer = setTimeout(function(){
// showing the popup
$('.popup').fadeIn(500);
}, delay);
}, function() {
// on mouse out, cancel the timer
clearTimeout(timer);
});
Fiddle
Jquery solution
$('document').ready(function () {
$('#myimage').hover(
//hover in
function () {
$("#backgroundDIv").css('z-index', 101);
},
//hover out
function () {
$("#backgroundDIv").css('z-index', 99);
});
});
HTML
<div id="mainDiv">
<img id="myimage" src="http://i48.fastpic.ru/big/2013/0606/5c/aa5f8d03b34f8e79f18c07343573bc5c.jpg" />
<input type="text" value="add me" id="backgroundDIv"/>
</div>
CSS
#myimage {
z-index:100;
position: absolute;
}
#backgroundDIv {
z-index=99;
position: absolute;
top:200px;
background-color:#fff200;
opacity:0.4;
}