Data loading indicator for when Ember.js objects are loading? - ember.js

We're having trouble getting some form of visual indication that a 'page' is loading in our Ember App.
Tried both a gif method and also Spin JS. Both fail as they are very laggy and only fully load when all the Ember objects have loaded. A similar problem to this question.
What methods are other people using in their public facing builds?
Edit: This is when the app is loading for the first time. The initial load is long enough to require some form of visual indication.

You could add an overlay to your document with an loading indicator. When you add it via CSS it is loaded before Ember is initialized. After ember is initialized you could remove the overlay.
Below an example how I might implement it:
HTML:
<html>
<head> ... load dependencies ... </head>
<body class="loading"> ... handlebars templates ... </body>
</html>
CSS:
body.loading:after {
content: '';
background: rgba(255,255,255,.3) url(images/loader.gif) 50% no-repeat;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
}
Ember code:
App.ApplicationView = Ember.View.extend({
removeLoader: function() {
$('body').removeClass('loading');
}.on('didInsertElement')
});
This way before Ember is initialized an loading indicator is showed, but when Ember is done initializing the loader is removed.

You can use jQuery ajax callbacks for this:
$(document).ajaxStart(function(){ console.log("ajax started")})
$(document).ajaxStop(function(){ console.log("ajax stopped")})
This will work for all ajax requests.

Related

Ember JS Implement a splash screen / loading startup screen

What is the best way to implement a loading screen in Ember 2.5? What I want to achieve is: show splash screen -> load data in background -> when DOM is ready, hide splash screen.
I tried several options, but I cannot achieve to hide the splash screen when the document is ready. I am loading a large table, so it will take some time to finish the DOM, so model-ready is not the right hook.
I did this by adding custom HTML (simple loading div) to the app/index.html:
<body>
<div class="loading-overlay" id="initialLoading"></div>
{{content-for "body"}}
<script src="assets/vendor.js"></script>
<script src="assets/event.js"></script>
{{content-for "body-footer"}}
</body>
Then I added the following to my app/application/route.js:
actions: {
loading(transition/* , originRoute*/) {
let controller = this.get('controller');
if(controller) {
controller.set('currentlyLoading', true);
}
transition.promise.finally(function() {
$("#initialLoading").remove();
if(controller) {
controller.set('currentlyLoading', false);
}
});
}
}
In my app/application/template.hbs I also had to add the loading div:
{{#if currentlyLoading}}
<div class="loading-overlay"></div>
{{/if}}
So what does happen?
index.html is loaded and no javascript is parsed yet: your loading screen is visible.
index.html is loaded and your javascript has been parsed. ember.js calls the loading action and sets currentlyLoading to true: both loading screens are shown.
the transition is complete, the first loading and second loading screen get removed
for every transition that is now happening, the loading screen is shown. To remove this behaviour, remove the second loading screen logic.
I hope it helps.

Foundation interchange image swap does not work correctly

The problem:
When I resize the window the images will only sometimes change. It's almost like they get stuck / the resize event is not being captured properly by foundation. If I start resizing the window like a rabid monkey it will occasionally swap the image. If I resize the window according to the media queries and then refresh the page the correct image renders. This appears to be a resize only issue.
Other details:
I have just a regular .html file (new site hosted from IIS on a separate machine) with a simple demo of Interchange image swapping.
If I manually call: $(document).foundation("interchange", "resize"); the image will swap correctly.
Foundation version 5.3.1
Testing in Chrome 36 and Firefox 31.
So far the only built in media query that works is (default). (medium), (large) etc. do nothing, I have to write out the actually query to get it to work (or manually create them using named_queries. This may be an unrelated problem but does seem strange to me.
<html>
<head>
<title>Interchange</title>
<script src='//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'></script>
<script type='text/javascript' src='/foundation.js'></script>
<script type='text/javascript' src='/foundation.interchange.js'></script>
<link rel='stylesheet' href='/foundation.css' />
<link rel='stylesheet' href='/normalize.css' />
<script type='text/javascript'>
$(function () {
$(document).foundation();
$(document).on('replace', function (e, newVal) {
console.log(newVal);
});
// Adding this horrible hack will make it work 100% of the time.
// BUT THIS SHOULD NOT BE NECESSARY!
//$(window).resize(function(){
// $(document).foundation("interchange", "resize");
//})
});
</script>
</head>
<body>
<img data-interchange="[/images/space-small.jpg, (default)], [/images/space-medium.jpg, (only screen and (min-width: 641px))], [/images/space-large.jpg, (only screen and (min-width: 1000px))]">
</body>
</html>
I found the answer to my own question and it was indeed that odd media queries issue I described in the OP that lead me to the problem.
Foundation's javascript is dependent on the Foundation CSS existing before it initializes.
All I had to do was make sure the CSS link was above the script include and everything started working as expected.
Not sure this will help anyone, but I was getting the same issue but ONLY on Chrome. I added the foundation.min.css to my page like b1j suggested and voila! unfortunately though as I used the SASS version I couldn't just leave this included into the page as I would have double the amount of css included into my page. So I pasted the foundation.css contents into a style tag in the head of my document and deleted its contents bit by bit until I found the piece of css that fixed it. Here it is:
meta.foundation-mq-small {
font-family: "/only screen/";
width: 0em; }
meta.foundation-mq-medium {
font-family: "/only screen and (min-width:40.063em)/";
width: 40.063em; }
meta.foundation-mq-large {
font-family: "/only screen and (min-width:64.063em)/";
width: 64.063em; }
meta.foundation-mq-xlarge {
font-family: "/only screen and (min-width:90.063em)/";
width: 90.063em; }
meta.foundation-mq-xxlarge {
font-family: "/only screen and (min-width:120.063em)/";
width: 120.063em; }
Not sure why this wasn't compiled into my CSS but I will look, but incase anyone needs a quick fix, this should do it!

Foundation Magellan - check if it's sticky

How can I check with JS if the Magellan bar (or the element I added "data-magellan-expedition='fixed'") is sticky while scrolling?
I want to add a class if it's sticky. Otherwise the class should be removed.
Adding the below script end of page (with the other scripts) then using the .navstuck class in my SCSS worked for me:
<!--for Sticky Nav per http://codepen.io/zurbchris/pen/rxMaoX-->
<script>
$(document).foundation();
$('.sticky').on('sticky.zf.stuckto:top', function(){
$(this).addClass('navstuck');
}).on('sticky.zf.unstuckfrom:top', function(){
$(this).removeClass('navstuck');
})
console.log(Foundation.version);
</script>
when the sticky is activated the div gets a css attr of
style="position: fixed; top: 0px;"
thus you can use that to add a class
if ($('#yourElement').css('position') == 'fixed')
{
// true
}

Styling the Ember rootElement

I've been banging my head against this for over a day and no amount of experimenting, Google'ing, or Stack Overflow searching has helped.
I'm developing an Ember/Vert.x app that has one Ember Route that accepts "real-time" push-data via SocksJS. This is working beautifully, including the successful implementation of dynamic (Ember) templates.
What I need now is the ability to set styles on the rootElement (rootElement is body). I've tried umpteen different approaches, including resorting to jQuery calls. Nothing will place a style on the body tag. I CAN get the style attribute set on the 1st div inside the body tag by doing:
App.ApplicationView = Ember.View.extend({
attributeBindings: ['style'],
style: "background-color: blue; background-image: url('" + App.currentProgram.backgroundImage + "')"
});
This renders:
<div id="ember325" class="ember-view" style="background-image: url('img/bg/1.png')">...</div>
However, I really want to style the body tag dynamically.
Any help would be GREATLY appreciated as this is a blocking item for my prototype client demo next week.
You can use the didInsertElement method, to know when the dom is inserted, and update the body element using this.$().parent().
App.ApplicationView = Ember.View.extend({
didInsertElement: function() {
this._super();
this.$().parent().css({
"background-color": "blue",
"background-image": "url('" + App.currentProgram.backgroundImage + "')"
});
}
})
Live sample http://jsfiddle.net/X5TmH/

Ember.js: Wrapping JQuery component (Minicolors)

I try to integrate the Minicolor JQuery component in Ember.js application.
Integration should be easy but it does not work for me... (input is displayed but without JQuery component)...
Minicolor integration guide:
https://github.com/claviska/jquery-miniColors
From doc: simply insert the js file and add the following input:
My js file:
App.ColorPicker = Em.TextField.extend({
type: 'minicolors',
attributeBindings: ['name'],
willInsertElement: function() {
;
}
});
The html file
{{view App.ColorPicker placeholder="Background color" name="color" valueBinding="App.MyController.backgroundColor"}}
I believe your issue is that ember is dynamically adding the <input type='minicolors' ... /> element after the initialization code for minicolors has already executed, causing your new minicolors input to not be initialized.
I got your example working by using the didInsertElement event instead of willInsertElement event to force minicolors to create the dynamically added App.ColorPicker element. The willInsertElement fires when the element is going to be inserted, but hasn't yet, and the didInsertElement will fire after the element has been inserted. I used the latest files from the minicolors github repository.
App.ColorPicker = Em.TextField.extend({
type: 'minicolors',
attributeBindings: ['name'],
didInsertElement: function() {
$.minicolors.init();
}
});
The only other issue I had was needing to make sure the css file and the png with the color picker graphical elements could be loaded. Apparently if the css and png files are not loadable the js portion doesn't work.