Cordova - setTimeout with anonymous function firing immediately - javascript

I'm using Cordova, Kendo ui, and leafletjs maps in an android app. What I want to do when I open a particular view is get a div to appear, wait three seconds, and then hide the div. This should be simple, but no matter the length of time I put in the timeout the div always appears and disappears immediately. I tried using Jquery show and hide at first, but then read that adding and removing classes is better with Phonegap.
js:
utils.hideLoading(); // calls kendo hideLoading function
$("#myDiv").removeClass( "opacityOff" );
$("#myDiv").addClass( "opacityOn" );
setTimeout(function(){
$("#myDiv").removeClass( "opacityOn" );
$("#myDiv").addClass( "opacityOff" );
}, 3000);
css:
#myDiv.opacityOff{
display:none;
opacity:0;
}
#myDiv.opacityOn{
display:block;
opacity:1;
}
#myDiv{
width: 11em;
height: 11em;
position: relative;
margin: 50% auto 0 auto;
margin: 32vh auto 0 auto;
background-color:#000000;
border-radius:50%;
}
Why would setTimeout be executing this anonymous function immediately?
I'm thinking this has something to do with leaflet re renders, but I don't understand it well enough to be sure.

Fixed this by just adding z-index:999; to my OpacityOn class. This was confusing for me because the div appeared for a second, and I thought that if z-index was the problem that it wouldn't appear at all. It looks like when leaflet maps redrew itself it gave itself a higher z-index. Don't fully understand why, if someone else with more knowledge of leaflet would like to clarify feel free.

Related

change dots on scroll [duplicate]

I'm using Bootstrap 3 and want to achieve this effect when the user scrolls past the large header image on my page. I need the background of the navbar to go from transparent to white. I looked in their code and I KNOW it is done with javascript, and even saw WHERE it was happening I think (look for the ID '#main-header' in that JS)...
Not knowing advanced Javascript aside, I'm looking for a way to apply this to my navigation bar when scrolling past a certain point. The class for my code is called 'navbar' and I would like it to turn white when it passes "#main". Let me know if you need more information, and thanks in advance if anyone wants to help!
The easiest way to accomplish what you're trying to do is a combination of some simple javascript (jQuery powered in this case) and CSS3 transitions.
We'll use JS to check for the windows scroll position on every scroll event and compare it to the distance of the bottom of the #main element - if the scroll position is greater, then we'll apply a class to the body to indicate we've scrolled past #main, and then we'll use CSS to define the nav styling for that "state."
So, our basic markup:
<nav class="nav">
[logo]
</nav>
<div id="main">#main</div>
<div id="below-main">#below-main</div>
And our javascript:
// get the value of the bottom of the #main element by adding the offset of that element plus its height, set it as a variable
var mainbottom = $('#main').offset().top + $('#main').height();
// on scroll,
$(window).on('scroll',function(){
// we round here to reduce a little workload
var stop = Math.round($(window).scrollTop());
if (stop > mainbottom) {
$('.nav').addClass('past-main');
} else {
$('.nav').removeClass('past-main');
}
});
And, our styles:
.nav {
background-color:transparent;
color:#fff;
transition: all 0.25s ease;
position:fixed;
top:0;
width:100%;
background-color:#ccc;
padding:1em 0;
/* make sure to add vendor prefixes here */
}
.nav.past-main {
background-color:#fff;
color:#444;
}
#main {
height:500px;
background-color:red;
}
#below-main {
height:1000px;
background-color:#eee;
}
A working example on Codepen
This is how I did it here. I also employ some scroll throttling and a bit more complicated styling semantics, but this is the gist of it.
If you're using Twitter Bootstrap this can be achieved with the 'Affix' plugin
It's pretty straight forward to set up, here is the documentation
You could probably just use javascript element.scrollTop along with Jquery addClass and removeClass. Haven't tried it myself though.
Here's an overflow link for getting scrollbar position: How to get scrollbar position with Javascript?

Load page Ajax and then slide it into page OR plugin

My site structure is more or less this:
HOME - PAGE1 - PAGE2 - PAGE3.
What I would realize is a site with transition like "a mobile app" between pages, where you click on a button then the new page slide in. Now I'm looking on how to realize that, if using AJAX (that load the page and slide it but I don't know AJAX) or use a plugin (but I can't find anything).
Another alternative is create a single page and then moving into that (would be great find a plugin to do that) but the pages are big so my site will became heavy.
Does anyone have an idea how help me?
Thanks guys!
ps: the site is developed ONLY for tablet and smartphones
there are many ways to implement what you wanted, below i will show you one of them. (example at the bottom of the answer)
you hide the content outside of the screen, and slide it when page loads:
HTML:
<div class="content_div">
<p class="title">HOME</p>
page 1
</div>
CSS:
body{
overflow:hidden;
}
.content_div {
box-shadow:0 0 10px;
border:10px solid black;
height:800px;
left:-1000px;
width:100%;
-webkit-animation:slide_in 800ms ease-out forwards;
position:absolute;
box-sizing:border-box;
}
.title{
font-size:50px;
text-align:center;
}
.nav{
margin-left:20px;
}
#-webkit-keyframes slide_in{
0% {
left:-1000px;
}
100% {
left:0px;
}
}
now when you click a link, you intercept the click using a custom handler, prevent the default redirection, execute a "slide out" animation and once the animation is done, you redirect manually:
the function inside .promise().done() will be executed as soon as all animations on the object are done:
$(function(){
$(".nav").on("click",function(ev){
ev.preventDefault();
$(".content_div").animate({
"margin-left":$(".content_div").width() +100
}).promise().done(function(){
window.location="http://jsfiddle.net/TheBanana/27o989vy/embedded/result/";
});
});
});
here is a Live Example
implement this on every page in your website, and you should have sliding transitions.
change the transitions if you would like a different animation.
NOTE: in jsfiddle it will be a bit messed up because it will open itself inside itself, but on your website it will work as needed.
UPDATE FOR AJAX:
if you would like to avoid the disappearing of pages while window relocates to a new page, you need to load the content from the new page dynamically instead of changing location.
you can do that using plain ajax, or you can use jQuery's ajax extension .load(), it does the same ajax behind the scenes:
$(".nav_waitforajax").on("click", function (ev) {
ev.preventDefault();
$(".content_div").animate({
"margin-left": $(".content_div").width() + 100
}).promise().done(function () {
$(".content_div").load("/three", function () {
$(".content_div").animate({
"margin-left": 0
});
});
});
});
Ajax Example
UPDATE 2: delegated handlers for dynamic content:
//monitors a `mouseover` event on every element inside `.content_div`
//which fits the selector of "*" (everything)
$(".content_div").on("mouseover","*",function(){
$(this).css({
"background":"red"
});
});
Delegates Example

Animating the Border of a TextBox in JavaScript

I am trying to test out a concept for a loading animation, but I have no idea where to start. Basically, I have a text box that is filled in automatically with some JavaScript on the page, but it can take a few seconds to load. I am looking for a way to put something resembling the IE11 indefinite-time progress bar inside it. It would be like a bar about 1/2 of the width of the box and only a few pixels in height that animates across the box. Something like this:
How can I do this in a way that will work in all major browsers (including mobile)?
This is my solution, hope that it helps you in the right direction (and I hope you don't mind using some jQuery):
HTML
<div id="container">
<div id="loading_bar"></div>
<input type="text" value="" id="input">
</div>
CSS
#input {
width:296px;
padding:2px;
position:absolute;
top:0;
left: 0;
border:1px solid #ddd;
margin:0;
z-index:1;
}
#container {
position:relative;
background:#ddd;
}
#loading_bar {
width:0;
padding:0;
margin:0;
background:#00f;
height:4px;
position:absolute;
top:2px;
left:0;
z-index:2;
}
jQuery
function to_zero(){
$("#loading_bar").css({'width':'0'});
}
function to_max(){
$("#loading_bar").animate({'width':'300px'}, 2000);
}
setInterval( function(){to_zero();to_max(); }, 2200);
DEMO
Browsers render borders statically;
About animating the border of a TextBox (presuming input:text or textarea) cross-borwser AND cross-platform is impossible. For a lesser scoped of browser, per say, modern browsers, there is css-level3 with border-image.
But it will be painfull.
About displaying a progress bar upon a TextBox, it will be quite easier, especially if your content is loaded via AJAX. It's all about a container displayed position absolute left top. Then the css animes the container.
See jquery-ui or search the net for 'animated progess bar'
I've always done 2 spans. You have one as the wrapper, with 100px. Then, As the % of loading, you just have the other span being x pixels wide.
You could then make a setTimeout function to keep the animation going. Slowing adding pixels until the inside span is as wide as the wrapper span.
This should load very fast.

Using addClass() and CSS transition on render function in Backbone app not working correctly

In my backbone.js application, I'm trying to fade in the view element after it's been appended. However it doesn't work.
Live example here: http://metropolis.pagodabox.com
var itemRender = view.render().el;
$('#items-list').append(itemRender);
$(itemRender).addClass('show');
However if I add a small setTimeout function, it works.
var itemRender = view.render().el;
$('#items-list').append(itemRender);
setTimeout(function(){
$(itemRender).addClass('show');
},10);
Using fadeIn() also works but I prefer to use straight CSS for the transition as it's more efficient, and prefer not to use any setTimeout "hacks" to force it to work. Is there a callback I can use for append? Or any suggestions? The full code is below:
itemRender: function (item) {
var view = new app.ItemView({ model: item }),
itemName = item.get('name'),
itemRender = view.render().el;
$('#items-list').append(itemRender);
$(itemRender).addClass('show');
app.itemExists(itemName);
}
CSS/LESS:
#items-list li {
padding: 0 10px;
margin: 0 10px 10px;
border: 1px solid #black;
.border-radius(10px);
position: relative;
.opacity(0);
.transition(opacity)
}
#items-list li.show {.opacity(1)}
This "hack" you mention (or some variant of it) is occasionally necessary for web development, simply due to the nature of how browsers render pages.
(NOTE: This is all from memory, so while the overall idea is right please take any details with a small grain of salt.)
Let's say you do the following:
$('#someElement').css('backgroundColor', 'red');
$('#someElement').css('backgroundColor', 'blue');
You might expect to see the background color of #someElement flash red for a brief moment, then turn blue right? However, that won't happen, because browsers try to optimize rendering performance by only rendering the final state at the end of the JS execution. As a result, the red background will never even appear on the page; all you'll ever see is the blue.
Similarly here, the difference between:
append
set class
and:
append
wait 1ms for the JS execution to finish
set class
Is that the latter allows the element to enter the page and AFTER the JS is executed have its style change, while the former just applies the style change before the element gets shown.
So while in general window.setTimeout should be avoided, when you need to deal with these ... complications of browser rendeering, it's really the only way to go. Personally I like using the Underscore library's defer function:
var itemRender = view.render().el;
$('#items-list').append(itemRender);
_(function(){
$(itemRender).addClass('show');
}).defer();
It's the same darn thing, but because it's encapsulated in a library function it feels less dirty to me :-) (and if the "post-render" logic is more than a line or two I can factor it in to a Backbone View method and do _(this.postRender).defer() inside my render method).
You can use CSS animations
#keyframes show {
0% { opacity: 0; }
100% { opacity: 1; }
}
#items-list li {
padding: 0 10px;
margin: 0 10px 10px;
border: 1px solid #black;
.border-radius(10px);
position: relative;
}
#items-list li.show {
animation: show 1s;
}

jQuery Mobile, transparent black overlay effect

I am currently using jQuery Mobile for a Phonegap application and I was wondering how could I add a black overlay that is semi transparent over only the content of a page. I don't want it to cover the top and bottom navbars. This would happen while I place an AJAX call to the server.
This effect is similar to the Twitter iOS app, when you are typing in the search bar.
$('#search').ajaxStart(function() {
// what do I put here?
});
Thank you for your help everyone! Much appreciated.
I agree with meagar (who should make his comment an answer so it can be accepted!) but would also add that if you don't want the overlay div to always be present (but just hidden), you can add it on the fly instead:
$('#search').ajaxStart(function() {
$('#content').wrap('<div class="overlay" />');
});
(#content represents whatever you happen to call your content wrapper and .overlay is the name I happened to choose for mine; easily changed!)
Whenever the Ajax complete callback fires (which will also be where the .hide() would be used in meagar's suggestion), just unwrap it again with this:
$('#content').unwrap();
The rest is CSS.
.overlay {
position: relative;
height: 100%;
width: 100%;
background-color: rgba(0,0,0,0.7);
}
Keep in mind... this may not in fact be the right CSS approach, depending on what's already on your page. The basic idea is that you want it to span just your content area, but there are traps! Floats, absolute positioning of some things... all conspire to make your overlay not cover only the content area. If you run into that trouble, it's a separate SO question though. ;-)
JSFiddle: http://jsfiddle.net/Ff5wV/

Categories