AngularJS: Add a loader element to top of DOM - javascript

Been trying to find out how to do this the best way but haven't found any answers, don't know if I suck at searching or no-one has asked the question. Probably the first one, but anyway.
I'm wondering what the best way is to add an element to the top of the DOM (so that it is on top of everything else) in AngularJS?
My solution to this problem now is to show a modal with the loading spinner in it but I think this is an ugly solution as it shouldn't be that hard to add my own div-element to the DOM that are showing the spinner.
This is the code I have in my modal right now:
<div class="modal-body" style="text-align: center;">
<i class="fa fa-spinner fa-spin fa-5x"></i>
</div>
So you can understand why I think it's unnecessary and ugly to have it in a modal. I've been reading about directives but not really sure how it would look like and how I would show it where I want it to be shown.

I just created something just like this for a project of mine. You can make a div and set the size to 100% of the screen. Set some variable on it so that it shows only when the data is loading.
I used the following CSS for mine:
#overlay {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0,0,0,.5);
z-index:10000;
text-align: center;
vertical-align: middle;
}
Its important to make a large z-index so that it shows on top of everything, and I used a semi-transparent overlay. You can style however you'd like.
And html like the following:
<div id="overlay" data-loading>
<i class="icon-spinner icon-do-spin" ></i>
</div>
FYI - 'icon-do-spin' is a cool class provided by FontAwesome to animate the spinner icon that you are using, and 'data-loading' is a directive I used to check for when all http pending requests are completed. You could just use something like ng-show/ng-hide/ng-if to show or hide the loading div.

In Angular, in order to work with DOM, you need a directive. And to control loader, you need a service. Here is a very simple demo for you. The principle is: directive watches for state change in service and draws "loader" if service says that loader shoud be presented:
index.html
<!DOCTYPE html>
<html data-ng-app="Demo">
<head>
<script data-require="angular.js#1.2.22" data-semver="1.2.22" src="https://code.angularjs.org/1.2.22/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body data-ng-controller="LoaderController as ctrl">
<div data-loader class="loader" data-ng-class="{'visible':Loader.visible}"></div>
<button data-ng-click="ctrl.show(true)">Loader</button>
</body>
</html>
script.js
(function() {
'use strict';
angular.module('Demo', []);
angular.module('Demo').directive('loader', [function(){
return {
'restrict' : 'A',
'controller' : ['$scope', 'Loader', function($scope, Loader){
$scope.Loader = Loader;
}]
}
}]);
angular.module('Demo').factory('Loader', [function(){
var instance = {}
instance.show = function(on){
instance.visible = on;
}
return instance;
}]);
angular.module('Demo').controller('LoaderController', ['$timeout', 'Loader', function($timeout, Loader){
this.show = function(){
Loader.show(true);
$timeout(function(){
Loader.show(false);
}, 5000)
}
}]);
})();
style.css
html, body {
margin: 0;
padding: 0;
}
.loader {
opacity: .5;
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(255, 0, 0, 0.5);
display: none;
}
.loader.visible {
display: block;
}

Related

How can I call a CSS animation on a nested element within a parent element?

I'm looking to remove a class from a nested div element upon focus of the parent. Then I want to replace the class with another that has a CSS animation that will autoplay. I'm looking to do this within multiple elements in the same class as well so it will need to be able to handle more than one. I'm not sure what to do as I've kind of reached to where I believe I should be at this point but to no avail.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<style>
<style>
div {
filter: opacity(0%);
background-color: red;
width: 300px;
height: 300px;
position: relative;
top: 50%;
left: 50%;
z-index: 1;
}
.noGrow {
}
.grow {
animation-name: derp;
animation-duration: 1s;
filter: opacity(100%);
}
#keyframes derp {
from{width: 0px;}
to{width: 300px;}
}
</style>
<body>
<span id="divHolder" tabindex="1">
<div class="noGrow firstDiv">
</div>
</span>
</body>
<script src="jquery.js"> </script>
<script>
var divHolder = $(".divHolder");
var firstDiv = $(".firsDiv");
divHolder.focus(function () {
if($(".firstDiv").hasClass("noGrow")){
$(this).removeClass("noGrow");
$(this).addClass("grow");
console.log("It's working.");
}
});
</script>
</html>
Thank you for any and all help. It is much appreciated.
Looking at your code, these two lines seem to be the problem:
$(this).removeClass("noGrow");
$(this).addClass("grow");
$(this) refers to the divHolder element you are binding the focus event to. If you want to change the class of firstDiv, you'll need to change the lines to this:
firstDiv.removeClass('noGrow');
firstDiv.addClass('grow');
However, based on your CSS, I would suggest using toggleClass, and leaving the noGrow class off completely. Your div becomes:
<div class="firstDiv"></div>
and your JS becomes:
divHolder.focus(function () {
firstDiv.toggleClass('grow');
console.log('growing!');
});
Finally, if you don't know where in the list of descendants your 'growable' div will be, you can use something like find():
divHolder.focus(function(){
$(this).find('div').toggleClass('grow');
// if the div is given an id like #growable we can do this:
// $(this).find('#growable').toggleClass('grow');
});

page.onload function not running

I just started making my first website, and this is the first REAL problem that I have run into. I'm trying to make "Sign in" and "Sign up" buttons that automatically change their text if the user is logged in. To do it, I'm using Javascript to read the localStorage username value, check if it equals null, and then set both button's .innerHTML based on that. The problem? My Javascript won't run. Here's the HTML/Javascript code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Phyre-Home</title>
<link href="Phyre-Home.css" rel="stylesheet">
<script language="javascript">
page.onload function{
var profile = document.getElementById("Profile");
var signout = document.getElementById("SignUpOut");
var username = localStorage.getItem('phyreUsername');
if(username == null) {
profile.innerHTML = "Sign in";
signout.innerHTML = "Sign up";
}else{
profile.innerHTML = username;
signout.innerHTML = "Sign out";
}
}
</script>
</head>
<body>
<header>
<img src="PhyreSiteHeader.bmp" alt="Phyre">
<button id="SignUpOut"></button>
<button id="Profile"></button>
<h1 style="display:none">Fire</h1>
<script language="javascript">
</script>
</header>
<nav>
<ul>
<li><b>Home</b></li>
<li>Profile</li>
<li>Games</li>
<li>Chat</li>
<li>Videos</li>
</ul>
</nav>
<aside>
<h1><b>Page Nav</b><br></h1>
<p><i>This page does not have its own, separate navigation section. Sorry.</i></p>
<h1><b>Ads</b><br></h1>
</aside>
<article>
</article>
</body>
</html>
...And here's the CSS, just in case it matters:
article, aside, figure, figcaption, footer, header, main, nav, section, summary {
display:block;
}
header:img{
max-width:90%;
}
body{
background-color:rgb(75, 75, 75);
margin:0px;
font-family:times new roman, serif;
}
header{
width:100%;
float:top;
}
#SignUpOut{
position:absolute;
top:0%;
right:0%;
}
#Profile{
position:absolute;
top:0%;
right:7.5em;
}
h1{
text-align:center;
font-family:AR BLANCA, times new roman, serif;
}
ul{
list-style-type:none;
margin:0;
padding:0;
}
li{
float:left;
width:20%;
font-size:large;
text-align:center;
border-style:solid;
border-color:rgb(187, 15, 23);
box-sizing:border-box;
background-color:rgb(237, 28, 36);
border-width:2px;
margin-bottom:0.5%;
}
aside{
float:left;
width:20%;
border-style:solid;
border-color:rgb(187, 15, 23);
box-sizing:border-box;
background-color:rgb(237, 28, 36);
border-width:3.5px;
padding:0.5%;
margin-right:0.5%;
}
article{
float:right;
width:79.5%;
border-style:solid;
border-color:rgb(187, 15, 23);
box-sizing:border-box;
background-color:rgb(237, 28, 36);
border-width:3.5px;
padding:0.5%;
}
The culprit is the first Javascript section. Please help if you can, I'm pretty new to HTML5, CSS3, and Javascript.
P.S. I don't have a domain or anything yet, so none of the links are valid.
As far as I know, there's no such thing as page, you probably want window
window.onload = function() {...
or just drop the onload handler and move the script to the bottom, right before </body>
The main issue is that page is not a JavaScript variable.
You could do something like
function myLoadFunction() {
...
}
then
<body onload="myLoadFunction()">
...
</body>
Alternatively you can use window.onload
window.onload = function () {
...
};
I have made you a completely working example here, that does everything you are asking, you may simply click this link to see it in action. You may click the second link in order to see the code and dissect it a bit.
Working Sample (with username)
Just click the link to see it work.
Working Sample (without username)
Just click the link to see it work.
Working Sample (Code)
Just click the link, then click Run with JS to see it work.
Now that I have shown you a completely working solution, allow me to explain why it works.
You do not appear to be using any sort of external library, this means that there is really nothing running overhead to try and help manage when these events fire and such.
You did not declare any kind of id on the elements you were trying to fetch
To demonstrate this, I cite your original code;
var profile = document.getElementById("Profile");
Which was assumed to be functioning on the following <a> tag.
<li>Profile</li>
The problem here is that document.getElementById actually needs an id to get by. This is remedied by ammending the <a> tag with an id, like this.
<li><a id="Profile" href="www.phyregaming.com/profile">Profile</a></li>
The next part of the problem is that you needed this code to run only after the page had loaded. But because you're running just normal javascript, it will run in the order it is seen - unless wrapped inside of a function. Because page.onload is not a valid function, your javascript simply threw an error, and since page.onload is not a real function, it didn't quite understand what its own problem was, so it didn't give you any really useful information.
I fixed this by first wrapping your code in a function, like this.
<script type="text/javascript">
function ready() {
// your javascript code here
}
</script>
What this meant is that when the page hit that part, it created the function, but it did not run it.
Then you needed to run the function, but only once the other parts of the page were ready. We did this using the onload attribute of the <body> tag, like this;
<body onload="ready()">
And that is really all there is to it! From there it was just a matter of assigning the id attributes where needed, and doing a little bit of housekeeping to the HTML and CSS.
I made some changes to help your sample run a bit better, most noticed is that I removed this part of your CSS
#Profile { position: absolute; top: 0%; right: 7.5em; }
I am not sure if you need it to be positioned like that, but from what it looked like, you wanted to make sure that the Profile section is also where the user finds the Login and Logout buttons. I accommodated by moving the <li> that contained those elements to the last ones in the list, this will ensure they are always rendered in the upper right part of the page, for this example.
The first one is just a sample showing how to run the code when the page is loaded. The second shows where you would put your actual code, but I do not know what your specific javascript is aiming to accomplish, so I commented it out.
Here is the complete working code.
You can remove the line localStorage.setItem("phyreUsername", "Ciel"); or comment it out, to see how the behavior changes based on whether or not a username is found.
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script type="text/javascript">
function ready(){
// comment this line out to test different behaviors
localStorage.setItem("phyreUsername", "Ciel");
var username = localStorage.getItem("phyreUsername");
var profile = document.getElementById("SignIn");
var signout = document.getElementById("SignUpOut");
if (username == null) {
profile.innerHTML = "Sign in";
signout.innerHTML = "Sign up";
} else {
profile.innerHTML = username;
signout.innerHTML = "Sign out";
}
}
</script>
</head>
<body onload="ready()">
<nav>
<ul>
<li><b>Home</b></li>
<li>Games</li>
<li>Chat</li>
<li>Videos</li>
<li>
Sign In
Sign Up
</li>
</ul>
</nav>
<aside>
<h1>
<b>Page Nav</b>
</h1>
<p style="font-style: italic">This page does not have its own, separate navigation section. Sorry.</p>
<h1>Ads</h1>
</aside>
</body>
</html>
CSS
article, aside, figure, figcaption, footer, header, main, nav, section, summary {
display:block;
}
body {
margin: 0;
}
nav {
width: 100%;
margin: 0;
padding: 0;
}
ul {
list-style-type:none;
margin:0;
padding:0;
}
li {
float: left;
width: 20%;
font-size: large;
text-align: center;
border: solid rgb(187,15,23) 2px;
margin-bottom: 0.5%;
box-sizing: border-box;
background: rgb(255, 0, 0);
}
body {
background-color:rgb(75, 75, 75);
margin:0px;
font-family:times new roman, serif;
}
header {
width:100%;
float:top;
}
h1 {
font-weight: bold;
}
aside {
float:left;
width:20%;
border-style:solid;
border-color:rgb(187, 15, 23);
box-sizing:border-box;
background-color:rgb(237, 28, 36);
border-width:3.5px;
padding:0.5%;
margin-right:0.5%;
}
article {
float:right;
width:79.5%;
border-style:solid;
border-color:rgb(187, 15, 23);
box-sizing:border-box;
background-color:rgb(237, 28, 36);
border-width:3.5px;
padding:0.5%;
}
I hope that this gives you enough information to really start making some headway. If you have further questions, please ask.

Creating a splash screen using ng-cloak

I'm trying to create a splash screen using AngularJS as described in this talk on the AngularJS youtube channel: http://youtu.be/xOAG7Ab_Oz0?t=10m20s
It uses the ng-cloak directive. Here's the HTML:
<head><head>
<body ng-app>
<!-- inline styles -->
<div class="splash" ng-cloak="">
<p>Loading</p>
</div>
<!-- Rest of app -->
</body>
And the CSS:
[ng-cloak].splash {
display: block !important;
}
[ng-cloak] {
display: none;
}
.splash {
background-color: #428bca;
}
Here is a fiddle: http://jsfiddle.net/TimFogarty/LaBvW/2/
In the fiddle, the splash div does not disappear as the talk said it would. Is there something wrong with this code? Have I made a mistake? How can I implement this splash screen?
This tutorial worked for me: http://www.ng-newsletter.com/advent2013/#!/day/21
Here is a plunker: http://plnkr.co/edit/twGP7gUe9uraYXSr6kQG?p=preview
Note some things:
In the demo I'm manually bootstrapping angular to simulate loading.
The splash screen markup should have ng-cloak attribute
The rest of the template should have ng-cloak attribute
Markup:
<div class="splash" ng-cloak="">
<p>Loading</p>
</div>
<div ng-cloak="">
<h1> app loaded </h1>
</div>
Css:
.splash {
display: none;
}
[ng-cloak].splash {
display: block !important;
}
The second css selector which was:
[ng-cloak] {
display: none;
}
should be
.splash {
display: none;
}
because angular will remove the ng-cloak class when the app is bootstrapped

Creating a GWT widget that others can embed in their website?

I've created a widget in GWT and I would like to be able to give users a small snippet of HTML that they can embed in their website so my widget will be rendered there.
I don't believe an iframe would be appropriate as one requirement is that clicking any links on my widget should take the user to my website (not just change the content of the iframe).
Any help would be greatly appreciated.
P.S. I tried embedding the following, but no luck:
< script src="http://embeddedapptest.appspot.com/embeddedapp/embeddedapp.nocache.js" >< /script >
< div id="foo" / >
It is possible. The snippet will need to be like
<script src="yourmodule.nocache.js"></script>
<div id="foo"/>
Then in your entry point do this:
RootPanel root = RootPanel.get("foo");
// add your things here. root.add(...);
You will need to be careful not to step on the outer page's styling and vice versa but compiled CSS should go a long way to helping that.
This is the technique used to embed an APIs Explorer in Google APIs documentation.
I don't think it's possible to do it now. But in the future you can use Web Components to do that.
But there's the possibility to export a GWT/Java API using gwt-exporter. That makes it possible to automatically create a JavaScript API. gwtchismes uses this to export a JavaScript version of GWT widgets. You can find a tutorial about it in their wiki.
In NetBeans GWT project
mycss.css:
body, html,div.wrap-frame{
margin: 0;
padding: 0;
widht: 100%;
height: 100%;}body{
background: white;
}
.row1or3 {
width: 100%;
height: 10%;
background: blue;
text-align: center;
}
.row2{
width: 100%;
height: 80%;
background: yellow;
text-align: center;
display:flex;
}
.wrapper{
width:100%;
height: 100%;
}
.box{
float:left;
height: 100%;
}
.box:nth-child(1){
width:25%;
background-color:red;
}
.box:nth-child(2){
width:50%;
background-color:green;
}
.box:nth-child(3){
width:25%;
background-color:yellow;
}
welcomeGWT.html
<html>
<head>
<script id=ft type="text/javascript" src="org.yournamehere.Main/org.yournamehere.Main.nocache.js"></script>
<meta name='gwt:module' content='org.yournamehere.Main=org.yournamehere.Main'>
<link rel="stylesheet" href="mycss.css">
</head>
<body>
<div class="row1or3"> Row1
</div>
<div class="row2">
<div class="wrapper">
<div class="box">
Left Side Menu
</div>
<div class="box" id="mydiv">
</div>
<div class="box">
Right Side Menu
</div>
</div>
</div>
<div class="row1or3">
Row3
</div>​
</body>
MainEntryPoint.java
public class MainEntryPoint implements EntryPoint {
/**
* Creates a new instance of MainEntryPoint
*/
public MainEntryPoint() {
}
/**
* The entry point method, called automatically by loading a module that
* declares an implementing class as an entry-point
*/
public void onModuleLoad() {
final Label label = new Label("Hello, GWT!!!");
final Button button = new Button("Click me!");
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
label.setVisible(!label.isVisible());
}
});
RootPanel root = RootPanel.get("mydiv");
root.add(button);
root.add(label);
}
}
Now you can name any div element of any html page as id=mydiv and add the compiled GWT jscript.
I have tested.

Why isnt my javascript working?

All my code seems to work except my javascript am I doing something wrong?
Thanks Im only a beginner!
I am trying to make the background change when the mouse goes over the 'Tags' tab but it wont do it? What is going on?
HTML:
<html>
<head>
<script language="JavaScript" type="text/javascript">
// This changes color on mouseover, leaves existing color box.
$('.tab-item').mouseover(function() {
$(this).addClass("tab-mouseover");
}).mouseout(function() {
$(this).removeClass("tab-mouseover");
});
// This changes color when clicked, removed old color box.
$('.tab-item').click(function() {
$('.tab-item').removeClass("tab-selected");
$(this).addClass("tab-selected");
});-->
</script>
<link href="arg.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="tab-item tab-selected" id="search-box">
Search
</div>
<div class="tab-item" id="tag-box">
Tags
</div>
</body>
</html>
CSS:
.tab-item {
-moz-border-radius: 10px;
border-radius: 10px;
font: 14px helvetica;
color: #000;
height: 20px;
float: left;
margin: 5px 5px 5px 5px;
padding: 5px 5px 5px 5px;
position: relative;
width: 75px;
}
.tab-mouseover {
background: #bdbdbd;
}
.tab-selected {
background: #c0c0c0;
}
Thanks!
James
You're using jQuery but haven't included it.
You also need to put your jquery code into the jquery ready event:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript">
// This changes color on mouseover, leaves existing color box.
$(function(){
$('.tab-item').mouseover(function() {
$(this).addClass("tab-mouseover");
}).mouseout(function() {
$(this).removeClass("tab-mouseover");
});
// This changes color when clicked, removed old color box.
$('.tab-item').click(function() {
$('.tab-item').removeClass("tab-selected");
$(this).addClass("tab-selected");
});
});
-->
</script>
You haven't added your library (jQuery, I think) as a source here.
Add it like this:
<script src='http://foo.com/bar/library.js'></script>
If you are, indeed using jQuery, you can directly add the following code to make it work:
<script src='http://code.jquery.com/jquery-1.6.4.js'></script>
Note that the above means you are depending on the availability of the jQuery website and not your own.
As per James' comment on this, yes, you can scrap the jQuery completely, but I'd recommend you to learn JavaScript yourself instead of copying code from a website. If you want to change the background color of the field onmouseover, use code like this:
<div onmouseover="this.style.backgroundColor='#bdbdbd';" onmouseout="this.style.backgroundColor='white';">Search</div>
Or
<div onmouseover='this.className="tab-mouseover"' onmouseout='this.className=""'>Search</div>
Or without JavaScript and just simple CSS:
<style>
.tab-mouseover:hover{
background: #bdbdbd;
}
</style>
<div class='tab-mouseover'>Search</div>
I can't answer the latter part, because I don't understand the use of deleting and then adding the same class to an element onclick.
Well, first, you haven't included a link to the jQuery library in your code. As a result, your code won't work, wherever you put it.
Second, since your code is in a script element at the head of the document, it will execute before the body of the document has been rendered. You need to put it in a
$(document).ready(function() {
/*
* Your code here
*/
});
block.
Try this:
$('.tab-item').hover(
function() {
$(this).addClass('tab-mouseover');
},
function() {
$(this).removeClass('tab-mouseover');
}
);
$('.tab-item').click(function() {
$('.tab-selected').removeClass('tab-selected');
$(this).addClass('tab-selected');
});
http://jsfiddle.net/7dDTv/1/

Categories

Resources