I'm trying to make the upper panel of my application to have top property to be -80px by default so it's invisible except of a small part of it. And when the user hover with his mouse on that part, it slides down again.
The problem is, this div has a textbox, i want the div to stop sliding up when the user is typing on this textbox even if he move his mouse pointer away, but unfortunately don't know how to do this, here's my code :
index.html
<div id="taskInput">
<div id="controllers">
<input type="text" name="mainTask" id="mainTask">
<button id="addMain">Add</button>
<button id="resetMain">Reset</button>
</div>
</div>
css of this part :
#taskInput {
background: red;
width:606px;
height:43px;
padding: 22px;
box-shadow: 0px 3px 4px -3px black;
position: absolute;
z-index : 0;
top:0px;
}
script.js
$(function(){
$("#taskInput").delay(400).animate({top:-80}, 500,function(){});
$("#taskInput").mouseover(
function(){
$(this).stop().animate({top:0}, 200, function(){});
});
$("#taskInput").mouseout(function(evt){
$(this).stop().animate({top:-80}, 200, function(){});
})
$("#mainTask").focus(function(){
//i though i can put something here to stop mouseout event or something
})
})
I've changed my mind from my comment, there's no need to unbind the events or use a global variable to track it. You can use document.activeElement to get the currently focused element on the page, and compare its id to the id of your <input>, like so:
$("#taskInput").mouseout(function(evt){
if(document.activeElement.id !== 'mainTask') {
$(this).stop().animate({top:-80}, 200, function(){});
}
});
Working DEMO
add a flag to the animate to top and change it in the focus function
i have not tested this but it should work
$(function(){
writing = false;
$("#taskInput").delay(400).animate({top:-80}, 500,function(){});
$("#taskInput").mouseover(
function(){
$(this).stop().animate({top:0}, 200, function(){});
});
$("#taskInput").mouseout(function(evt){
if(writing == false){
$(this).stop().animate({top:-80}, 200, function(){});
}
})
$("#mainTask").focus(function(){
//i though i can put something here to stop mouseout event or something
writing = true
})
$("#mainTask").focusout(function(){
//i though i can put something here to stop mouseout event or something
writing = false
})
})
jsFiddle DEMO
Easiest way is to give the #mainTask a data-focus attribute set to true, then when doing the mouseout on #taskInput, make sure it is False before animating the slideUp.
$(function(){
// ... code
$("#taskInput").mouseout(function(evt){
console.log($('#mainTask').data('focus'));
if ($('#mainTask').data('focus') === false) {
$(this).stop().animate({top:-80}, 200, function(){});
}
})
$("#mainTask").on({
focus: function(){
$(this).data('focus', true);
},
blur: function () {
$(this).data('focus', false);
}
});
})
I guess, you could also give this a try:
$('#taskInput').delay(400).animate({top:-80},500);
$('#taskInput').mouseover(function()
{
$(this).stop().animate({top:0},200);
});
$('#taskInput').mouseout(function()
{
if(!$('#mainTask').is(':focus'))
{
$(this).stop().animate({top:-80},200);
}
});
DEMO
Edit:
You could also add this to your code:
$('#mainTask').blur(function()
{
$('#taskInput').stop().animate({top:-80},200);
});
DEMO 2
in the $("#mainTask").focus event handler you can set a global boolean variable to true, set it to false in an blur event handler and check on the value of that variable in the #taskInput mouseout event handler
var preventSlide = false;
$("#taskInput").mouseout(function(evt){
if (!preventSlide) {
$(this).stop().animate({top:-80}, 200, function(){});
}
})
$("#mainTask").focus(function(){
preventSlide = true;
})
$("#mainTask").blur(function(){
preventSlide = false;
})
$(function(){
var flag=true;
$("#taskInput").on('mouseenter mouseleave', function(e) {
if (flag) $(this).stop().animate({top: e.type=='mouseenter'?0:-80}, 200);
}).delay(400).animate({top:-80}, 500);
$("#mainTask").on('blur focus', function(e) {
flag=e.type=='blur';
});
});
FIDDLE
Related
The JSFiddle speaks for itself
Open this fiddle http://jsfiddle.net/NfRN5/
Click the input field
Change tabs on your browser
Come back to the fiddle - the width effect will run again =/
Is there a way to prevent this and make it steady when the user navigates away and comes back?
To view the problem in this thread, you will need to click the "Expand snippet" button. The small preview doesn't demonstrate the issue in question.
input.search-field {
width: 100px;
transition: all 1s ease-in-out;
}
input.search-field:focus {
width: 300px;
}
<input type="search" class="search-field">
In chat you mentioned you were trying to emulate Apple.com's search bar.
After peaking at their JS, I came up with this fiddle: http://jsfiddle.net/NfRN5/7/
The trick is to only blur the input in the 10ms following a mousedown, or some keypresses.
var $search = $('.search-field'), searchBlurable = false
$search
// Always focus when focused
.focus(function(e){
$search.addClass('focused')
searchBlurable = false
})
// Only blur after mouse or key events
.blur(function(e){
if(searchBlurable){
$search.removeClass('focused')
}
})
// Set Blurable for tab/esc
.keydown(function(e){
if(e.keyCode === 27 || e.keyCode === 9) { // esc || tab
searchBlurable = true
$search.blur()
}
})
// Set Blurable for 10ms after a mousdown
$('html').mousedown(function(e){
searchBlurable = true
window.setTimeout(function () {
searchBlurable = false
}, 10)
})
I don't believe that can be achieved in pure CSS.
Try some JavaScript / jQuery: http://jsfiddle.net/NfRN5/3/
var $fields = $(".search-field")
$fields.focus(function(){
$fields.removeClass('focused')
$(this).addClass('focused')
})
You can't use the blur event because that is called by the browser when you change tabs.
I made some assumptions about what the rest of the code in your app will look like, you might have to add some other triggers to remove the focused class.
I use a complementary class to handle it.
Add the "focus" class to the active element when the window loses focus (window.blur) and remove the class when it gets focus back.
window.addEventListener("focus", function () {
document.querySelectorAll(".focus").forEach((el) => {
el.classList.remove("focus");
}, false);
});
window.addEventListener("blur", function () {
let el = document.activeElement;
if (el !== null) el.classList.add("focus");
}, false);
input.search-field {
width:100px;
transition: all 1s ease-in-out;
}
input.search-field:focus,
input.search-field.focus {
width:300px;
}
<input type="search" class="search-field">
I have the next div:
<div class="div-class" style="width:158px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;" title=<%=myDesc%>
How can I show the tooltip only when ellipsis is active?
I find this function
function isEllipsisActive(e) {
return (e.offsetWidth < e.scrollWidth);
}
But I didn't know how to use it knowing I use jsp and struts
Try something like this:
Working DEMO
Working DEMO - with tooltip
$(function() {
$('div').each(function(i) {
if (isEllipsisActive(this))
//Enable tooltip
else
//Disable tooltip
});
});
function isEllipsisActive(e) {
return (e.offsetWidth < e.scrollWidth);
}
For anyone using qtip (being quite popular).
First, add a class to each of your overflowing elements.
<span class="ellipsis-text">Some very long text that will overflow</span>
Then, use the jQuery selector to select multiple such elements, and apply the qTip plugin (or any other tooltip that comes to mind) on to your elements as such:
$('.ellipsis-text').each(function() {
if (this.offsetWidth < this.scrollWidth) {
$(this).qtip({
content: {
text: $(this).text()
},
position: {
at: 'bottom center',
my: 'top center'
},
style: {
classes: 'qtip-bootstrap', //Any style you want
}
});
}
});
I'm trying to create a drop down list directive, with down-arrow that appears when the mouse is hovering the dropdown header or when the dropdown list is oppend, and disappears otherways.
I succeeded to do this, but if the dropdown list is closed not by selecting element or by pressing on the header list again, than the arrow isn't disappead.
(I.E. If i'm openning one list and than openning another without closing the first one, than arrow of the first list is not disappearing)
JsFiddle - http://jsfiddle.net/rpg2kill/uS4Bs/
code:
var myApp = angular.module('myApp', ['ui.bootstrap']);
function MyCtrl($scope) {
$scope.supportedList= ['Option1', 'Option2', 'Option3', 'Option4'];
$scope.selectedItem = 'Option1';
}
myApp.directive('dropDown',
function () {
return {
restrict: 'E',
replace: false,
scope: {
supportedList:'=',
selectedItem:'='
},
template:
'<div ng-mouseenter="onMouseEntered()" ng-mouseleave="onMouseLeft()">' +
'<a class="dropdown-toggle" data-toggle="dropdown" href="" ng-click="onMouseClicked()" >' +
'<img ng-style="{\'visibility\': dropDownIconVisibility}" src="http://png.findicons.com/files/icons/2222/gloss_basic/16/arrow_down.png"> </img>' + //Arrow down Icon
'<span>{{selectedItem}}</span>' +
'</a>' +
'<ul class="dropdown-menu">' +
'<li ng-repeat="item in supportedList" ng-click="onSelectedItem(item)">' +
'{{item}}' +
'</li>' +
'</ul>' +
'</div>'
,
link: function(scope, element, attrs) {
scope.dropDownIconVisibility = "hidden";
scope.dropDownIconVisibilityLocked = false;
scope.onSelectedItem = function(item) {
scope.dropDownIconVisibilityLocked = false;
scope.selectedItem = item ;
};
scope.onMouseEntered = function()
{
scope.dropDownIconVisibility = "visible";
};
scope.onMouseLeft = function()
{
if (scope.dropDownIconVisibilityLocked)
return;
scope.dropDownIconVisibility = "hidden";
};
scope.onMouseClicked = function()
{
scope.dropDownIconVisibility = "visible";
scope.dropDownIconVisibilityLocked = !scope.dropDownIconVisibilityLocked;
};
}
};
})
The code is little ugly. A better solution is to show the arrow if the mouse is hovering OR the list is openned, but I don't know how to bind angular to the state of the dropdown list.
Is there a way to binding angular to Twitter bootstrap's dropdown event?
Or is there a better way to solve this problem?
I suggest you using full CSS approach - it takes less code, it does not trigger JS evaluations, thus, it performs better (Angular is a bit slow with all its cool features). Once you go mobile - CSS will be more preferable, as supports downgrading with media queries and so on... There are too many pros!
Remove all your mouse-tracking code and add just two CSS rules and here you go:
a.dropdown-toggle img {
visibility: hidden;
}
a.dropdown-toggle:hover img {
visibility: visible;
}
I succeeded to solve the problem, unfortunately the solution is not so pretty, but at least it works.
I'll try to solve this with only CSS as madhead suggested.
The problem was that I didn't know when the user clicked outside the dropdown, that caused the dropdown popup to close but the icon was still displayed. So I attached an handler to each directive that listen on document.click event and hides the Icon.
document.addEventListener('click', function (event) {
scope.$apply(function () {
scope.hideDropdownIcon();
});
}, false);
That worked, but if I clicked on another Dropdown when the current dropdown was opened, the document.click event was not fired. So I had to create my event and attach it to $window and to call it when any dropdown is opens.
var event = new Event('hideDropDownIcon');
$window.addEventListener('hideDropDownIcon', function (e) {
scope.hideDropdownIcon();
}, false);
You can see it here:
http://jsfiddle.net/rpg2kill/uS4Bs/6/
There must be a better solution. So if you know how to do it better or by using only css, I would like to know.
Thanks.
Found CSS solution to the problem.
css is so simple instead all the js events..
The CSS:
a.dropdown-toggle img {
visibility: hidden;
}
li.ng-scope:hover img,li.ng-scope:active img,.open a img{
visibility: visible;
}
You can check this: http://jsfiddle.net/rpg2kill/HVftB/1/
Is there a way to detect vertical scroll distance with a media query?
It seems that media queries are designed around detecting the medium (shocking right :P) so things like browser height are testable, but not specifically how far down the page is scrolled.
If is not possible, but you know a way in JS (not jQuery) feel free to post!
First off, the accepted answer doesn't work.
The correct name is
window.onscroll
and not
window.onScroll
https://developer.mozilla.org/en-US/docs/Web/API/window.onscroll
Second, this is horribly inefficient as the function is called way more than it needs to and can make the page laggy when scrolled. From John Resig:
http://ejohn.org/blog/learning-from-twitter/
Much better to use a timer that runs every 150 ms or so - something like:
var scrolled = false;
window.onscroll = function() {
scrolled = true;
}
setInterval(function(){
if (scrolled) {
scrolled = false;
// scrollFunction()
}
}, 150);
I don't believe it's possible with a CSS media query, but I do know that the scroll height can be found in JavaScript using window.pageYOffset. If you wanted to run this value through a function every time the users scrolled up or down on a page, you could do something like
window.onscroll = function() {
scrollFunctionHere(window.pageYOffset);
};
Or just:
window.onscroll = scrollFunctionHere;
If the function itself checked the value of window.pageYOffset.
For more advice on how to do use window.onscroll efficiently in JavaScript, refer to mynameistechno's answer.
Important note on efficiency: running a function every single time a scroll event is emitted can tear through CPU cycles if anything non-trivial is performed in the callback. Instead, it is good practice to only allow a callback to run so many times per second. This has been termed "debouncing".
Simple debounced scroll event handler code below. Notice how the text toggles between "HELLO" and "WORLD" every 250ms, rather than every single frame:
var outputTo = document.querySelector(".output");
var timeout_debounce;
window.addEventListener("scroll", debounce);
function debounce(event) {
if(timeout_debounce) {
return;
}
timeout_debounce = setTimeout(clearDebounce, 250);
// Pass the event to the actual callback.
actualCallback(event);
}
function clearDebounce() {
timeout_debounce = null;
}
function actualCallback(event) {
// Perform your logic here with no CPU hogging.
outputTo.innerText = outputTo.innerText === "HELLO"
? "WORLD"
: "HELLO";
}
p {
padding: 40vh;
margin: 20vh;
background: blue;
color: white;
}
<p class="output">Test!</p>
In Jquery you have the method .scrollTop()
http://api.jquery.com/scrolltop/
This example make a div scroll with the window scroll.
$(window).scroll(function(){
$("div").css("margin-top", $(window).scrollTop())
});
Here is one way to solution.f https://jsfiddle.net/oravckzx/1/
$(window).scroll(function(){
$('.post-sidebar').each(function(){
var ScrollTopVar = $(window).scrollTop();
var OffsetTopVar = $(this).offset().top;
var OuterHeightVar = $(this).outerHeight();
var PositionVar = OffsetTopVar-(OuterHeightVar*1.1);
if (ScrollTopVar >= PositionVar) {
$('.hide') .css('background','green').css('font-size','12px')
$('.post-sidebar') .css('background','orange').css('font-size','12px')
$('.hide') .css('background','green').css('font-size','12px')
$('.post-sidebar') .css('background','gray').css('font-size','12px')
document.getElementById("demo3").innerHTML = ScrollTopVar;
document.getElementById("demo2").innerHTML = PositionVar;
}else {
$('.hide') .css('background','yellow').css('background','yellow')
$('.hide') .css('background','yellow')
$('.hide') .css('background','yellow')
document.getElementById("demo").innerHTML = ScrollTopVar;
document.getElementById("demo12").innerHTML = ScrollTopVar;
document.getElementById("demo13").innerHTML = ScrollTopVar;
document.getElementById("demo14").innerHTML = ScrollTopVar;
document.getElementById("demo2").innerHTML = PositionVar;
}
});
});
.red {height:100px;
background:red;margin-bottom:20px;}
.hide {height:50px;background:blue;margin-bottom:20px;}
.post-sidebar {
height:50px;
background:yellow;
margin-bottom:20px;
box-sizing: border-box;
display: block;
font: normal 700 34px Lato, sans-serif;
padding-right: 20px;
width: 452px;
}
.p {
font: normal 700 14px Lato, sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="red"><p id="demo"></div>
<div class="red"></div><p id="demo12">ok
<div class="red"><p id="demo13">ok</div>
<div class="post-sidebar"><p id="demo2"></p><p>lizard</p></div>
<div class="hide"><p id="demo2">If reaches to chosen class in html, saves value of ScrollTopVar (as distance from top) to separate variable as eventually PositionVar (which is the distance from top to the chosen class in html, - and that specific distance depends of device which is doing it), and then does certain action if ScrollTopVar value matches or exceeds PositionVar value. Else sets it back if needed, if not including Else it remains as it once met the value. <p id="demo3"></div>
<div class="red"><p id="demo14">ok</div>
<div class="red"><p id="demo"></div>
<div class="red"><p id="demo"></div>
I am using this div to open exit popup using jquery. But it's not showing in IE8 and IE9.
Here is div:
<div style="display: none; padding: 10px;" id="exit_content">
<h3>10% Discount on purchase of this item!</h3><br />
</div>
These 2 functions are used to open and close popup on mouse move.
function modalOpen (dialog) {
dialog.overlay.fadeIn('fast', function () {
dialog.container.fadeIn('fast', function () {
dialog.data.hide().slideDown('fast');
});
});
}
function simplemodal_close(dialog) {
dialog.data.fadeOut('fast', function () {
dialog.container.hide('fast', function () {
dialog.overlay.slideUp('fast', function () {
$.modal.close();
});
});
});
}
Here is script used for open and close.
$(document).mousemove(function(e) {
if(e.pageY <= 5) {
// Launch MODAL BOX
$('#exit_content').modal({onOpen: modalOpen, onClose: simplemodal_close});
}
});
This popup is displaying in all browser except IE8 and IE9.
$(document).mousemove(function(e) {
if(e.pageY <= 5) {
this is probably what's breaking in IE8 and IE9, try debugging and see what IE is passing as a value of e
I don't think pageY is going to be there in old IE