Skip to content

Commit

Permalink
Added support to show a loading message
Browse files Browse the repository at this point in the history
  • Loading branch information
jhdavids8 committed Nov 26, 2014
1 parent 4c2f09b commit 34cdadf
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 50 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ Please Wait

### Recommended
Wrap your current body contents in a div that his hidden until the body has the class 'pg-loaded'


About Pathgather
---------------------
Pathgather is an NYC-based startup building a platform that dramatically accelerates learning for enterprises by bringing employees, training content, and existing enterprise systems into one engaging platform.

Every Friday, we work on open-source software (our own or other projects). Want to join our always growing team? Peruse our [current opportunities](http://www.pathgather.com/jobs/) or reach out to us at <tech@pathgather.com>!
58 changes: 40 additions & 18 deletions spec/please_wait.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,54 @@ describe 'PleaseWait', ->
document.body.innerHTML = originalHTML

describe "when using the default template", ->
it "requires a logo", ->
expect(-> pleaseWait.start({logo: null, spinnerTemplate: "<div></div>"})).toThrowError("Option 'logo' is required")
describe "when setting a logo", ->
it "sets the logo", ->
pleaseWait.start({logo: "logo.png"})
addedScreen = document.body.getElementsByClassName("pg-loading-screen")[0]
logo = addedScreen.getElementsByClassName("pg-loading-logo")[0]
expect(logo.src).toContain("logo.png")

it "requires a spinner template", ->
expect(-> pleaseWait.start({logo: 'logo.png', spinnerTemplate: null})).toThrowError("Option 'spinnerTemplate' is required")
describe "when setting a spinner", ->
it "sets the spinner", ->
pleaseWait.start({spinnerTemplate: "<div>Spin!</div>"})
addedScreen = document.body.getElementsByClassName("pg-loading-screen")[0]
spinner = addedScreen.getElementsByClassName("pg-loading-spinner")[0]
expect(spinner.innerHTML).toEqual("<div>Spin!</div>")

describe "when setting a message", ->
it "sets the message", ->
pleaseWait.start({message: "Hi!"})
addedScreen = document.body.getElementsByClassName("pg-loading-screen")[0]
message = addedScreen.getElementsByClassName("pg-loading-message")[0]
expect(message.innerHTML).toContain("Hi!")

describe "when using a custom template", ->
it "adds the template to the body", ->
loadingScreen = pleaseWait.start({logo: 'logo.png', spinnerTemplate: "<div></div>"})
loadingScreen = pleaseWait.start({template: "<div>LOADING!</div>"})
addedScreen = document.body.getElementsByClassName("pg-loading-screen")[0]
expect(loadingScreen).toEqual(addedScreen)
expect(addedScreen.nodeName).toEqual("HEADER")
expect(loadingScreen.children[0].nodeName).toEqual("H1")
expect(loadingScreen.innerHTML).toEqual("<div>LOADING!</div>")

describe "when using a custom template", ->
it "does not require a logo", ->
expect(-> pleaseWait.start({logo: null, template: "<div></div>"})).not.toThrow()
describe "when the template has an img tag of class pg-loading-logo", ->
it "sets the logo", ->
pleaseWait.start({logo: "logo.png", template: "<div><img class='pg-loading-logo'></img></div>"})
addedScreen = document.body.getElementsByClassName("pg-loading-screen")[0]
logo = addedScreen.getElementsByClassName("pg-loading-logo")[0]
expect(logo.src).toContain("logo.png")

it "does not require a spinner template", ->
expect(-> pleaseWait.start({spinnerTemplate: null, template: "<div></div>"})).not.toThrow()
describe "when the template has an element of class pg-loading-spinner", ->
it "sets the spinner", ->
pleaseWait.start({spinnerTemplate: "<div>Spin!</div>", template: "<div><div class='pg-loading-spinner'></div></div>"})
addedScreen = document.body.getElementsByClassName("pg-loading-screen")[0]
spinner = addedScreen.getElementsByClassName("pg-loading-spinner")[0]
expect(spinner.innerHTML).toEqual("<div>Spin!</div>")

it "adds the template to the body", ->
loadingScreen = pleaseWait.start({logo: null, template: "<div></div>"})
addedScreen = document.body.getElementsByClassName("pg-loading-screen")[0]
expect(loadingScreen).toEqual(addedScreen)
expect(addedScreen.nodeName).toEqual("HEADER")
expect(loadingScreen.children[0].nodeName).toEqual("DIV")
describe "when the template has an element of class pg-loading-message", ->
it "sets the message", ->
pleaseWait.start({message: "Hi!", template: "<div><div class='pg-loading-message'></div></div>"})
addedScreen = document.body.getElementsByClassName("pg-loading-screen")[0]
message = addedScreen.getElementsByClassName("pg-loading-message")[0]
expect(message.innerHTML).toContain("Hi!")

describe "when specifying a background color", ->
it "sets the loading screen's background color", ->
Expand Down
70 changes: 46 additions & 24 deletions src/please-wait.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,26 @@

_pleaseWait =
defaultOptions:
backgroundColor:
required: false
logo:
required: (options = {}) -> !options.template?
spinnerTemplate:
required: (options = {}) -> !options.template?
template:
default: """
<h1 class='pg-loading-logo-header'>
<img class='pg-loading-logo'></img>
</h1>
<div class='pg-loading-spinner'>
backgroundColor: null
message: null
showEllipsis: true
logo: null
spinnerTemplate: null
template: """
<div class='pg-loading-inner'>
<div class='pg-loading-center-outer'>
<div class='pg-loading-center-middle'>
<h1 class='pg-loading-logo-header'>
<img class='pg-loading-logo'></img>
</h1>
<p class='pg-loading-message'>
</p>
<div class='pg-loading-spinner'>
</div>
</div>
</div>
"""
</div>
"""

done: ->
return unless @_loadingDiv?
Expand All @@ -61,12 +67,32 @@
@_loadingDiv.className = "pg-loading-screen"
@_loadingDiv.style.backgroundColor = @_options.backgroundColor if @_options.backgroundColor?
@_loadingDiv.innerHTML = @_options.template
unless options.template? # Initialize the default template with the logo and spinner
spinnerTemplate = null
spinner = @_loadingDiv.getElementsByClassName("pg-loading-spinner")[0]
spinner.innerHTML = @_options.spinnerTemplate
logo = @_loadingDiv.getElementsByClassName("pg-loading-logo")[0]
logo.src = @_options.logo
spinnerDiv = @_loadingDiv.getElementsByClassName("pg-loading-spinner")[0]
logo = @_loadingDiv.getElementsByClassName("pg-loading-logo")[0]
messageDiv = @_loadingDiv.getElementsByClassName("pg-loading-message")[0]

if logo?
logo.src = @_options.logo

if spinnerDiv?
if @_options.spinnerTemplate?
spinnerDiv.innerHTML = @_options.spinnerTemplate
else
spinnerDiv.style.display = 'none'

if messageDiv?
if @_options.message?
messageDiv.innerHTML = if @_options.showEllipsis
"""
#{@_options.message}
<span class='ellipsis one'>.</span>
<span class='ellipsis two'>.</span>
<span class='ellipsis three'>.</span>
"""
else
@_options.message
else
messageDiv.style.display = 'none'

document.body.appendChild(@_loadingDiv)
@_loadingDiv.className += " pg-loading"
Expand All @@ -78,11 +104,7 @@

# Set options
for k, v of defaultOptions
optionSpecified = options[k]?
if v.required?
required = if typeof v.required == "function" then v.required(options) else v.required
if required && !optionSpecified then throw new Error("Option '#{k}' is required")
newOptions[k] = if optionSpecified then options[k] else v.default
newOptions[k] = if options[k]? then options[k] else v

newOptions

Expand Down
170 changes: 162 additions & 8 deletions src/please-wait.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,41 +34,89 @@ body.pg-loaded {
}

&.pg-loading {
.pg-loading-logo-header, .pg-loading-spinner {
.pg-loading-logo-header, .pg-loading-spinner, .pg-loading-message {
opacity: 1;
}

.pg-loading-logo-header, .pg-loading-spinner {
.pg-loading-logo-header, .pg-loading-spinner, .pg-loading-message {
@include prefixed(animation, pgAnimLoading 1s cubic-bezier(0.7,0,0.3,1) both);
}

.pg-loading-message {
@include prefixed(animation-delay, 0.3s);

.ellipsis {
opacity: 0;

&.one {
@include prefixed(animation, dot-1 1.5s infinite);
}

&.two {
@include prefixed(animation, dot-2 1.5s infinite);
}

&.three {
@include prefixed(animation, dot-3 1.5s infinite);
}
}
}

.pg-loading-spinner {
@include prefixed(animation-delay, 0.3s);
}
}

.pg-loading-logo-header, .pg-loading-spinner {
.pg-loading-inner {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
position: static;
}

.pg-loading-center-outer {
width: 100%;
padding: 0;
display: table !important;
height: 100%;
position: absolute;
top: 0;
left: 0;
margin: 0;
}

.pg-loading-center-middle {
padding: 0;
vertical-align: middle;
display: table-cell !important;
margin: 0;
text-align: center;
}

.pg-loading-logo-header, .pg-loading-spinner {
width: 100%;
opacity: 0;
cursor: default;
pointer-events: none;
top: 0;
height: 100%;
}

.pg-loading-logo-header {
@include prefixed(transform, translate3d(0,25%,0));
text-align: center;

img {
display: inline-block !important;
}
}

.pg-loading-message {
margin: 90px auto 0 auto;
font-size: 22px;
font-weight: 400;
}

.pg-loading-spinner {
@include prefixed(transform, translate3d(0,55%,0));
margin: 90px auto 0 auto;
}
}

Expand Down Expand Up @@ -122,4 +170,110 @@ body.pg-loaded {
from {
opacity: 1;
}
}
}

@-webkit-keyframes dot-1 {
0% { opacity: 0; }
25% { opacity: 1; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@-moz-keyframes dot-1 {
0% { opacity: 0; }
25% { opacity: 1; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@-o-keyframes dot-1 {
0% { opacity: 0; }
25% { opacity: 1; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@-ms-keyframes dot-1 {
0% { opacity: 0; }
25% { opacity: 1; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@keyframes dot-1 {
0% { opacity: 0; }
25% { opacity: 1; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@-webkit-keyframes dot-2 {
0% { opacity: 0; }
25% { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 1; }
}

@-moz-keyframes dot-2 {
0% { opacity: 0; }
25% { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 1; }
}

@-o-keyframes dot-2 {
0% { opacity: 0; }
25% { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 1; }
}

@-ms-keyframes dot-2 {
0% { opacity: 0; }
25% { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 1; }
}

@keyframes dot-2 {
0% { opacity: 0; }
25% { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 1; }
}

@-webkit-keyframes dot-3 {
0% { opacity: 0; }
50% { opacity: 0; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@-moz-keyframes dot-3 {
0% { opacity: 0; }
50% { opacity: 0; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@-o-keyframes dot-3 {
0% { opacity: 0; }
50% { opacity: 0; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@-ms-keyframes dot-3 {
0% { opacity: 0; }
50% { opacity: 0; }
75% { opacity: 1; }
100% { opacity: 1; }
}

@keyframes dot-3 {
0% { opacity: 0; }
50% { opacity: 0; }
75% { opacity: 1; }
100% { opacity: 1; }
}

0 comments on commit 34cdadf

Please sign in to comment.