Nice reversible cards in a IBM Verse style

In an application I am displaying objects with cards. Because the type of objects may differ in type and amount of data (text, images, tables, dates) the cards to display them differ.

Some cards have interaction (popup, dialogs, reversible) and some are just static. In this post I will discuss the reversible card type.

The reversible card has as features:

  • a front card with a folded corner, if you move over the fold an info icon appears which you can click to see the card’s back.
  • when you flip over to the back or front it is all nicely animated.
  • on the back of the card there is another icon to switch back to the card’s front.

The purpose of this reversible card is to save space in my UI, and to provide layout for secondary information, which is more important if you want to look at more detailed information.

It could also be a placeholder for data that, when placed in the front of the card, ask for too much landscape (e.g. a chart).

Things become much clearer with images so here are a few:

card-default

Image: Default presentation.

card-mouse-over-fold

Image: Expand folding (animation) when mouse-over.

card-flipped

Image: animation when flipping over a card.

card-back

Image: the back of the card.

I use the cards within a repeat control and with Bootstrap they align nicely and are responsive:

cards

I have no idea when Bootstrap 4 will be released with it’s card component but according to my experience cards are … less useful without interaction.

I made a small video to demonstrate the reversible cards feature:

If you want to implement the card yourself here is the code:

card-code

Most of the chemistry is performed with CSS so you also want that:

body{
padding:20px;
}

.flip {
-webkit-perspective: 800;
perspective: 800;
position: relative;
text-align: left;
min-height:200px;
margin-bottom:20px;
}

.flipped {
height: 100%;
background-color:#efefef;
-webkit-transform: rotateY(-180deg);
transform: rotateY(-180deg);
}

.card {
height: 100%;
-webkit-transform-style: preserve-3d;
-webkit-transition: 0.5s;
transform-style: preserve-3d;
transition: 0.5s;
}

.card .face {
-webkit-backface-visibility: hidden ;
backface-visibility: hidden ;
z-index: 2;
}

.front {
/*position: relative;*/
background-color: #FFF;

height:200px;
position: absolute;
width: 100%;
z-index: 1;
border: 1px solid #e3e3e3;
box-shadow: 5px 7px rgba(0, 0, 0, 0.15);
transition: background 0.4s ease;
}

.front-content, .back-content {
padding: 20px;
}
.front-content:before {
content:””;
width: 80px;
height: 80px;
float: right;
}
.corner-tip:before, .corner-tip:after {
background-color: #FFF;
position: absolute;
display: block;
z-index: 2;
border-top-right-radius: 60%;
width: 50%;
height: 50%;
content: “”;
}
.corner-tip:before {
right: 100%;
top: 0%;
background: -webkit-radial-gradient(-180% 200%, circle, rgba(255,255,255,0) 80%, rgba(0,0,0,.2) 100%);
}
.front:hover .corner-tip:before {
border-right: solid 1px #fff;
}
.front div.corner:hover .corner-tip:before {
border-right: solid 2px #fff;
}
.corner-tip:after {
top: 100%;
right: 0%;
background: -webkit-radial-gradient(-250% 320%, circle, rgba(255,255,255,0) 80%, rgba(0,0,0,.2) 100%);
}
.front:hover .corner-tip:after {
border-top: solid 1px #fff;
}
.front div.corner:hover .corner-tip:after {
border-top: solid 2px #fff;
}
.corner { /* edit these sizes for the default revealing corner size */
height: 20px;
width: 20px;
right: 0;
top: 0;
position: absolute;
overflow: visible;
}
.front:hover .corner { /* edit corner size (First animation, when the whole page is rollovered) */
height: 30px;
width: 30px;
}
.front div.corner:hover { /* edit corner size (Second animation, when the corner itself is rollovered) */
height: 50px;
width: 50px;
}
.corner:before {
position: absolute;
top: 0;
right: 0;
content: “”;
display: block;
width: 133%;
height: 133%;
}
.corner-contents:after {
position: absolute;
top: 0;
right: 0;
content: “”;
background: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0) 37%, #DDD 62%, rgba(230, 230, 230, 0.1) 64%, rgba(255, 255, 255, 0) 67%), -webkit-radial-gradient(-50% 150%, circle, transparent 74%, rgba(0, 0, 0, 0.2) 74%, transparent 81%);
display: block;
width: 133%;
height: 133%;
}
.corner-tip {
position: absolute;
top: 0;
right: 0;
content: “”;
background: -webkit-linear-gradient(45deg, #ddd 17%, #dfdfdf 18%, #f5f5f5 30%, #f8f8f8 34%, #eee 39%, rgba(200,200,200,0) 41%);
display: block;
width: 100%;
height: 100%;
}
.corner-button {
position: absolute;
top: 0;
right: 0;
color: #fff;
text-align: center;
padding:5px;
display: inline-block;
font-size: 1.6em;
color:black;
}
.corner-contents {
width: 125%;
position: absolute;
display: block;
overflow: hidden;
-webkit-mask: -webkit-linear-gradient(45deg, transparent 49%, #000 53%);
top: 0;
right: 0;
height: 125%;
}
._corner-contents:before {
content: “”;
position: absolute;
top: 0;
right: 0;
content: “”;
display: block;
width: 100%;
height: 100%;
background-color: #eeeef4; /* Match this background color to #fpc_effect-back */
}
.corner, .corner-contents, .corner-tip {
-webkit-transition-property: all;
-webkit-transition-duration: .3s;
-webkit-transition-timing-function: cubic-bezier(0, 0.35, .5, 1.7);
}

.back {
height:200px;
width: 100%;

-webkit-transform: rotateY(-180deg);
transform: rotateY(-180deg);
border: 1px solid #e3e3e3;
box-shadow: 5px 7px rgba(0, 0, 0, 0.15);
transition: background 0.4s ease;
}

.imgThumb{
width:66px;
height:66px;
}

.card blockquote {
border-left: none;
margin: 0;
}

.card blockquote img {
margin-bottom: 10px;
}

.card blockquote p:before {
content: “\f10d”;
font-family: ‘Fontawesome’;
float: left;
margin-right: 10px;
}

Okay, you are now all powered to impress your customers. Happy development 🙂

Responsive StandbyDialog & Cancel that operation

Introduction

Fredrik Norling has posted a new XSnippet on OpenNTF for a responsive standby  widget.  Great because in my current project a) I use Bootstrap for responsive behavior b) some operations take way more time that others.

Below is a sample how the dialog looks like:

standby_widget

When investigating the code I noticed 2 things:

  • A typo for the bootstrap model
  • The close button does not actually cancel the operation. It just closes the dialog.

Small dialog

The typo is a quickfix. Change

 '<div class="modal-dialog modal-m"><div class="modal-content">' +

into

‘<div class=”modal-dialog modal-sm”><div class=”modal-content modal-content-sm”>’ +

so you use Bootstrap’s small modal and not the default large one.

Cancel the partial refresh

For the partial refresh I found the solution in a post on Sven Hasselbach’s (holy) blog. Sven also posted the solution as an XSnippet on OpenNTF.

Scriptblock

First add a new scriptblock on the custom control that contains the Standby Dialog widget:

<xp:scriptBlock id=”scriptBlockXHRHandler”>
<xp:this.value><![CDATA[

var xhrCall = null;

dojo.addOnLoad( function(){

/*** hijack dojo’s xhrRequest ***/
dojo._xhrPost = dojo.xhrPost;
dojo._xhrGet = dojo.xhrGet;

dojo.xhrPost = function( args ){
xhrCall = dojo._xhrPost( args );
}

dojo.xhrGet = function( args ){
xhrCall = dojo._xhrGet( args );
}
});
]]>
</xp:this.value>
</xp:scriptBlock>

Then I included the call to the cancel function of the xhrCall object just before the allowSubmit function of the XSP object.

xhrCall.cancel();
XSP.allowSubmit();

Now if you click the close button in the Bootstrap modal the partial refresh is aborted.standby_widget abort

 

jQuery Mobile 1.3 Panel Widget XPages demo (for download)

The last couple of days I have been ‘playing’ with jQuery Mobile and mostly with the panel widget.

I have made some kind of starter-kit (NSF) to build a great XPages app for tablets/smartphones. I have setup a subset of custom controls which accept properties. A simple form in Notes you can use to setup navigation for header, footer and a vertical menu.

You can download the (zipped) NSF on Dropbox.

Below you can see a sample result:

panelinxpages

Please let me know if you experience any problems or if you have suggestions for improvement. Happy coding!