jQuery++ template
Includes the full version of jQuery++. Use it as a starting point when you want to demo something.
HTML
<script src="http://jquerypp.com/release/latest/jquerypp.js"></script>
<article>
<h1 class="post-title">Weekly Widget 1 - TreeCombo</h1>
<div class="author-time">18 January 2013 by justinbmeyer</div>
<p>I, <a href="http://twitter.com/justinbmeyer">@justinbmeyer</a>, am
going to post a weekly widget made with CanJS. I hope to continue
this for as long as I have widgets to write. If you
<strong>want to see something</strong>, please tweet it to
<a href="http://twitter.com/justinbmeyer">@canjs</a>. These posts
are going to be quick and dirty. Eventually, I will put
these up on <a href="http://canjs.us/recipes.html">CanJS’s recipe page</a> with
a full description.
</p>
<p>I’m starting with the <code>TreeCombo</code> below:</p>
<iframe style="width: 100%; height: 300px" src="http://jsfiddle.net/sTLhX/35/embedded/result,html,js"
allowfullscreen="allowfullscreen" frameborder="0">JSFiddle</iframe>
<h2 id="what-it-does">What it does</h2>
<p>The tree combo allows you to select items within and
navigate through a hierarchial collection
of data. Click “→” to see child items. Click the
breadcrumb navigation at the top to return to parent items.</p>
<p>It also displays a list of the items the user has selected under
“You’ve selected:”.</p>
</article>
<article>
<h1 class="post-title">Weekly Widget 2 - 2-Way Mustache Helpers
</h1>
<div class="author-time">27 January 2013 by justinbmeyer</div>
<p>This article shows how to make 2-way binding mustache helpers
and use them in a basic form.</p>
<p>By default, CanJS supports 1-way binding templates.
1-way binding means that if data changes,
the template is automatically updated. For example,
if <code>attendee.name</code> changes, the following input’s value is updated:
</p>
<pre><code class="xml"><span class="tag"><<span...
CSS
* {
font: 13px/16px "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
color: #333;
}
h1, h2, h3, b, strong { font-weight: bold; color: #000;}
h1 { font-size: 18px; margin-bottom:5px; }
p {margin: 5px 0; }
article {
margin: 10px;
padding-bottom: 10px;
border-bottom: solid 1px #eee;
}
.author-time { color: #999; font-size: 11px; }
.more, .less {
color: #fff;
text-decoration: none;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: #49afcd;
border-color: #2f96b4 #2f96b4 #1f6377;
padding: 0 3px 2px;
height: 11px;
line-height: 11px;
display: inline-block;
}
.less {
padding: 0 4px 2px;
background-color: #206478;
}
JavaScript
(function(){
/**
* $('.body').more({
* moreHTML: "<a href='javascript://' class='more'>...</a>",
* moreWidth: 50,
* lessHTML: " <a href='javascript://' class='less'>less</a>",
* lines: 2
* })
*/
$.fn.more = function(options){
// setup defaults
options = $.extend({
lessHTML: " <a href='javascript://' class='less'>-</a>",
moreHTML: " <a href='javascript://' class='more'>+</a>",
moreWidth: 50,
lines: 2
},options||{});
this.each(function(el){
var $el = $(this);
// save current HTML for later
$el.data('originalHTML', $el.html())
// the active range we will be moving around
var range = $el.range(),
// the end of the body's text for comparison
end = range.clone().collapse(false).start("-1"),
// the start of the body's text for comparison
start = nextChar(range.collapse().end("+1"),end).clone(),
// the current line's first character's coordinates
prevRect = start.rect(),
// how many lines we've come across
lines = 0;
// go until we reach the end of the body
while(range.compare("START_TO_START",end) != 0){
range.end("+1").start("+1");
var rect = range.rect();
// if the charcter is on a new line
if( rect && (rect.top -prevRect.top > 4) ) {
lines++;
// quit on second line
if(lines == options.lines){
break;
}
prevStart = range.clone()
prevRect = rect;
}
}
if(lines === options.lines){
// backup to previous line
range.end('-1').start('-1');
}
// get the last visible text element
prevChar(range, start)
var movedLeft = false,
offset = $el.offset(),
width = $el.width();
// keep moving back until there is room for more
while(range.compare("START_TO_START",start) != -1 ){
if( range.rect(true).left <= (offset.left+width-options.moreWidth) ) {
break;
}
movedLeft =...