Added initial implementation of error messages

Cleans up error reporting when an ajax call fails, and thus
the #page-content div can't be filled. This is accomplished by using
a #status which has a p.message element that can be populated for text
displaying status messages. By adding either .error or .success
to #status causes it to be highlighted as either a error or success message
respectively.

When its the first load of the page, and #page-content hasn't yet been
populated with content, an error message is shown in the #page-content
div.

Removed the /posts/ and /tags/ fallbacks in the generated
manifest.appcache because even when online, ajax calls for invalid URLs
under those paths return the respective fallback page instead of an
error message, and populate the #page-content div with the fallback. So
from this point forward the fact that the website is offline will be
handled from JavaScript.

When a page is not accessible in the application cache and the user is
offline, an error message is displayed using the mechanism mentioned
above.

Signed-off-by: Collin J. Doering <collin.doering@rekahsoft.ca>
This commit is contained in:
Collin J. Doering 2015-01-06 04:08:40 -05:00
parent f0a702f5d4
commit 5bbacb1725
9 changed files with 343 additions and 45 deletions

View File

@ -0,0 +1,278 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="170.41849"
height="149.08997"
id="svg2"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="error-loading.svg"
inkscape:export-filename="/home/collin/.code/my-projects/www/blog-rekahsoft-ca/images/error-loading.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<linearGradient
id="linearGradient5353">
<stop
style="stop-color:#fcd4d4;stop-opacity:1;"
offset="0"
id="stop5355" />
<stop
style="stop-color:#fcd4d4;stop-opacity:0;"
offset="1"
id="stop5357" />
</linearGradient>
<linearGradient
id="linearGradient5333">
<stop
id="stop5343"
offset="0"
style="stop-color:#fc9f9f;stop-opacity:0.54117647;" />
<stop
id="stop5341"
offset="1"
style="stop-color:#fd6a6a;stop-opacity:0.69411765;" />
</linearGradient>
<linearGradient
id="linearGradient5257">
<stop
id="stop5271"
offset="0"
style="stop-color:#ff2b00;stop-opacity:0.08730159;" />
<stop
style="stop-color:#ff2b00;stop-opacity:0.42352941;"
offset="0.5"
id="stop5275" />
<stop
style="stop-color:#ff2b00;stop-opacity:0.8888889;"
offset="1"
id="stop5273" />
</linearGradient>
<linearGradient
id="linearGradient5251"
osb:paint="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop5253" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="14.62377 : 358.12118 : 1"
inkscape:vp_y="817.72657 : 575.60686 : 0"
inkscape:vp_z="442.92966 : -250.34465 : 1"
inkscape:persp3d-origin="85.352622 : -47.069556 : 1"
id="perspective3761" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5257-5"
id="radialGradient5267-2"
cx="113.57143"
cy="618.07648"
fx="113.57143"
fy="618.07648"
r="87.14286"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient5257-5">
<stop
id="stop5271-1"
offset="0"
style="stop-color:#ff2b00;stop-opacity:0.08730159;" />
<stop
style="stop-color:#ff2b00;stop-opacity:0.42352941;"
offset="0.5"
id="stop5275-8" />
<stop
style="stop-color:#ff2b00;stop-opacity:0.8888889;"
offset="1"
id="stop5273-8" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5277-1"
id="radialGradient5283-1"
cx="113.57143"
cy="618.07648"
fx="113.57143"
fy="618.07648"
r="87.64286"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient5277-1">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop5279-5" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop5281-9" />
</linearGradient>
<radialGradient
r="87.14286"
fy="618.07648"
fx="113.57143"
cy="618.07648"
cx="113.57143"
gradientUnits="userSpaceOnUse"
id="radialGradient5401"
xlink:href="#linearGradient5257-5"
inkscape:collect="always" />
<radialGradient
r="87.64286"
fy="618.07648"
fx="113.57143"
cy="618.07648"
cx="113.57143"
gradientUnits="userSpaceOnUse"
id="radialGradient5403"
xlink:href="#linearGradient5277-1"
inkscape:collect="always" />
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
id="filter3787-2-9">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.4169922"
id="feGaussianBlur3789-7-9" />
</filter>
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
id="filter3787">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.4169922"
id="feGaussianBlur3789" />
</filter>
<filter
inkscape:collect="always"
id="filter3922"
x="-0.10782261"
width="1.2156452"
y="-0.02160711"
height="1.0432142">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.67423386"
id="feGaussianBlur3924" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="161.21708"
inkscape:cy="-84.257025"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1600"
inkscape:window-height="884"
inkscape:window-x="1920"
inkscape:window-y="16"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-74.356556,-330.19148)"
style="opacity:0.45">
<path
sodipodi:type="star"
style="fill:#ff0d2d;fill-opacity:0.89878539999999985;fill-rule:nonzero;stroke:#ffffff;stroke-width:25;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3787)"
id="path2985"
sodipodi:sides="3"
sodipodi:cx="154.28571"
sodipodi:cy="249.50504"
sodipodi:r1="299.12799"
sodipodi:r2="149.564"
sodipodi:arg1="0.52359878"
sodipodi:arg2="1.5707963"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 413.33814,399.06903 -518.10487,0 259.05244,-448.691985 z"
transform="matrix(0.3072269,0,0,0.3072269,112.16645,351.05621)"
inkscape:transform-center-y="-22.97504"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:0.93117411999999999;fill-rule:nonzero;stroke:#ffffff;stroke-width:13.22081279999999914;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3787-2-9)"
id="path2985-0"
sodipodi:sides="3"
sodipodi:cx="154.28571"
sodipodi:cy="249.50504"
sodipodi:r1="299.12799"
sodipodi:r2="149.564"
sodipodi:arg1="0.52359878"
sodipodi:arg2="1.5707963"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 413.33814,399.06903 -518.10487,0 259.05244,-448.691985 z"
transform="matrix(0.23030533,0,0,0.23030533,124.03435,369.97686)"
inkscape:transform-center-y="-17.222694" />
<text
xml:space="preserve"
style="font-size:116.73020935000002396px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:#000000;font-family:FreeMono;-inkscape-font-specification:FreeMono;stroke-opacity:1;filter:url(#filter3922)"
x="123.86201"
y="452.85916"
id="text3799"
sodipodi:linespacing="125%"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><tspan
sodipodi:role="line"
id="tspan3801"
x="123.86201"
y="452.85916">!</tspan></text>
<text
xml:space="preserve"
style="font-size:116.73020935000000975px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;opacity:0.75000000000000000;fill:#ffffff;fill-opacity:1;stroke:none;font-family:FreeMono;-inkscape-font-specification:FreeMono"
x="112.19463"
y="588.04706"
id="text3799-3"
sodipodi:linespacing="125%"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><tspan
sodipodi:role="line"
id="tspan3801-9"
x="112.19463"
y="588.04706">!</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
images/error-loading.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -43,6 +43,10 @@
//$('.navbar-collapse').collapse('hide');
});
$('#status a.close-button').click(function () {
$(this).parent().slideUp();
});
// Callback for when the inital page has completely loaded (including images, etc..)
$(window).load(function () {
$.address.change(function(event) {
@ -120,8 +124,14 @@
type: 'GET',
dataType: 'html',
beforeSend: function (xhr, settings) {
// Remove loading error from page-content and any status message errors
$('#page-content').removeClass('loading-error');
$('#status').slideUp('normal', function () {
$('#status').removeClass('error').removeClass('success');
});
// Add .loading to #page-content and #nav to facilitate a loading animation
$('#page-content, #nav').removeClass('loading-done').removeClass('loading-error').addClass('loading');
$('#page-content, #nav').removeClass('loading-done').addClass('loading');
console.log('beforeSend a.menuitem');
},
@ -153,12 +163,18 @@
}, 250);
},
error: function (xhr, status) {
/* Remove .loading then add .loading-error to #page-content and #nav to
* stop the loading animation and facilitate a loading error animation
/* Remove .loading from #page-content and #nav to stop the loading
* animation. Then add .loading-error to #page-content if its the sites
* first load (#page-content has class .init). Finally, display an error
* message in #status.
*/
$('#page-content, #nav').removeClass('loading').addClass('loading-error');
console.log('error retrieving page "' + page_href +'": ' + status);
$('#page-content, #nav').removeClass('loading');
if ($('#page-content.init')[0]) {
$('#page-content').addClass('loading-error').html('<p class="container border-box">Error initially loading blog.rekahsoft.ca. Check the url! Given "' + page_href + '"</p>');
} else {
$('#status > p.message').text('Error retrieving page "' + page_href +'": ' + status);
$('#status').addClass('error').slideDown();
}
}
});
}

View File

@ -1,7 +0,0 @@
!!! 5
%html
%body
.container
.border-box
%h1 You are currently offline and this post is unaccesable

View File

@ -45,9 +45,6 @@
#nav.loading
@include animation-play-state(running)
#nav.loading-error
// do something
#nav-menu
text-align: center
margin-bottom: 0
@ -99,3 +96,31 @@
@include transform(scale(1.1))
a.rss-icon:active
@include transform(scale(0.9))
#status
display: none
border: 1px solid
border-top: none
border-bottom-right-radius: 5px
border-bottom-left-radius: 5px
background-color: rgb(146, 208, 240)
box-shadow: 2px 5px 5px 2px #888888
padding: 8px
margin-bottom: 1.25em
p.message
display: inline-block
text-align: center
margin-bottom: 0
a.close-button
display: inline-block
position: absolute
right: 10px
height: 25px
#status.error
background-color: #FD6F6F
#status.success
background-color: rgb(136, 211, 136)

View File

@ -92,18 +92,17 @@ sub
@include transition(opacity 1s ease-in 0.5s)
opacity: 1
// TODO: this needs work
#page-content.loading-error
//background: url('/images/error-loading.png') no-repeat 50%
//height: 200px
#page-content.loading-error p
background: #fd6f6f url('/images/error-loading.png') no-repeat 50%
height: 200px
font-weight: bold
line-height: 200px
text-align: center
#page-content.init.loading
background: url('/images/init-loading.gif') no-repeat 50%
height: 125px
#page-content.init.loading-error
// do something
#footer-left
padding-left: 1em

View File

@ -138,29 +138,20 @@ main = do
let randomNum = random stdGen :: (Int, StdGen)
randomStr = show . abs . fst $ randomNum
manifestStart = [ "CACHE MANIFEST"
, "# " ++ randomStr
, "" ]
, "# " ++ randomStr ]
manifestCacheSingles = [ "/index.html"
, "/default.css" ]
paginatedPostsCache = take 2 $ map (\(n,_) -> "/pages/blog" ++ (show n) ++ ".html") $ toList $ paginateMap paginatedPosts
tagsCache = concatMap (\(t,ids) -> take 2 $ ["/tags/" ++ t ++ show n ++ ".html" | n <- [1..length $ paginateEvery numPaginatePages ids]]) $ tagsMap tags
manifestCacheFromIds = filter (not . null) $ fmap (maybe "" ("/"++)) manifestCacheRoutesMaybe
manifestCache = manifestCacheFromIds ++ tagsCache ++ paginatedPostsCache
manifestFallback = [""
, "FALLBACK:"
, "/posts/ /post-offline.html"
, "/tags/ /tags-offline.html"
, "" ]
manifestNetwork = [ "NETWORK:"
, "*"
, "http://*"
, "https://*"
, "" ]
makeItem . unlines $ manifestStart ++ manifestCacheSingles ++ manifestCache ++ manifestFallback ++ manifestNetwork
match "*-offline.haml" $ do
route $ setExtension "html"
compile $ getResourceBody >>= withItemBody (unixFilter "haml" [])
, "https://*" ]
makeItem . unlines $ manifestStart ++ [""] ++
manifestCacheSingles ++ manifestCache ++ [""] ++
manifestNetwork ++ [""]
match "css/**" $ do
route idRoute

View File

@ -1,7 +0,0 @@
!!! 5
%html
%body
.container
.border-box
%h1 You are currently offline and this tag page is unaccesable

View File

@ -4,7 +4,6 @@
/[if IE 8] <html class="ie ie8" lang="en">
<!-- [if (gte IE 9)|!(IE)]><!-->
%html.en(manifest='manifest.appcache')
// Work in progress on application cache;
%head
/ Basic Page Needs
%meta(charset="utf-8")
@ -39,6 +38,10 @@
$partial("templates/partials/logo-banner.haml")$
$partial("templates/partials/nav.haml")$
#status.container
%p.message
%a.close-button Close
#page-content.init.loading
%noscript
#noscript-alert.container