What I am trying to do is, that when the user clicks on the search button, the search bar displays. But for some reason, it's just not working and I have no idea, why? I double-checked on
https://www.w3schools.com/jsref/event_onclick.asp just to make sure I am doing it right but to no avail. I tried the add.eventlistner that does not work, because it sees the button as null where the onclick="showBar()" should see the button, in JS.
HTML
<button onclick="showBar()" class="btn btn-outline-success" type="submit">
Search
<img src="./images/iconmonstr-search-thin-240.png" alt="search icon">
</button>
CSS
.form-control, .me-2 {
animation: slide 1s 1;
}
.me-2 {
display: none !important;
}
JS
let slideSearch = document.querySelector(".me-2");
function showBar() {
slideSearch.style.display = "block";
}
Your problem is you're using !important on display: none of .me-2.
You should not use !important in your style unless you want to hide it permanently.
let slideSearch = document.querySelector(".me-2");
function showBar() {
slideSearch.style.display = "block";
}
.form-control, .me-2 {
animation: slide 1s 1;
}
.me-2 {
display: none; /*Removed !important*/
}
<button onclick="showBar()" class="btn btn-outline-success" type="submit">
Search
<img src="./images/iconmonstr-search-thin-240.png" alt="search icon">
</button>
<input class="me-2"/>
If you cannot get rid of !important for some reason. You can try to add !important to .me-2 in Javascript that would override !important in your CSS.
let slideSearch = document.querySelector(".me-2");
function showBar() {
slideSearch.style.setProperty('display','block','important');
}
.form-control, .me-2 {
animation: slide 1s 1;
}
.me-2 {
display: none !important;
}
<button onclick="showBar()" class="btn btn-outline-success" type="submit">
Search
<img src="./images/iconmonstr-search-thin-240.png" alt="search icon">
</button>
<input class="me-2"/>
Related
I have a disabled button and I want to display a message in the other side of the page (NOT A CHILD ELEMENT) when I hover this button. How to do that? I already tried using jquery and CSS but it doens't work:
#deleteManagerWarning{
display: none;
color: red;
float: right;
}
#disabledCloseBtn:hover + #deleteManagerWarning{
display: block;
}
and
$("#disabledCloseBtn").hover(function(){
$("#deleteManagerWarning").css("display", "block");
});
This is the html button:
<button type="submit"
class="btn-close"
id="disabledCloseBtn"
name="disabledCloseBtn"
disabled
aria-label="Close">
This is the html message:
<span id="deleteManagerWarning">Unable to delete Manager</span>
If the two elements are far separated from each other in the markup, CSS won't help you-- you need a relationship like descendent or adjacent. In this case, your jQuery would be working if the button were not disabled:
$(document).ready(() => {
$("#disabledCloseBtn").hover(function(){
console.log('hover');
$("#deleteManagerWarning").css("display", "block");
});
});
#deleteManagerWarning {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button type="submit" class="btn-close" id="disabledCloseBtn" name="disabledCloseBtn" aria-label="Close">
Close
</button>
</div>
<div>
<p>Dummy content</p>
<p>Dummy content</p>
<p>Dummy content</p>
<span id="deleteManagerWarning">Unable to delete Manager</span>
</div>
However, it appears that jQuery does not (or cannot) fire the hover event for a disabled button-- the following example is exactly the same as the first except the button is disabled:
$(document).ready(() => {
$("#disabledCloseBtn").hover(function(){
console.log('hover');
$("#deleteManagerWarning").css("display", "block");
});
});
#deleteManagerWarning {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button type="submit" class="btn-close" id="disabledCloseBtn" name="disabledCloseBtn" disabled aria-label="Close">
Close
</button>
</div>
<div>
<p>Dummy content</p>
<p>Dummy content</p>
<p>Dummy content</p>
<span id="deleteManagerWarning">Unable to delete Manager</span>
</div>
In this case, you have a few alternative options you can employ:
Fake the disabled state on the button: reduce the opacity, remove click handlers, make sure you update the ARIA messaging to report the button as disabled. (You could also fake the button entirely using a <div> and wiring up all the accessibility and interactivity, but this would be much more difficult and to a similar effect). This may actually be more accessible, because a disabled button isn't focusable by keyboard.
Use a different hover target: Instead of the button, try using the wrapper around the button, or float something invisible over the button.
Here is an example faking the disabled state:
$(document).ready(() => {
$("#disabledCloseBtn").hover(
function() {
$("#deleteManagerWarning").css("display", "block");
},
function() {
$("#deleteManagerWarning").css("display", "none");
},
);
});
#deleteManagerWarning {
display: none;
}
.disabled {
opacity: 0.5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button type="submit" class="btn-close disabled" id="disabledCloseBtn" name="disabledCloseBtn" aria-label="Close">
Close
</button>
</div>
<div>
<p>Dummy content</p>
<p>Dummy content</p>
<p>Dummy content</p>
<span id="deleteManagerWarning">Unable to delete Manager</span>
</div>
Just make sure you are figuring out a way to communicate that it is disabled to assistive technologies -- and remember, content that is popping into the existence on the other side of the page probably needs to be appropriately announced to screen readers.
Problem
It appears that JavaScript and jQuery do not detect disabled tags (I learned something today).
CSS has no problem:
Figure I
<button class='A'>A</button>
<output class='A'>HELLO WORLD!</output>
Figure II
button.A:hover:disabled + output.A {
display: inline-block;
}
/* 👍 */
Figure III
$('button.A').hover(enter, exit)
// OR
document.querySelector('button.A').addEventListener('mouseenter', enter);
document.querySelector('button.A').addEventListener('mouseleave', exit);
/* 👎 */
If you need to use jQuery or JavaScript you'll need to wrap the disabled button in another tag (See Example C and D). Note, the JavaScript portion of Figure III is slightly different than the JavaScript in Example D. In Figure III the events used are "mouseenter" and "mouseleave" which are the equivalent of the jQuery .hover() method. In Example D the events "mouseover" and "mouseout" were used because Example D was setup to delegate the events which requires bubbling in which "mouseenter" and "mouseleave" do not do. At the bottom of this answer are links to everything either discussed or demonstrated.
Solutions
CSS: A combination of :hover, :disabled, and sibling combinators (+ and ~). If given the exact HTML layout, I could assist you in obtaining the exact selector. If it's too much HTML, a link to a Plunker, Pen, or Fiddle will be fine.
From what I already know, I believe the general sibling combinator will work (see Example B)
OR
jQ/JS: Wrap the disabled button in another tag and target that instead.
/**
* Example C - button wrapper (jQuery)
*/
$("button.C, menu.C").hover(jQEnter, jQExit);
function jQEnter(e) {
/* DEMO =------------------= */
console.clear();
console.log(this.tagName);
/* =-----------------------= */
$("output.C").show();
}
function jQExit(e) {
$("output.C").hide();
}
/**
* Example D - button wrapper (JavaScript)
*/
document.querySelector('fieldset.D').addEventListener('mouseover', JSEnter);
document.querySelector('fieldset.D').addEventListener('mouseout', JSExit);
function JSEnter(e) {
/* DEMO =------------------= */
console.clear();
console.log(e.target.tagName);
/* =-----------------------= */
if (e.target.matches('button.D, menu.D')) {
document.querySelector('output.D').style.display = 'inline-block';
}
}
function JSExit(e) {
if (e.target.matches('button.D, menu.D')) {
document.querySelector('output.D').style.display = 'none';
}
}
/**
* Example A - adjacent sibling combinator (CSS)
*/
button.A:disabled:hover+output.A {
display: inline-block;
}
/**
* Example B - general sibling combinator (CSS)
*/
button.B:disabled:hover~output.B {
display: inline-block;
}
<style>
/* DEMO =----------------------=*/
fieldset {
position: relative;
margin-bottom: 20px;
}
fieldset:nth-of-type(2) {
padding-bottom: 25px;
}
fieldset fieldset {
margin-bottom: 5px;
}
pre {
outline: dashed blue 1px;
}
p {
margin-top: -3px;
margin-bottom: -3px;
}
output {
position: absolute;
z-index: 1;
display: none;
margin-bottom: 4px;
color: red;
}
menu {
max-width: max-content;
padding: 10px;
outline: red dashed 1px;
}
.as-console-row::after {
width: 0;
font-size: 0;
}
.as-console-row-code {
width: 100%;
word-break: break-word;
}
.as-console-wrapper {
min-height: 25% !important;
max-width: 50%;
margin-left: 50%;
}
/* =---------------------------= */
</style>
<fieldset class='A'>
<legend>Example A - <code>output.A</code> is <b>directly</b> after <code>button.A</code></legend>
<pre><code>
button.A:disabled:hover + output.A {
display: inline-block;
}
</code></pre>
<button class="A" disabled>button A</button>
<output class="A">output A</output>
</fieldset>
<fieldset class='B'>
<legend>Example B - <code>output.B</code> is after <code>button.B</code></legend>
<p><b>and</b> there could be other tags between them</p>
<pre><code>
button.B:disabled:hover ~ output.B {
display: inline-block;
}
</code></pre>
<button class="B" disabled>button B</button>
<fieldset disabled>
<legend>Manager</legend>
</fieldset>
<output class="B">output B</output>
</fieldset>
<fieldset class='C'>
<legend>Example C - <code>output.C</code> is anywhere on page</legend>
<output class="C">output C</output>
<menu class='C'>
<button class="C" disabled>button C</button>
</menu>
<button class="C" disabled>button C</button>
<button class="C">button C ENABLED</button>
</fieldset>
<fieldset class='D'>
<legend>Example D - <code>output.D</code> is anywhere on this page</legend>
<output class="D">output D</output>
<menu class='D'>
<button class="D" disabled>button D</button>
</menu>
<button class="D" disabled>button D</button>
<button class="D">button D ENABLED</button>
</fieldset>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
References
HTML Attribute
disabled
CSS Selectors
:disabled
:hover
Child & Sibling Combinators
jQuery Methods
.hover()
.show() & .hide()
JavaScript Events
Events
Event Delegation
Currently, I have this menu, What I want to do is whenever we hover on the button with classname "scroll-button-down" I want to scroll down the menu, but right now only the button is scrolling not all the menu.
This is my code so far:
return (
<div className="menu-wrapper">
<div>
<a className="menu-item">Pizza</a>
<a className="menu-item">Hamburguers</a>
<button>{"⌃"}</button>
<a className="menu-item">Guacamole</a>
<a className="menu-item">Sushi</a>
<button className="scroll-button-down">{"⌄"}</button>
</div>
</div>
);
css
.scroll-button-down:hover {
animation: moveMenushow 0.6s linear forwards;
}
#keyframes moveMenushow {
100% {
transform: translateY(-40%);
}
}
Using JS, you can achieve this effect. Below is a code you can use to track the events. What element to scroll is not clear for me, so you will need to do that part yourself.
let scrollToken = null;
function mouseEnter(direction){
scrollToken = setInterval(function(){
if(direction === "down"){
// Scroll down, e.g. by using scrollBy
}else{
// Scroll up, e.g. by using scrollBy
}
}, 3);
}
function mouseLeave(){
clearInterval(scrollToken);
}
<div className="menu-wrapper">
<div>
<a className="menu-item">Pizza</DropDownItem>
<a className="menu-item">Hamburguers</DropDownItem>
<button className="scroll-button-down" onmouseover="mouseEnter('down')" onmouseleave="mouseLeave()">{"⌃"}</button>
<a className="menu-item">Guacamole</DropDownItem>
<a className="menu-item">Sushi</DropDownItem>
<button>{"⌄"}</button>
</div>
</div>
I'm trying to animate my Create Note form in when I click on a button but it just immediately comes in without a transition. What I'm trying to do is to add a class that sets its display from 'none' to 'flex'.
This is how the form looks (HTML)
//Finally, this is the javascript that I'm trying to get it to work
const createBtn = document.getElementById('createBtn');
const form = document.getElementById('noteForm');
createBtn.addEventListener('click', () => {
form.classList.toggle('active');
});
.active {
display: flex;
}
form {
display: none;
/* other propertites */
transition: all 250ms ease-in;
}
<button id="createBtn">Create a Note</button>
<form id="noteForm">
<!--form Content-->
<input type="text">
</form>
I am not sure if this is the correct way to be animating things in but I want to know how I can pull something like this off with vanilla JS.
Your code is right... except that display is not an animatable property.
For a fading effect, you have to use opacity:
//Finally, this is the javascript that I'm trying to get it to work
const createBtn = document.getElementById('createBtn');
const form = document.getElementById('noteForm');
createBtn.addEventListener('click', () => {
form.classList.toggle('active');
});
.active {
opacity: 1;
}
form {
display: flex;
opacity: 0;
/* other propertites */
transition: all 250ms ease-in;
}
<button id="createBtn">Create a Note</button>
<form id="noteForm">
<!--form Content-->
<input type="text">
</form>
But note that the form will remain interactive even when hidden. To avoid that, you can use the solution from this answer on SO:
//Finally, this is the javascript that I'm trying to get it to work
const createBtn = document.getElementById('createBtn');
const form = document.getElementById('noteForm');
const fieldset = document.getElementById('noteFormFieldset');
createBtn.addEventListener('click', () => {
form.classList.toggle('active');
fieldset.disabled = !form.classList.contains('active')
});
.active {
opacity: 1;
}
form {
display: flex;
opacity: 0;
/* other propertites */
transition: all 250ms ease-in;
}
<button id="createBtn">Create a Note</button>
<form id="noteForm">
<fieldset id="noteFormFieldset" disabled>
<!--form Content-->
<input type="text">
</fieldset>
</form>
I my app UI I have a table with a set of permissions listed. In each row there is a toggle-button that sets the default state of each permission to either "deny" or "grant" in the DB.
If the user clicks the button, async action is triggered in the background. It all works perfectly fine, but what I want to add is when user click the button its inner html changes to a spinner or some sort of "wait..." text and the button get disable while the action runs. This is to prevent user from clicking multiple time is the action take a bit longer to complete, giving impression like nothing is happening.
Now, I know how to do it in jQuery or even plain JS, but I have no idea how to access the button properties in VUE.js
My button look like this:
<button #click="defaultPermissionState(perm.id,'grant',$event)">Deny</button>
I'm only recently started into vue.js, so still learning it ;)
UPDATE: I've actually managed to find a way to do it by exploring the $event and being able to change the text and button properties by doing this:
event.path[0].innerHTML = 'wait...';
event.path[0].disabled = true;
but this does not look like a very elegant solution, so if anyone knows of something better I would still like to hear it
You can use v-if with :disabled. Check this quick example:
new Vue({
el: "#app",
data: {
isLoadingArray: []
},
methods: {
clicked(index) {
this.$set(this.isLoadingArray, index, true)
setTimeout(() => {
this.$set(this.isLoadingArray, index, false)
}, 2000)
}
}
})
.lds-dual-ring {
display: inline-block;
width: 64px;
height: 64px;
}
.lds-dual-ring:after {
content: " ";
display: block;
width: 46px;
height: 46px;
margin: 1px;
border-radius: 50%;
border: 5px solid #fff;
border-color: #fff transparent #fff transparent;
animation: lds-dual-ring 1.2s linear infinite;
}
#keyframes lds-dual-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button type="button" #click="clicked(0)" :disabled="isLoadingArray[0]">
<div v-if="isLoadingArray[0]" class="lds-dual-ring"></div>
<span v-else>click me</span>
</button>
<button type="button" #click="clicked(1)" :disabled="isLoadingArray[1]">
<div v-if="isLoadingArray[1]" class="lds-dual-ring"></div>
<span v-else>click me</span>
</button>
<button type="button" #click="clicked(2)" :disabled="isLoadingArray[2]">
<div v-if="isLoadingArray[2]" class="lds-dual-ring"></div>
<span v-else>click me</span>
</button>
</div>
You can do it like this
data: function() {
return {
waiting: false,
...otherstuffs
}
},
methods: {
callAsync() {
this.waiting = true;
callASYNC()
.then((result) => {
this.waiting = false;
})
}
}
In your HTML
<button :disabled="waiting"> {{ waiting ? 'Waiting ...' : 'Deny' }} </button>
So basically, just set a flag before you hit the request, and set it back when the call finishes. Use this flag to set the button value to whatever you want
This should help
<template>
<button disabled={{disableBtn}}
#click="defaultPermissionState(perm.id,'grant',$event)">{{btnText}}
</button>
</template>
export default {
data() {
return {
btnText: 'Deny',
disableBtn: false
}
},
method: {
defaultPermissionState(id, type, e) {
this.disableBtn = true;
this.btnText = 'Clicking.....';
}
}
}
Hide the button and show the spinner using a data or computed property. Update the 'busy' property from your async function.
<button v-if='!busy' #click="defaultPermissionState(perm.id,'grant',$event)">Deny</button>
<spinner v-else />
you can use $event to change the inner html for buttons
$event.path[0].innerHTML = "Write the inner html"
Not completely sure how to explain what's going on. I'm trying to do a transformation on my search bar after it's submitted. The CSS and HTML are pretty large so I'm linking to CodePen to see in action, but I'll post the JS/CSS here as well.
I'd like to do something 'fancy' with the search bar, while the results pop up on the same screen so I thought 'transitions'.
CSS
.postSearch{
-webkit-transition: all 3s ease;
-webkit-transform: rotate(1440deg);
-moz-transition: all 3s ease;
-moz-transform: rotate(1440deg);
margin-left: 80%;
}
HTML Form
<div class="revolver">
<form id="myForm">
<p class="inp-wrap search-wrap">
<label for="charName" class="search-label grid-25">Find</label>
<input type="search" name="charName" id="charName" class="grid-75" placeholder="e.g. Teodoro" />
</p>
<p class="inp-wrap cat-wrap">
<label for="servers" class="grid-20">on</label>
<select name="servers" id="servers" class="grid-80">
<option>Thrall</option>
</select>
</p>
<p class="inp-wrap submit-wrap">
<button class="grid-100 btn" name="SubmitButton" onclick="updateTransition()" type="button">
<span class="search-icon-container">
<i class="fa fa-search" aria-hidden="true"></i>
</span> GO!
</button>
</p>
</form>
</div>
JS
function updateTransition() {
var el = document.querySelector("div.revolver");
if (el) {
$('#myForm').addClass('postponed');
$('#myForm').removeClass('myForm');
el.className = "postSearch";
} else {
$('#myForm').addClass('myForm');
$('#myForm').removeClass('postponed');
el = document.querySelector("div.postSearch");
el.className = "revolver";
}
};
There is a lot more to this page in production which is why some of the IDs etc don't make sure. I feel like using 'toggleClass' is a better idea for the myForm/postponed swap also. (I do this so hitting 'Go' again doesn't re-submit the form.
The codepen is located here - If you notice when you hit 'go' you'll see a scroll bar periodically pop up. On smaller resolutions it happens, on 4K it happens. On the website it actually is causing the background image to 'shake' and snap around.
I'm not too familiar with transitions, but I followed the documents pretty specifically. I'll end up inverting it to get the search bar to go back since it kind of 'snaps' back right now. Would appreciate any advice.
Thanks.
It is because of the component is going out from document. Try by adding overflow: hidden to it's parent container. Please try this and let me know if this is helpful for you.
function updateTransition() {
var el = document.querySelector("div.revolver");
if (el) {
$('#myForm').addClass('postponed');
$('#myForm').removeClass('myForm');
el.className = "postSearch";
} else {
$('#myForm').addClass('myForm');
$('#myForm').removeClass('postponed');
el = document.querySelector("div.postSearch");
el.className = "revolver";
}
};
html,
body {
position: relative;
height: 100%;
margin: 0;
/* temporary class */
}
.overflow-hidden {
overflow: hidden;
position: relative;
min-height: 100%;
}
.postSearch {
-webkit-transition: all 3s ease;
-webkit-transform: rotate(1440deg);
-moz-transition: all 3s ease;
-moz-transform: rotate(1440deg);
margin-left: 80%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="overflow-hidden">
<div class="revolver">
<form id="myForm">
<p class="inp-wrap search-wrap">
<label for="charName" class="search-label grid-25">Find</label>
<input type="search" name="charName" id="charName" class="grid-75" placeholder="e.g. Teodoro" />
</p>
<p class="inp-wrap cat-wrap">
<label for="servers" class="grid-20">on</label>
<select name="servers" id="servers" class="grid-80">
<option>Thrall</option>
</select>
</p>
<p class="inp-wrap submit-wrap">
<button class="grid-100 btn" name="SubmitButton" onclick="updateTransition()" type="button">
<span class="search-icon-container">
<i class="fa fa-search" aria-hidden="true"></i>
</span> GO!
</button>
</p>
</form>
</div>
</div>
Scroll occurs because while form is spinning it goes out parent.
One possible solution is to add overflow: hidden for the time of animation.
body.transitionActive{
overflow: hidden;
}
js
[...]
$('#myForm').addClass('postponed');
$('body').addClass('transitionActive');
setTimeout(function(){
$('body').removeClass('transitionActive');
}, 3000);
$('#myForm').removeClass('myForm');
[...]
See how it works here: http://codepen.io/anon/pen/ALNLak