onClick called on second Click when :active is set on img - javascript

Basically what I want to achieve is an clickable image with an active state.
When the image is clicked something should happen and while it is pressed (active) it should display another image.
document.getElementById("scrollbox-table-nav-softer").addEventListener("click", tableNavSofterOnClick);
function tableNavSofterOnClick(){
//doStuff..
}
#scrollbox-table-nav-softer{
max-height: 45px;
position: absolute;
left: 15px;
top: 0;
z-index: 1;
}
#scrollbox-table-nav-softer:active{
content: url("https://www.joomlack.fr/images/demos/demo2/on-top-of-earth.jpg");
}
<img src="http://cdn05.branchez-vous.com/wp-content/uploads/2016/09/bge2-800x410.jpg" id="scrollbox-table-nav-softer"/>
The problem is that when the page is loaded the first click on that element does nothing (the onClick method is not called). On the second click it works as intended (image changes when clicked and the onClick method is executed).
What causes the first click to malfunction?
EDIT:
I managed to fix this issue by adding a class to the CSS :active block like so:
#scrollbox-table-nav-softer:active .elementActive{
content: url("../img/button_softer_active.png");
}
I dont know how or why... but it works now as intended. If someone can explain this to me I would appreciate it.

Quick fix:
You need to change image src on onmouseup and onmousedown events:
<img
onmousedown="document.getElementById('scrollbox-table-nav-softer').src='your_image_1.jpg'"
onmouseup="document.getElementById('scrollbox-table-nav-softer').src='your_image.jpg'"
src="your_image.jpg"
id="scrollbox-table-nav-softer"/>
https://jsfiddle.net/xcmqkcba/1/

Related

How to stop safari (on ipad) from firing hover event?

I have a button that is fixed on my page and when you start to scroll it appears. I noticed on ipad safari I have to click this button twice to fire the click event once.
After searching around I found this sure enough when I commented out my "display:none" on the button it works.
How can I achieve having it hidden and then changing it to "display:block" without getting this double click issue?
You can use css position instead to place it off screen:
.hide {
position: absolute;
left: -999em;
}
You could also try the visibility property
.hide {
visibility: hidden;
}
w3c example

How to dynamically change the Tweet button without it blinking?

I am trying to have the Tweet button updated dynamically so that different text is tweeted (if one presses the Tweet button) every time some event happens.
Actually, what I am trying to achieve is the same as described in the following question:
Dynamically change Tweet Button "data-text" contents
And the provided answer to that question works ok with one annoying small problem. If I implement it like that, the Tweet button blinks when it's updated (disappears and appears) because it is rendered from scratch by using
twttr.widgets.load();
Does anyone have an idea on how would I achieve the same thing but without the "blinking"?
The way I finally solved this was like so.
In the html file I define two divs one after another:
<div id="share_fixed">
<a class="twitter-share-button" href="http://twitter.com/share" data-url=" " data-size="large" data-show-count="false" data-text=" ">
</a>
</div>
<div id="share">
</div>
The div with id="share_fixed" will contain a Tweet button which will be static (rendered only when the page loads).
The other div with id="share" will contain the Tweet button which will be rerendered (updated) every time some event occurs.
In the CSS I position both divs at the same location and overlay the one which changes on top of the fixed one:
#share {
position: absolute;
bottom: 12px;
left: 15px;
z-index: 1;
}
#share_fixed {
position: absolute;
bottom: 12px;
left: 15px;
z-index: 0;
}
This will actually force the fixed "dummy" Tweet button to always be positioned below the one which changes and blinks on reload. Whenever the button on top changes and "blinks" the one below it will remain and since it's exactly the same, it will seem like nothing changes.
In the Javascript file I add e.g. something like this:
var tweetBtn = $(document.createElement('a')).addClass("twitter-share-button")
.attr('href', 'http://twitter.com/share')
.attr('data-url', ' ')
.attr('data-size', 'large')
.attr('data-show-count', 'false')
.attr('data-text', "Some new tweet text");
$("#share iframe").remove();
$("#share").append(tweetBtn);
twttr.widgets.load();
I guess there are more ways to solve this, but this works for me on Chrome, haven't tried on other browsers.

Delayed CSS rendering while Javascript does it's work

I have a very large and complicated jQuery plugin which I will avoid posting here for simplicity's sake. My problem is very simple, and I will reduce it only to the relevant code:
I have a click event attached to a set of buttons:
$("ul.tick-boxes button").click(function(event) {
event.preventDefault();
$("ul.product-grid").addClass("loading");
$(this).toggleClass("active");
$theElement.trigger("filterOptionsChanged");
});
If you go to this link, you can see these in action in the left sidebar:
http://mazer.com/collections/refrigerator?preview_theme_id=22019779
Here is the css that produces a check-mark when you click the buttons:
ul.tick-boxes button.active .tick-box::after {
content: "\e603";
font-family: "custom-icons";
color: #51425d;
top: 2px;
left: 2px;
font-size: 0.75rem;
position: absolute;
}
If your computer is as slow as mine, then when you click these filter options, it takes a second or so to "tick" the "tick-box". If you can't see it, try unticking it, which for me takes noticeably longer. The time-point where the "tick" visibly renders is always simultaneous with the product-grid rebuilding and rendering. I haven't posted the code for manipulating the product-grid, but you can know that the line $theElement.trigger("filterOptionsChanged") triggers a lot of array and object processing to build a document fragment of the new product list, and updates the DOM at the end. I understand this can take a second, that is not my problem. But what I don't understand is why my "tick-boxes" are waiting until after the code of that event is finished to render. According to my css, all I need is a class active on the button, and that code is fired one line above triggering the "filterOptionsChanged" event, so it should fire before any product grid changes happen.
Now. If I open up my inspector in chrome, I can actually see the active classes toggling instantaneously on click, before the product grid updates. However, the css which adds the tick doesn't catch the active class on the element until after my "filterOptionsChanged" code completes.
My first attempt to solve the problem will be posted below. I read a good bit about the "expensiveness" of css pseudo-selectors. That essentially to a browser, it is like a dom manipulation every time an ::after element is created. So I then write this css:
ul.tick-boxes button .tick-box::after {
content: "\e603";
font-family: "custom-icons";
color: #51425d;
top: 2px;
left: 2px;
font-size: 0.75rem;
position: absolute;
opacity: 0;
}
ul.tick-boxes button.active .tick-box::after {
opacity: 1;
}
So now an ::after element always exists from the beginning, any rendering costs are paid for at the outset, so my thought was, now when I click this button, the tick is already there, we are just giving it an opacity of 1. Didn't fix the delay.
Now, I try removing the "filterOptionsChanged" event trigger entirely. This makes my whole sorting plugin stop working, but I don't care at this point, because I want to understand what is causing the problem. When I do remove that event trigger, the buttons and css render snappy. No more problems.
I have a vague thought that, ok, if a click event can be snappy without that event trigger, I need a way of seperating the two. First add the active class, then trigger "filterOptionsChanged". I think, ok, jQuery Deferreds. Here is that code:
$("ul.tick-boxes button").click(function(event) {
event.preventDefault();
var showLoading = jQuery.Deferred();
$("ul.product-grid").addClass("loading");
$(this).toggleClass("active");
showLoading.resolve();
$.when(showLoading).done(function() {
$theElement.trigger("filterOptionsChanged");
});
});
So showLoading is a blank Deferred, I then add my classes for the tick boxes to show, then I resolve the deferred. Now I say, when showLoading is done, then do the whole product-grid manipulation. Don't do these at the same time, javascript, wait for one to finish, then do the other. Still no avail. Any ideas?
According to this, all function calls in JavaScript block the UI until they complete; I'd wager that this includes the original function call to start the click event. A cheap solution might be to replace the trigger with something like:
setTimeout(function() { $theElement.trigger("filterOptionsChanged"); }, 200);
Which will hopefully delay the trigger long enough for the browser to repaint the UI (you could/should add a little loading icon in the original function, then remove it in the timeout). You could also take a look at web workers, which look like they're pretty much threads.
Try this,
CSS:
ul.tick-boxes button.active .tick-box::after {
content: "\e603";
font-family: "custom-icons";
color: #51425d;
top: 2px;
left: 2px;
font-size: 0.75rem;
position: absolute;
}
JS:
$("ul.tick-boxes button").click(function(event) {
event.preventDefault();
$("ul.product-grid").addClass("loading");
$(this).toggleClass("active").fadeIn(10, function () {
$theElement.trigger("filterOptionsChanged");
});
});
Using callback to delay the triggering. See if this work for you.

Setting up a call to external js class

It may be a simple question, but being a newbie it is hard to get it to run.
So I have this leanModal javascript class, which I want to use for a modal popup.
here is the example paragraph that has to appear once an image is clicked:
<p id="lean_overlay"> Some text to appear</p>
Following is the css that is applied to it:
#lean_overlay {
position: fixed;
z-index:100;
top: 0px;
left: 0px;
height:100%;
width:100%;
background: #000;
display: none;
}
The tutorial of leanModal class says the following:
Step 3: call the function on your modal trigger, as follows. Be sure to set the href attribute of your trigger anchor to match the id of your target element.
$("#trigger_id").leanModal();
What I want to be done is once an img is clicked, the leanModal method to be called, but I got lost in the previous tutorial, in particular which element is a modal trigger and which one is the target element. Moreover, how to call a function once an image is clicked?
any help is much appreciated.
Since you mentioned image is clicked, then you can check its target by
$('img').click(function (e) {
alert(e.target);
});

How to display file browser from click on text and have mouse cursor change to pointer when hovering text

I'm trying to display a file chooser when a user clicks a link on my page. I've looked around a bit, but still haven't found a complete solution.
I have ruled out binding a listener to the click event on my link and simulating the click event on my form's file field because I've read that Safari doesn't support programmatically clicking on an input[type=file].
Currently I am using the approach where I set the opacity of the file field to 0 and absolute position it over the top of the link, effectively intercepting any clicks on the link. The problem with this is that I can't figure out a way to change the user's cursor when they hover the link since it is obscured by the file input, which doesn't allow for such styling. I have given all immediate parent elements the css style cursor: pointer, but still no luck.
Does anyone have an idea of a different approach I could take in order to get the cursor to change to a pointer on hover of my link? Is my best bet going to be going with something like they have at http://www.uploadify.com/?
EDIT
To explain a little better, I have this file input on my page:
<div class="logo_file">
<input id="logo_file_field" type="file">
</div>
With this css:
.logo_file {
position: absolute; /* this element's parent has position: relative */
top: -65px;
left: 0;
width: 175px;
overflow: hidden;
cursor: pointer;
}
input#logo_file_field {
opacity: 0;
-moz-opacity: 0;
filter: alpha(opacity=0);
cursor: pointer;
}
And I am trying to show the file chooser corresponding to that field when the user clicks this link:
<div class="logo_link_wrap">
<a id="logo_change_link">Change Photo</a>
</div>
Which has this css:
.logo_link_wrap {
margin-top: 38px;
cursor: pointer;
}
Right now I am placing the invisible file field over the link, but the cursor is not turning into a pointer like it should when you hover over a link. The file chooser does display, it's really only the cursor not changing that is holding me up. Thanks
The problem is that you are placing the input field over the link and making the input field invisible by using opacity:0;. But the input field is still there and is blocking the cursor access to the link.
Would it not be better to replace the opacity with display:none?
With display:none you hide the input field and remove it from the flow. I'm assuming that you want the link to be used to active the upload function of the input field, and I'm also assuming that you know how to do that.
Try wrapping the input tag in an anchor tag
<input type="file" ... />

Categories