Onion skinning is a technique described at ploughdeep.com. When I first saw this, I thought it was an awesome solution to building flexible custom borders around boxes on my websites. Unfortunately it increases the complexity of your html and css to unmaintainable levels. I used the technique a few times but left it by the wayside due to the complexity it added.
Recently we had to implement custom boxes with shadows that I knew that onion skinning would be a perfect fit because we needed them to be of variable size. I knew that onion skinning would be the simpliest solution, however even the simpliest solution was still to complex. I did a quick google search for "javascript onion skin" and came accross an article on Ajaxian that did almost what I needed.
Even though the ajaxian code had enough code for me to adapt for my needs, I wanted a more generic library that could be customized for most onion skinning cases. Enter skins.js.
This library provides a few prebuilt skinners that will provide enough functionality that you'll ever need
The Skin class is the most basic class that all skins are based on. In order to use it you do the following
<style type="text/css">
.skin {
display: inline-table;
/* \*/display:block;/**/
}
.skin-2 {
background:url(css/shadow.gif) right bottom no-repeat;
}
.skin-1 {
background:url(css/corner_bl.gif) left bottom no-repeat;
}
.skin-0 {
padding:0 16px 16px 0;
background:url(css/corner_tr.gif) right top no-repeat;
}
#dropshadow_example {
display:block;
border:1px solid #ccc;
border-color:#efefef #ccc #ccc #efefef;
}
</style>
<img id="dropshadow_example" src="css/zomgcute.jpg" />
<script type="text/javascript">
new Skin(3, 'skin').render($("dropshadow_example"));
</script>
This will emulate the code that is given on the ajaxian site. You'll notice that with skins.js, the internal skin starts with 0 and goes on from there.
What the skinner will generate is the following
<div class="skin-2 skin">
<div class="skin-1 skin">
<div class="skin-0 skin">
<img id="dropshadow_example" src="css/zomgcute.jpg" />
</div>
</div>
</div>
Graphics courtesy of sportmonger.com
Although there are three total classes other than the basic Skin class, we'll start with the BordercornerSkin, which is a combination of all three classes, BorderSkin, CornerSkin, and CompositeSkin. Refer to test.html and the skins-1.5.0.js for further examples of these individual classes. We'll keep things basic to get you started.
<style type="text/css">
.skin {
display: inline-table;
/* \*/display:block;/**/
}
.bordercorner-example-border-top {
background-image:url(css/border-top.gif);
}
.bordercorner-example-border-right {
background-image:url(css/border-right.gif);
}
.bordercorner-example-border-bottom {
background-image:url(css/border-bottom.gif);
}
.bordercorner-example-border-left {
float: left;
background-image:url(css/border-left.gif);
}
.bordercorner-example-corner-top-left {
background-image:url(css/corner-tl.gif);
padding: 16px;
}
.bordercorner-example-corner-top-right {
background-image:url(css/corner-tr.gif);
}
.bordercorner-example-corner-bottom-right {
background-image:url(css/corner-br.gif);
}
.bordercorner-example-corner-bottom-left {
background-image:url(css/corner-bl.gif);
}
#dropshadow_example {
display:block;
border:1px solid #ccc;
border-color:#efefef #ccc #ccc #efefef;
}
</style>
<img id="bordercorner-example" src="css/zomgcute.jpg" />
<script type="text/javascript">
new BorderCornerSkin('bordercorner-example', 'bordercorner-example').render($('bordercorner-example'));
</script>
When using the BorderCornerSkin, it creates eight classes: four for the borders and four for the corners
The BorderCornerSkin takes two arguments for creating the class itself, the first argument is the class prefix used for four border classes
new BorderCornerSkin('bordercorner-example',
'bordercorner-example');
The second argument is the class prefix used for the four corner classes
new BorderCornerSkin('bordercorner-example',
'bordercorner-example');
The four border classes are as follows: [prefix]-border-top, [prefix]-border-right, [prefix]-border-bottom, and [prefix]-border-left.
.bordercorner-example-border-top {
background-image:url(css/border-top.gif);
}
.bordercorner-example-border-right {
background-image:url(css/border-right.gif);
}
.bordercorner-example-border-bottom {
background-image:url(css/border-bottom.gif);
}
.bordercorner-example-border-left {
float: left;
background-image:url(css/border-left.gif);
}
The four corner classes are as follows: [prefix]-border-top-left, [prefix]-border-top-right, [prefix]-border-bottom-right, and [prefix]-border-bottom-left.
.bordercorner-example-corner-top-left {
background-image:url(css/corner-tl.gif);
padding: 16px;
}
.bordercorner-example-corner-top-right {
background-image:url(css/corner-tr.gif);
}
.bordercorner-example-corner-bottom-right {
background-image:url(css/corner-br.gif);
}
.bordercorner-example-corner-bottom-left {
background-image:url(css/corner-bl.gif);
}
Normally, if you were doing this manually, you would have to set the background position and the background repeat for each of these eight classes. Since the BorderCornerSkin class knows where these eight classes are supposed to be positioned, you don't have to worry about these css properties.
Justin Palmer made a wonderful library called event:Selectors that allows you to assign javascript functions to elements based on css rules.
<div class="blue-background">I'm so blue...</div>
<script type="text/javascript">
var selectors = {
'.blue-background' : function(element) {
Element.setStyle(element, { backgroundColor : '#0000ff' });
}
}
EventSelectors.start(selectors);
</script>
Now, this is horrible example of the event selectors library because we can do the same thing with a simple css rule, but you get the idea.
<img class="dropshadow" src="css/zomgcute.jpg" />
<div style="clear: both;"></div>
<img class="dropshadow" src="css/zomgcute.jpg" />
<div style="clear: both;"></div>
<img class="dropshadow" src="css/zomgcute.jpg" />
<div style="clear: both;"></div>
<script type="text/javascript">
var selectors = {
'.dropshadow' : function(element) {
new BorderCornerSkin('bordercorner-example', 'bordercorner-example').render(element);
}
}
EventSelectors.start(selectors);
</script>