Random changing backgrounds WITH fade effect - random

Aloha Stockoverflow.
In advance, thank you!
I am trying to modify my randomly changing background on my webpage, to add a FADE effect, so the change from 1 background to another is not so sudden and sharp.
I have tried to search through the web endlessly for a solution to my issue, but it all points towards adding a jQuery plugin which I would preferably avoid if it is possible.
My working code is as follows and needs to have added some kind of fadein / fadeout effect.
<script type="text/javascript">
var num;
var temp=0;
var speed=5000; /* this is set for 5 seconds, edit value to suit requirements */
var preloads=[];
/* add any number of images here */
preload(
'images/bg1.jpg',
'images/bg2.jpg',
'images/bg3.jpg',
'images/bg4.jpg',
'images/bg5.jpg'
);
function preload(){
for(var c=0;c<arguments.length;c++) {
preloads[preloads.length]=new Image();
preloads[preloads.length-1].src=arguments[c];
}
}
function rotateImages() {
num=Math.floor(Math.random()*preloads.length);
if(num==temp){
rotateImages();
}
else {
document.body.style.backgroundImage='url('+preloads[num].src+')';
temp=num;
setTimeout(function(){rotateImages()},speed);
}
}
if(window.addEventListener){
window.addEventListener('load',rotateImages,false);
}
else {
if(window.attachEvent){
window.attachEvent('onload',rotateImages);
}
}
</script>
Thank you very much for taking the time to look at it. :)

How to do it without plugins:
Use 2 layers for the background image, position them on top of each other.
Init the page with the first image on the bottom layer, make the top layer invisible (using CSS opacity property, make sure to Google this, different browsers use different approaches).
When fading:
Set the new image for the top layer.
Use a short, looping (frameduration < 40ms) setTimeout to increment the opacity of your top layer to 1. Use increments of 1/(speed/frameduration).
When comletely faded in, set the bottom layer to use the new (now visible) image, and set the top layer to opacity 0.
Like this:
<html>
<head>
<script type="text/javascript">
var num;
var current=0;
var speed=5000; /* this is set for 5 seconds, edit value to suit requirements */
var fps = 25;
var fadeDuration = 1000;
var opacityIncrement = 1/(fadeDuration/(1000/fps));
var preloads=[];
var topLayerOpacity = 0;
var topLayer = document.createElement("div");
var bottomLayer = document.createElement("div");
setOpacity(topLayer, 0);
/* add any number of images here */
preload(
'images/bg1.jpg',
'images/bg2.jpg',
'images/bg3.jpg',
'images/bg4.jpg'
);
function loadComplete(){
//add layers to background div
document.getElementById('backgroundContainer').appendChild(bottomLayer);
document.getElementById('backgroundContainer').appendChild(topLayer);
rotateImages();
}
function preload(){
//preload images
for(var c=0;c<arguments.length;c++) {
preloads[preloads.length]=new Image();
preloads[preloads.length-1].src=arguments[c];
}
}
// selecte new random image from preloads and start fade-in
function rotateImages() {
num=Math.floor(Math.random()*preloads.length);
//don't select current image
if(num==current){
rotateImages();
}
else {
topLayer.style.backgroundImage = 'url('+preloads[num].src+')';
current=num;
//start fade-in
fadeIn();
setTimeout(function(){rotateImages()},speed);
}
}
// fade in topLayer
function fadeIn(){
if (topLayerOpacity < 1){
topLayerOpacity += opacityIncrement;
setOpacity(topLayer, topLayerOpacity);// opacityIncrement);
setTimeout(fadeIn, 1000/fps);
}else{
fadeInComplete();
}
}
//return opacity for element
function getOpacity(el){
alert (el.style.opacity);
return el.style.opacity;
}
//sets opacity on element
function setOpacity(el, val){
el.style.opacity = val;
el.style.filter = 'alpha(opacity=' + val*100 + ')';
}
//called when fadeIn completed
function fadeInComplete(){
bottomLayer.style.backgroundImage = topLayer.style.backgroundImage;
topLayerOpacity = 0;
setOpacity(topLayer, topLayerOpacity);
}
if(window.addEventListener){
window.addEventListener('load',loadComplete,false);
}
else {
if(window.attachEvent){
window.attachEvent('onload',loadComplete);
}
}
</script>
<style type="text/css">
#backgroundContainer{
width:100%;
height:100%;
position:absolute;
/*background-color:green;*/
}
#backgroundContainer div{
width:100%;
height:100%;
position:absolute;
top:0;
}
.page {
width:100%;
text-align:center;
position:absolute;
}
.contents{
width:400px;
margin:0 auto;
background-color:lightblue;
}
</style>
</head>
<body>
<!-- holds background layers -->
<div id="backgroundContainer"></div>
<!-- substitutes for 'body' on this webpage -->
<div class="page">
<!-- contents for your webpage, through css centered within page-div -->
<div class="contents">
<p>Contents</p>
</div>
</div>
</body>
</html>
OR
Use jQuery/mootools/script.aculo.us/...
Best of luck!

Related

Set a NativeScript Label line height on iOS

I have a label with a large font size, and the default line-height is quite loose for my taste. I'd like to reduce it to less than the default.
Providing a line-height value larger than the font-size does increase the line spacing, but a smaller value (or negative value) does not reduce it to be smaller than the default on iOS.
From a GitHub issue, I got this snippet that I updated to work with the latest NS;
import { Label } from "#nativescript/core/ui/label";
export function setIOSLineHeight(label: Label, lineHeight: number){
const iosLabel = label.nativeView;
let attributedString;
if (iosLabel.attributedText) {
attributedString = iosLabel.attributedText;
} else {
attributedString = NSMutableAttributedString.alloc().initWithString(iosLabel.text);
}
let range = new NSRange({ location: 0, length: iosLabel.text.length });
const paragraphStyle = NSMutableParagraphStyle.alloc().init();
paragraphStyle.lineSpacing = 0;
paragraphStyle.minimumLineHeight = lineHeight;
paragraphStyle.maximumLineHeight = lineHeight;
attributedString.addAttributeValueRange(NSParagraphStyleAttributeName, paragraphStyle, range);
iosLabel.attributedText = attributedString;
}
However, calling this method in the mounted() lifecycle method does not have any effect for any value of lineHeight - even ones that do have an effect via the CSS property:
<template>
<Page ref="page">
<Label ref="topLine" text="Hello this is a text that flows onto multiple lines" textWrap="true" />
</Page>
</template>
<script>
import { isIOS } from 'tns-core-modules/platform';
import { setIOSLineHeight } from '../label-helper.ts';
export default {
mounted() {
if (isIOS) {
/* Has no effect, regardless of value */
setIOSLineHeight(this.$refs.topLine, 40);
}
}
}
</script>
<style lang="scss" scoped>
Label {
font-size: 60;
/* Does work */
line-height: 100;
/* Does not work */
line-height: 40;
}
</style>
How can I reduce the line height of my Label to a value smaller than the font size?
In NativeScript I have used the following code to handle both IOS and Android for Line Spacing
function labelLineHeight(nsLabel) {
if(isIOS){
var label= nsLabel.ios;
var attributedString;
if(label.atributedText){
attributedString = label.atributedText;
}
else{
attributedString=NSMutableAttributedString.alloc().initWithString(label.text);
}
var paragraphStyle = NSMutableParagraphStyle.alloc().init();
paragraphStyle.lineSpacing = 5;
var range= NSMakeRange(0, label.text.length);
attributedString.addAttributeValueRange(NSParagraphStyleAttributeName, paragraphStyle, range);
label.attributedText = attributedString;
}
if(isAndroid){
var label = nsLabel.android;
//Default spacing is 20% of text size
//setLineSpacing(add,multiplyby);
label.setLineSpacing(12, 1);
}
}
Also follow this thread for more inputs on the line-spacing. You can see the pull request too for reference.

How to start a HTML 5 video from a particular position in laravel 5

i new start a video in a specific position when the web is loading, i get the position using a eloquent var coming from the controler.
I also use jquery for other functions in the same view.
I have checked the variables arrive correctly so I do not know where is the error.
The strange thing is this method only works if I show a alert popup before in firefox. (not work in chrome or other browser).
This is my code:
<video id="video" style="display:none; width:100%; height:100%;" autoplay>
<source src="/files/convert/videos/{{$moviesNow->url}}" type="video/mp4" />
Su navegador no soporta el tag video.
</video>
<script>
var vid = document.getElementById("video");
var time = {{$difTime}};
var isPlaying = {{$playNow}};
var moviesArr = [];
};
var j = jQuery.noConflict();
j(document).ready(function() {
if(time >= 0 && isPlaying == 1){
//vid.currentTime = time;
}
});
function setCurTime() {
vid.currentTime = time;
};
</script>
Also i trying use:
document.getElementById('video').addEventListener('loadedmetadata', function() {
this.currentTime = time;
}, false);
But the problem is not solved.
The loadedmetadata event is helpful, but it doesn't ensure that the section of video you are trying to access is seekable yet. You could try a simpler solution using Media Fragments:
Just add #t=120 to the end of the video url to have it auto-forward to that spot. Like this:
video {
height: 180px;
width: 320px;
}
<video src="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4#t=120" controls autoplay></video>

Jquery Mobile + Phonegap improve listview performance

In my JQM 1.4 + Phonegap 3.6 app, I am using a listview as in the following code.
HTML:
<div id="boardselection">
<ul id="modelsListview" data-role="listview" data-icon="false">
</ul>
</div>
JS:
function resetModelsListView(prodata, firsttime, funfeatureOn, specificBrand, specificPro) {
console.log("on passe dans resetModelsListView");
// funfeatureOn = 0;
//debug timer
var time = [];
var dummy;
var i;
var listviewdeferred = $.Deferred();
var optionspro = '';
var optionsbrand = '';
var optionsmodel = '';
var countpros = 0;
var countbrands = 0;
var countmodels = 0;
var chosenmodelListViewHandle = $('#modelsListview');
var chosenbrandSelect = $('#chosenbrand');
optionsmodel += '';
var alreadyusedbrands = [];
prodata.sort(SortByName);
// get previously selected model to reselect it later
//var previouslySelectedModelId =parseInt(chosenmodelSelect.find('li:selected').val());
if (!funfeatureOn) {
prodata.sort(SortByModel);
} else {
prodata.sort(SortByFUN);
}
//populate model list
//~ if (firsttime){
//~ var perfIsChecked = true;
//~ var smallwaveIsChecked = true;
//~ var stepupIsChecked = true;
//~ }else {
var perfIsChecked = $('#checkboxperf').is(":checked");
var smallwaveIsChecked = $('#checkboxsmallwave').is(":checked");
var stepupIsChecked = $('#checkboxstepup').is(":checked");
//~ }
console.log("perfIsChecked, smallwaveIsChecked, stepupIsChecked =");
console.log(perfIsChecked);
console.log(smallwaveIsChecked);
console.log(stepupIsChecked);
//if none checked then no filter
if (!perfIsChecked && !smallwaveIsChecked && !stepupIsChecked) {
perfIsChecked = true;
smallwaveIsChecked = true;
stepupIsChecked = true;
}
for (i = 1; i < prodata.length; ++i) {
if (specificBrand && prodata[i]['brand'] != specificBrand) {
} else if (specificPro && prodata[i]['name'] != specificPro) {
} else {
if (prodata[i]['fun'] == 0 && perfIsChecked) {
optionsmodel += '<li><a class="optionfuninit" href="#" data-proid="' + prodata[i]['id'] + '"><div class="listviewtexts"><span class="listviewtextsmodel">' + prodata[i]['model'] + '</span> - <span class="listviewtextspro">as surfed by ' + prodata[i]['name'] + '</span></div></a></li>';
} else if (prodata[i]['fun'] == 1 && smallwaveIsChecked) {
optionsmodel += '<li><a class="optionfuninit" href="#" data-proid="' + prodata[i]['id'] + '"><div class="listviewtexts"><span class="listviewtextsmodel">' + prodata[i]['model'] + '</span> - <span class="listviewtextspro">as surfed by ' + prodata[i]['name'] + '</span></div></a></li>';
} else if (prodata[i]['fun'] == 2 && stepupIsChecked) {
optionsmodel += '<li><a class="optionstepupinit" href="#" data-proid="' + prodata[i]['id'] + '"><div class="listviewtexts"><span class="listviewtextsmodel">' + prodata[i]['model'] + '</span> - <span class="listviewtextspro">as surfed by ' + prodata[i]['name'] + '</span></div></a></li>';
} else if (prodata[i]['fun'] == 3 && smallwaveIsChecked) {
optionsmodel += '<li><a class="optionkidsinit" href="#" data-proid="' + prodata[i]['id'] + '"><div class="listviewtexts"><span class="listviewtextsmodel">' + prodata[i]['model'] + '</span> - <span class="listviewtextspro">as surfed by ' + prodata[i]['name'] + '</span></div></a></li>';
}
if (prodata[i]['model'] !== prodata[i - 1]['model']) { //eliminate name duplicates if prodata sorted by model
countmodels = countmodels + 1;
}
}
}
chosenmodelListViewHandle.html(optionsmodel);
if (chosenmodelListViewHandle.listview("option", "disabled")) {
chosenmodelListViewHandle.listview("option", "disabled", false);
}
//~ if (resetModelsOnly) {
//~ if ( !isNaN(previouslySelectedModelId) ) {
//~ chosenmodelListViewHandle.find('li[href="' + previouslySelectedModelId + '"]').attr("selected", "selected").siblings('li').removeAttr('selected');
//~ }
//~ }
//~ highlightFunModels(funfeatureOn, 1);
//~ highlightStepupModels(funfeatureOn, 0);
chosenmodelListViewHandle.listview("refresh", true);
$("#chosenmodel-button").addClass("ui-icon-carat-d ui-btn-icon-right");
if (!funfeatureOn) {
} else {
$('ul#chosenmodel-menu').find("a.ui-btn:contains(SMALL-WAVE)").addClass("optionfun");
$('ul#chosenmodel-menu').find("a.ui-btn:contains(STEP-UP)").addClass("optionstepup");
}
prodata.sort(SortById); //we need this otherwise prodata is not usable by the $('#chosenpro').trigger
$("#chosenmodel-button span").attr({ 'data-i18n': 'select.3' });
$("#boardselection").i18n();
listviewdeferred.resolve();
return listviewdeferred;
}
This dynamically displays a long list of images and text, depending on wether filters (checkboxes) are checked or not, and this list is quite long to generate and particularly difficult to scroll in iOS.... The performance is bad.
Can you help me figure out a way to improve the performance.
The accepted answer is not correct. Your code is slow, but not because of jQuery Mobile. Take a look at the loop in your jsFiddle: jsfiddle.net/L3gr46s8/4
for (i = 0; i <= 50; i++) {
$('ul[data-role="listview"]').append('<li>' + 'list item ' + i + '</li>');
$('ul[data-role="listview"]').listview('refresh');
}
There are a couple very significant problems in those four lines of code.
First, your code executes two DOM traversals to locate the ul on the page. You could execute $('ul[data-role="listview"]') before the loop and store the result in a variable:
var listView = $('ul[data-role="listview"]');
Second, your code inserts the list item directly to the DOM and you instruct jQuery Mobile to immediately apply markup enhancement with .listview('refresh');. This is extraordinarily expensive! Especially on under-powered mobile devices. Depending upon the browser and page layout, those two lines could trigger a full page re-draw with every iteration of the loop.
You should render the content as a DocumentFragment (in memory), insert it all to the DOM in one action and tell JQM to enhance the markup once at the end. Even simply moving $('ul[data-role="listview"]').listview('refresh'); out of the loop would be a dramatic improvement.
Here is some additional reading on the importance of rendering your content first in memory before inserting it into the DOM:
How expensive is it to dynamically insert DIVs using JavaScript?
John Resig - DOM DocumentFragments
To put it short, jQuery Mobile is simply slow.
I have a dynamic listview in my app and also had performance issues when using jQuery Mobile. I came to a conclusion that the issue was in rendering and was caused by jQuery Mobile. I implemented my own styling and the rendering time came down from 170ms to 25ms.
Here's some backup to my point (3 articles): http://apachecordova.blogspot.fi/search/label/jQuery%20Mobile
EDIT:
As an answer to your question in the comments, I don't think it would help if I posted my code here. The whole point is that you only write the code YOU need. My listview probably is totally different than yours.
To prove my point (again), I made two listviews. The first one is a basic jQM listview. The other one is styled with custom CSS and it's pretty close to what I use in my app. There's a button in both which renders the listview. What is happening under the hood is very different:
jQM: As you can see, there's a lot of stuff (that you may not need) going on
Custom CSS: attached an event listener to all the elements to make the comparison more fair
These profiles have been recorded with Chrome Developer Tools and the difference is obvious: 173ms vs 12ms. This custom CSS took me about 5min to write:
#custom-listview {
list-style-type: none;
padding: 0px;
margin: 0px;
}
#custom-listview li {
display: block;
position: relative;
overflow: visible;
}
#custom-listview a {
display: block;
position: relative;
text-overflow: ellipsis;
text-decoration: none;
color: white;
padding: .7em 1em;
font-size: 16px;
background-color: #333;
border: solid 1px #1f1f1f;
overflow: hidden;
white-space: nowrap;
font-family: sans-serif;
}
I had to add some code here, because SO won't let me link to Fiddle without:
jQM
Custom CSS
I'm not saying jQuery Mobile is all bad. It's good for many things. But if you have complex structure and/or a lot of data, the performance may become an issue especially in PhoneGap apps. That's the conclusion I have come to with my little experience.

How to scrollTop a div whose content is managed by AngularDart?

I have a div holding some chat history. I would like for the div content to scroll when it becomes full. I have this working using jQuery in another project, but what would be the proper AngularDart way to achieve this?
Simplifying a bit, in my HTML I have
<div class="chatHistory">{{ctrl.text}}</div>
(using style white-space:pre) and in my controller I have the method
void addToChatHistory(String msg) {
text += msg;
var elt = querySelector(".chatHistory");
elt.scrollTop = elt.scrollHeight;
}
Issues:
This code scrolls the div content but not quite enough because it sets the scrollTop too quickly; i.e., even before the .chatHistory can be updated by Angular.
Besides this (partial) solution doesn't feel very Angular in style given the use of querySelector.
I tried setting up a watch on the text field but that also fires too early. Suggestions?
For the first issue you can use Timer.run to defer the scroll execution :
Timer.run(() => elt.scrollTop = elt.scrollHeight);
For the second issue you can inject the Element managed by your controller and use querySelector on it :
MyController(Element e) : elt = e.querySelector('.chatHistory');
EDIT
I published a package containing this directive: http://pub.dartlang.org/packages/bwu_angular
-------
I would create a Directive/Decorator like NgEventDirective but for the resize event and add it to your div. In the event handler you set your scrollTop property.
I found contradictory info about the resize event.
DART - Resize div element event says it is available everywhere
Onresize for div elements? is a workaround for browsers that don't support this event.
another page covering this topic: http://marcj.github.io/css-element-queries/
I tried to create an Angular implementation for the 'workaround' (2nd link) but run into this issue https://code.google.com/p/dart/issues/detail?id=18062 which contains info about a workaround but I didn't yet find time to implement it.
EDIT
I checked my attempt and it worked in Dartium with the version I downloaded today (Dart VM version: 1.4.0-dev.4.0 (Thu May 1 04:06:09 2014) on "linux_x64").
I haven't tried in other version since I created the issue.
(The code should be improved to make the directive more generic - the event method should be assignable by an attribute not hardcoded)
index.html
<!DOCTYPE html>
<html ng-app>
<head>
<script src="packages/web_components/platform.js"></script>
<style>
.resize-triggers {
visibility: hidden;
}
.resize-triggers, .resize-triggers > div, .contract-trigger:before {
content: " ";
display: block;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
.resize-triggers > div {
background: #eee;
overflow: auto;
}
.contract-trigger:before {
width: 200%;
height: 200%;
}
</style>
<style>
#my_element {
height: 200px;
overflow: scroll;
}
</style>
</head>
<body ng-cloak>
<div>
<div id="my_element" style="border: 1px solid blue;">
<div id='my_sizable' ng-observe-size></div>
</div>
</div>
<script type="application/dart" src="index.dart"></script>
<script type="text/javascript" src="packages/browser/dart.js"></script>
</body>
</html>
index.dart
library angular_observe_resize.main;
import 'dart:async' as async;
import 'dart:html' as dom;
import 'package:angular/angular.dart' as ng;
import 'package:angular/application_factory.dart' as ngaf;
// see https://stackoverflow.com/questions/19329530
// and this bug https://code.google.com/p/dart/issues/detail?id=18062
// source from http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/
#ng.Decorator(selector: '[ng-observe-size]')
class NgObserveSizeDirective implements ng.AttachAware, ng.DetachAware {
dom.Element _element;
bool _hasAttacheEvent;
NgObserveSizeDirective(this._element);
void onSizeChange(dom.Event e) {
_element.parent.scrollTop = _element.scrollHeight;
}
dom.HtmlElement _triggers;
void resetTriggers() {
var expand = _triggers.children[0];
var contract = _triggers.children[_triggers.children.length - 1];
var expandChild = expand.children[0];
contract.scrollLeft = contract.scrollWidth;
contract.scrollTop = contract.scrollHeight;
expandChild.style.width = '${expand.offsetWidth + 1}px';
expandChild.style.height = '${expand.offsetHeight + 1}px';
expand.scrollLeft = expand.scrollWidth;
expand.scrollTop = expand.scrollHeight;
}
int _resizeLastWidth;
int _resizeLastHeight;
bool checkTriggers() {
return _element.offsetWidth != _resizeLastWidth ||
_element.offsetHeight != _resizeLastHeight;
}
int _resizeRaf;
void scrollListener(dom.Event e) {
resetTriggers();
if(_resizeRaf != null) {
dom.window.cancelAnimationFrame(_resizeRaf);
}
_resizeRaf = dom.window.requestAnimationFrame((num highResTime){
if(checkTriggers()) {
_resizeLastWidth = _element.offsetWidth;
_resizeLastHeight = _element.offsetHeight;
onSizeChange(e);
}
});
}
#override
void attach() {
if(_element.getComputedStyle().position == 'static') {
_element.style.position = 'relative';
}
_triggers = new dom.DivElement()
..classes.add('resize-triggers')
..append(new dom.DivElement()..classes.add('expand-trigger')..append(new dom.DivElement()))
..append(new dom.DivElement()..classes.add('contract-trigger'));
_element.append(_triggers);
new async.Future.delayed(new Duration(seconds: 1), () {
//_triggers = _element.children[_element.children.length - 1];
resetTriggers();
dom.Element.scrollEvent.forTarget(_element, useCapture: true).listen(scrollListener);
});
}
#override
void detach() {
_triggers.remove();
}
}
class MyAppModule extends ng.Module {
MyAppModule() {
type(NgObserveSizeDirective);
}
}
main() {
print('main');
ngaf.applicationFactory().addModule(new MyAppModule()).run();
new async.Timer.periodic(new Duration(seconds: 1), (t) {
var elt = (dom.querySelector('#my_sizable') as dom.HtmlElement);
elt.append(new dom.Element.html('<div>${new DateTime.now()}</div>'));
});
}
If you're using an AngularDart component you can inject the shadowdom then select an element inside it to focus on. Didnt find a way of getting the container of the shadowdom.
new Future.delayed(new Duration(milliseconds: 300), () {
var rowElement = _shadowRoot.querySelector('.step-container');
if (rowElement != null ) {
rowElement.scrollIntoView(ScrollAlignment.TOP);
}
});
ShadowDom.host might work, though its currently marked as experimental.

Dynamic Image Loading in processing

In a processing drawing loop, I have an algorithm that uses face detection to trigger a picture being taken. However so far I cannot get the image to display in my drawing loop. Does anyone know how to halt a drawing loop until an image is loaded and displayed? Here's the section of my drawing loop:
if (faces.length > 0) {
save("Source/face.jpg");
PImage img = loadImage("Source/face.jpg");
image(img,0,0);
} else {
println("not seeing anything");
}
Obviously this isn't working, how do I dynamically load and display images in processing?
I have this function in javascript
loadimage: function(image, i) {
var img = new Image();
$(img).load(function () {
$(this).hide();
$('#loader'+i).append(this);
$('#loading'+i).removeClass('image-container-loading');
$(this).fadeIn();
}).error(function () {
// notify the user that the image could not be loaded
}).attr('src',image).css('width','50px').css('height','50px').css('position','absolute');
}
Called:
self.loadimage('http://www.test.com/files/images/hi.jpg,ide);
html:
<li class='promotion'><span class='image-container' id='loader"+ide+"'>
<span class='units'></span>
<span style='border: solid 0px' class='image-container-loading' id='loading'>
</span></li>

Resources