Skip to content
Browse files

removing dist dirs

  • Loading branch information...
1 parent 16cc536 commit 668d8d2d7e1293a07b91c0ba6726d58618b32532 @joestelmach joestelmach committed Mar 25, 2012
Showing with 3 additions and 3,037 deletions.
  1. +1 −1 .gitignore
  2. +2 −0 Rakefile
  3. +0 −640 dist/backbone-ui.css
  4. +0 −2,396 dist/backbone-ui.js
View
2 .gitignore
@@ -1,4 +1,4 @@
dev
dist/*
-doc/dist
+doc/dist/*
*.DS_Store
View
2 Rakefile
@@ -8,6 +8,7 @@ task :build => [:doc] do
puts 'generating distribution'
`rm -rf dist/*`
+ `mkdir -p dist`
css_source_files = Dir.entries("./src/css").find_all do |source_file|
source_file.match /\.css$/
@@ -50,6 +51,7 @@ desc "generate the documentation in doc/dist"
task :doc do
puts 'generating documentation'
`rm -rf doc/dist/*`
+ `mkdir -p doc/dist`
def build_script_tags(dirs)
dirs.map do |dir|
View
640 dist/backbone-ui.css
@@ -1,640 +0,0 @@
-a.button {
- position:relative;
- height:28px;
- text-decoration:underline;
- font-size:14px;
- font-family:Helvetica;
- color:#333;
-
- /* inline-block with IE7 hack */
- display: inline-block;
- zoom: 1;
- *display: inline;
- vertical-align:top;
-}
-
-.button.has_border {
- border:1px solid #666;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -o-user-select: none;
- user-select: none;
- background-color:#eee;
- text-decoration:none;
-}
-
-.button.has_glyph {
- padding-left:30px;
-}
-
-.button.has_glyph_right {
- padding-right:30px;
-}
-
-.button .label {
- line-height:28px;
- padding:0;
-}
-
-.button.has_border .label {
- padding:0 5px;
-}
-
-.button.disabled {
- color:#aaa;
-}
-
-.button.has_border.disabled {
- border-color:#999;
-}
-
-.button.disabled .glyph {
- filter:alpha(opacity=50);
- opacity:0.5;
-}
-
-.button.has_border:hover {
- background-color:#ddd;
- border-color:#222;
-}
-
-.button.has_border.disabled:hover {
- background-color:#fff;
- border-color:#999;
- cursor:default;
-}
-
-.button.has_border.active {
- background-color:#ccc;
-}
-
-.button input[type=submit] {
- border:1px solid transparent;
- background-color:transparent;
- position:absolute;
- top:-5px;
- right:-5px;
- bottom:-5px;
- left:-5px;
- cursor:pointer;
-}
-.calendar {
- user-select: none;
- -webkit-user-select: none;
- text-transform:capitalize;
-}
-
-.calendar table {
- border-collapse:collapse;
- border:1px solid #444;
-}
-
-.calendar thead {
- border-bottom:1px solid #444;
- line-height:33px;
- background-color:#eaeaea;
-}
-
-.calendar .go_forward,
-.calendar .title {
- border-left:1px solid #444;
-}
-
-.calendar a {
- display:block;
- text-decoration:none;
- color:#222;
-}
-
-.calendar td,
-.calendar th {
- text-align:center;
- padding:0;
- margin:0;
- font-size:14px;
-}
-
-.calendar .row.days td {
- line-height:33px;
- border-right:1px solid #444;
- background-color:#eaeaea;
-}
-
-.calendar .cell {
- border:1px solid #444;
- background-color:#fff;
-}
-
-.calendar .cell.inactive {
- background-color:#eaeaea;
- color:#999;
-}
-
-.calendar .cell.today {
- font-weight:bold;
-}
-
-.calendar .cell a,
-.calendar .cell .day {
- width:33px;
- line-height:33px;
-}
-
-.calendar .cell a:hover,
-.calendar .cell a:active {
- background-color:#e9d4c7;
-}
-
-.calendar .cell.selected a,
-.calendar .cell.selected a:hover {
- background-color:#ae5317;
- color:#fff;
-}
-
-.checkbox {
- text-decoration:none;
- height:30px;
- white-space:nowrap;
-}
-
-.checkbox:hover {
- cursor:pointer;
-}
-
-.checkbox .checkmark {
- position:relative;
- width:20px;
- height:20px;
- margin-top:5px;
- text-align:center;
- border:1px solid #666;
- -moz-border-radius: 6px;
- -webkit-border-radius: 6px;
- border-radius: 6px;
- color:#222;
- font-size:18px;
- background-color:#fff;
-}
-
-.checkbox:hover .checkmark {
- background-color:#eee;
- border-color:#222;
-}
-
-.checkbox .checkmark_fill {
- height:14px;
- width:14px;
- line-height:16px;
- position:absolute;
- background-color:#222;
- top:3px;
- left:3px;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
-}
-
-.checkbox .label {
- line-height:32px;
- padding:0 0 0 10px;
- text-decoration:none;
- color:#222;
- overflow:hidden;
-}
-
-.checkbox,
-.checkbox .checkmark,
-.checkbox .label {
- /* inline-block with IE7 hack */
- display: inline-block;
- zoom: 1;
- *display: inline;
- vertical-align:top;
-}
-.date_picker .text_field {
- width:100px;
-}
-
-.date_picker_calendar {
- position:absolute;
- z-index:1000;
-}
-.glyph {
- position:absolute;
- top:3px;
- left:3px;
- line-height:24px;
- text-align:center;
- color:#666;
- font-style:normal;
- font-size:11px;
-}
-
-.glyph.right {
- left:auto;
- right:3px;
-}
-
-.list ul {
- list-style-type:none;
- margin:0;
- padding:0;
-}
-.menu {
- max-height:150px;
- margin-right:3px;
- position:relative;
-}
-
-.menu ul {
- padding:5px;
-}
-
-.menu .menu_scroller {
- border:1px solid #666;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- background-color:#fff;
- -moz-box-shadow: 2px 2px 2px #666;
- -webkit-box-shadow: 2px 2px 2px #666;
- box-shadow: 2px 2px 2px #666;
-}
-
-.menu .menu_scroller .content {
- margin:0;
- max-height:150px;
-}
-
-.menu .menu_scroller.disabled .content {
- margin-right:0;
-}
-
-.menu li {
- position:relative;
- font-size:14px;
- white-space:nowrap;
- margin:2px 0;
-}
-
-.menu li a {
- text-decoration:none;
- line-height:28px;
- color:#222;
- padding:0 5px;
- display:block;
- position:relative;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
-}
-
-.menu li a:hover span,
-.menu li a:link span,
-.menu li a:active span,
-.menu li a:visited span{
- text-decoration:none;
- color:#222;
-}
-
-.menu li a:hover,
-.menu li a.selected {
- background-color:#e9d4c7;
- text-decoration:none;
-}
-
-.menu li a.has_glyph {
- padding-left:24px;
-}
-
-.menu li .glyph.right {
- top:4px;
- right:4px;
-}
-.pulldown {
- position:relative;
- height:30px;
- /* inline-block with IE7 hack */
- display: inline-block;
- zoom: 1;
- *display: inline;
-}
-
-.pulldown.placeholder {
- font-style:italic;
-}
-
-.pulldown .button:link,
-.pulldown .button:active,
-.pulldown .button:hover,
-.pulldown .button:visited {
- color:#333;
- text-decoration:none;
-}
-
-
-.radio_group .choice:hover {
- cursor:pointer;
-}
-
-.radio_group .mark {
- margin:0 5px 0 0;
- width:20px;
- height:20px;
- line-height:17px;
- border:1px solid #666;
- -moz-border-radius: 11px;
- -webkit-border-radius: 11px;
- border-radius: 11px;
- color:#222;
- font-family:Verdana;
- text-align:center;
- font-size:16px;
-}
-.radio_group .choice:hover .mark {
- background-color:#eee;
- border-color:#222;
-}
-
-.radio_group ul {
- margin:0;
- padding:0;
-}
-
-.radio_group li {
- margin-left:10px;
-}
-
-.radio_group li a {
- display:block;
- text-decoration:none;
-}
-
-.radio_group .label {
- line-height:22px;
- color:#222;
-}
-
-.radio_group .mark,
-.radio_group li,
-.radio_group .label {
- /* inline-block with IE7 hack */
- display: inline-block;
- zoom: 1;
- *display: inline;
- vertical-align:top;
-}
-
-.scroller {
- position:relative;
- outline: none;
-}
-
-.scroller .content_wrapper{
- padding-right:13px;
-}
-
-.scroller.disabled .content_wrapper{
- padding-right:0;
-}
-
-.scroller .content {
- overflow:hidden;
- margin-right:9px;
-}
-
-.scroller.disabled .content {
- margin-right:5px;
-}
-
-.scroller .tray {
- position:absolute;
- right:3px;
- top:3px;
- bottom:3px;
- width:10px;
- background-color:#eee;
- border-radius: 8px;
- -webkit-border-radius: 8px;
- -moz-border-radius: 8px;
-}
-
-.scroller.disabled .tray {
- visibility:hidden;
-}
-
-.scroller .knob {
- position:absolute;
- right:1px;
- width:8px;
- cursor:move;
-}
-
-.scroller .knob_top {
- position:absolute;
- right:0;
- left:0;
- height:11px;
- background-color:#555;
- border-top-left-radius: 8px;
- -webkit-border-top-left-radius: 8px;
- -moz-border-radius-topleft: 8px;
- border-top-right-radius: 8px;
- -webkit-border-top-right-radius: 8px;
- -moz-border-radius-topright: 8px;
-}
-
-.knob_middle {
- position:absolute;
- right:0;
- left:0;
- top:10px;
- bottom:10px;
- background-color:#555;
-}
-
-.knob_bottom {
- position:absolute;
- right:0;
- left:0;
- bottom:0px;
- height:10px;
- background-color:#555;
- border-bottom-left-radius: 8px;
- -webkit-border-bottom-left-radius: 8px;
- -moz-border-radius-bottomleft: 8px;
- border-bottom-right-radius: 8px;
- -webkit-border-bottom-right-radius: 8px;
- -moz-border-radius-bottomright: 8px;
-}
-.tab_set .tab_bar {
- height:29px;
- padding-left:20px;
-}
-
-.tab_set .tab {
- text-decoration:none;
- color:#222;
- border:1px solid #222;
- padding:0 10px;
- margin:0 5px 0 0;
- height:28px;
- line-height:30px;
- border-top-left-radius: 4px;
- -webkit-border-top-left-radius: 4px;
- -moz-border-radius-topleft: 4px;
- border-top-right-radius: 4px;
- -webkit-border-top-right-radius: 4px;
- -moz-border-radius-topright: 4px;
- /* inline-block with IE7 hack */
- display: inline-block;
- zoom: 1;
- *display: inline;
- vertical-align:top;
-}
-
-.tab_set .tab.selected,
-.tab_set .tab.selected:hover {
- background-color:#ddd;
-}
-
-.tab_set .tab:hover {
- background-color:#eee;
-}
-
-.tab_set .content_container {
- border:1px solid #666;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- padding:10px;
-}
-.table_view table.heading {
- border-width:1px;
- border-style:solid;
- border-color:#222;
-}
-
-.table_view table {
- text-align:left;
- width:100%;
- border-collapse:collapse;
-}
-
-.table_view table th {
- padding:0;
- margin:0;
- background-color:#eee;
-}
-
-.table_view th.first {
- padding-left:5px;
- border-left:none;
-}
-
-.table_view th.last {
- padding-right:5px;
-}
-
-.table_view .content{
- background-color:#fff;
- border-width:0 1px 1px 1px;
- border-color:#222;
- border-style:solid;
- padding:5px;
-}
-
-.table_view .wrapper {
- border:none;
- padding:5px;
-}
-
-.table_view tr.first .wrapper {
-}
-
-.table_view .content td {
- white-space:nowrap;
- overflow:hidden;
-}
-
-.table_view.clickable .content tr:hover .wrapper {
- background-color:#ddd;
- cursor:pointer;
-}
-
-.text_area {
- position:relative;
- border:1px solid #666;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- background-color:#fff;
- /* inline-block with IE7 hack */
- display: inline-block;
- zoom: 1;
- *display: inline;
- vertical-align:top;
-}
-
-.text_area.disabled {
- filter:alpha(opacity=60);
- opacity:0.6;
-}
-
-.text_area textarea {
- border:none;
- outline:none;
- margin:5px 4px 4px 4px;
- font-size:14px;
- background-color:#fff;
-}
-.text_field {
- position:relative;
- border:1px solid #666;
- width:200px;
- height:28px;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- background-color:#fff;
- /* inline-block with IE7 hack */
- display: inline-block;
- zoom: 1;
- *display: inline;
- vertical-align:top;
-}
-
-.text_field.disabled {
- filter:alpha(opacity=60);
- opacity:0.6;
-}
-
-.text_field .input_wrapper {
- position:absolute;
- left:5px;
- right:5px;
- top:3px;
-}
-
-.text_field input {
- width:100%;
- border:none;
- outline:none;
- font-size:14px;
-}
-.time_picker .text_field {
- width:80px;
-}
-
-.time_picker .menu li {
- background-color:#fff;
-}
-
-.menu {
- z-index:1000;
-}
-
View
2,396 dist/backbone-ui.js
@@ -1,2396 +0,0 @@
-(function(context) {
- // ensure backbone and jquery are available
- if(typeof Backbone === 'undefined') alert('backbone environment not loaded') ;
- if(typeof $ === 'undefined') alert('jquery environment not loaded');
-
- // define our Backbone.UI namespace
- Backbone.UI = Backbone.UI || {
- KEYS : {
- KEY_BACKSPACE: 8,
- KEY_TAB: 9,
- KEY_RETURN: 13,
- KEY_ESC: 27,
- KEY_LEFT: 37,
- KEY_UP: 38,
- KEY_RIGHT: 39,
- KEY_DOWN: 40,
- KEY_DELETE: 46,
- KEY_HOME: 36,
- KEY_END: 35,
- KEY_PAGEUP: 33,
- KEY_PAGEDOWN: 34,
- KEY_INSERT: 45
- },
-
- IMAGE_DIR_PATH : '/images',
-
- setSkin : function(skin) {
- if(!!Backbone.UI.currentSkin) {
- $(document.body).removeClass('skin_' + Backbone.UI.currentSkin);
- }
- $(document.body).addClass('skin_' + skin);
- Backbone.UI.currentSkin = skin;
- },
-
- noop : function(){}
- };
-
- _(Backbone.View.prototype).extend({
- // resolves the appropriate content from the given choices
- resolveContent : function(model, content) {
- model = model || this.model;
- content = content || this.options.content;
- var hasModelProperty = _(content).exists() && _(model).exists();
- return _(content).isFunction() ? content(model) :
- hasModelProperty && _(model[content]).isFunction() ? model[content]() :
- hasModelProperty ? _(model).resolveProperty(content) : content;
- },
-
- mixin : function(objects) {
- var options = _(this.options).clone();
-
- _(objects).each(function(object) {
- $.extend(true, this, object);
- }, this);
-
- $.extend(true, this.options, options);
- }
- });
-
- // Add some utility methods to underscore
- _.mixin({
- // produces a natural language description of the given
- // index in the given list
- nameForIndex : function(list, index) {
- return list.length === 1 ? 'first last' :
- index === 0 ? 'first' :
- index === list.length - 1 ?
- 'last' : 'middle';
- },
-
- exists : function(object) {
- return !_(object).isNull() && !_(object).isUndefined();
- },
-
- // resolves the value of the given property on the given
- // object.
- resolveProperty : function(object, property) {
- var result = null;
- if(_(property).exists() && _(property).isString()) {
- var parts = property.split('.');
- _(parts).each(function(part) {
- if(_(object).exists()) {
- var target = result || object;
- result = _(target.get).isFunction() ? target.get(part) : target[part];
- }
- });
- }
-
- return result;
- },
-
- // sets the given value for the given property on the given
- // object.
- setProperty : function(object, property, value) {
- if(!property) return;
-
- var parts = property.split('.');
- _(parts.slice(0, parts.length - 2)).each(function(part) {
- if(!_(object).isNull() && !_(object).isUndefined()){
- object = _(object.get).isFunction() ? object.get(part) : object[part];
- }
- });
-
- if(!!object) {
- if(_(object.set).isFunction()) {
- var attributes = {};
- attributes[property] = value;
- object.set(attributes);
- }
- else {
- object[property] = value;
- }
- }
- }
- });
-
- var _alignCoords = function(el, anchor, pos, xFudge, yFudge) {
- el = $(el);
- anchor = $(anchor);
- pos = pos || '';
-
- // Get anchor bounds (document relative)
- var bOffset = anchor.offset();
- var bDim = {width : anchor.width(), height : anchor.height()};
-
- // Get element dimensions
- var elbOffset = el.offset();
- var elbDim = {width : el.width(), height : el.height()};
-
- // Determine align coords (document-relative)
- var x,y;
- if (pos.indexOf('-left') >= 0) {
- x = bOffset.left;
- } else if (pos.indexOf('left') >= 0) {
- x = bOffset.left - elbDim.width;
- } else if (pos.indexOf('-right') >= 0) {
- x = (bOffset.left + bDim.width) - elbDim.width;
- } else if (pos.indexOf('right') >= 0) {
- x = bOffset.left + bDim.width;
- } else { // Default = centered
- x = bOffset.left + (bDim.width - elbDim.width)/2;
- }
-
- if (pos.indexOf('-top') >= 0) {
- y = bOffset.top;
- } else if (pos.indexOf('top') >= 0) {
- y = bOffset.top - elbDim.height;
- } else if (pos.indexOf('-bottom') >= 0) {
- y = (bOffset.top + bDim.height) - elbDim.height;
- } else if (pos.indexOf('bottom') >= 0) {
- y = bOffset.top + bDim.height;
- } else { // Default = centered
- y = bOffset.top + (bDim.height - elbDim.height)/2;
- }
-
- // Check for constrainment (default true)
- var constraint = true;
- if (pos.indexOf('no-constraint') >= 0) constraint = false;
-
- // Add fudge factors
- x += xFudge || 0;
- y += yFudge || 0;
-
- // Create bounds rect/constrain to viewport
- //var nb = new zen.util.Rect(x,y,elb.width,elb.height);
- //if (constraint) nb = nb.constrainTo(zen.util.Dom.getViewport());
-
- // Convert to offsetParent coordinates
- //if(el.offsetParent()) {
- //var ob = $(el.offsetParent).getOffset();
- //nb.translate(-ob.left, -ob.top);
- //}
-
- // Return rect, constrained to viewport
- return {x : x, y : y};
- };
-
-
- // Add some utility methods to JQuery
- _($.fn).extend({
- // aligns each element releative to the given anchor
- alignTo : function(anchor, pos, xFudge, yFudge, container) {
- _.each(this, function(el) {
- var rehide = false;
- // in order for alignTo to work properly the element needs to be visible
- // if it's hidden show it off screen so it can be positioned
- if(el.style.display === 'none') {
- rehide=true;
- $(el).css({position:'absolute',top:'-10000px', left:'-10000px', display:'block'});
- }
-
- var o = _alignCoords(el, anchor, pos, xFudge, yFudge);
- $(el).css({
- position:'absolute',
- left: Math.round(o.x) + 'px',
- top: Math.round(o.y) + 'px'
- });
-
- if(rehide) $(el).hide();
- });
- },
-
- // Hides each element the next time the user clicks the mouse or presses a
- // key. This is a one-shot action - once the element is hidden, all
- // related event handlers are removed.
- autohide : function(options) {
- _.each(this, function(el) {
- options = _.extend({
- leaveOpen : false,
- hideCallback : false,
- ignoreInputs: false,
- ignoreKeys : [],
- leaveOpenTargets : []
- }, options || {});
-
- el._autoignore = true;
- setTimeout(function() {
- el._autoignore = false; $(el).removeAttr('_autoignore');
- }, 0);
-
- if (!el._autohider) {
- el._autohider = _.bind(function(e) {
-
- var target = e.target;
- if(!$(el).is(':visible')) return;
-
- if (options.ignoreInputs && (/input|textarea|select|option/i).test(target.nodeName)) return;
- //if (el._autoignore || (options.leaveOpen && Element.partOf(e.target, el)))
- if(el._autoignore) return;
- // pass in a list of keys to ignore as autohide triggers
- if(e.type && e.type.match(/keypress/) && _.include(options.ignoreKeys, e.keyCode)) return;
-
- // allows you to provide an array of elements that should not trigger autohiding.
- // This is useful for doing thigns like a flyout menu from a pulldown
- if(options.leaveOpenTargets) {
- var ancestor = _(options.leaveOpenTargets).find(function(t) {
- return e.target == t || $(e.target).closest($(t)).length > 0;
- });
- if(!!ancestor) return;
- }
-
- var proceed = (options.hideCallback) ? options.hideCallback(el) : true;
- if (!proceed) return;
-
- $(el).hide();
- $(document).bind('click', el._autohider);
- $(document).bind('keypress', el._autohider);
- el._autohider = null;
- }, this);
-
- $(document).bind('click', el._autohider);
- $(document).bind('keypress', el._autohider);
- }
- });
- }
- });
-}(this));
-(function(){
- window.Backbone.UI.Button = Backbone.View.extend({
- options : {
- tagName : 'a',
-
- // true will disable the button
- // (muted non-clickable)
- disabled : false,
-
- // true will activate the button
- // (depressed and non-clickable)
- active : false,
-
- hasBorder : true,
-
- // A callback to invoke when the button is clicked
- onClick : null,
-
- // renders this button as an input type=submit element as opposed to an anchor.
- isSubmit : false
- },
-
- initialize : function() {
- this.mixin([Backbone.UI.HasModel, Backbone.UI.HasGlyph]);
-
- _(this).bindAll('render');
-
- $(this.el).addClass('button');
-
- // if we're running in a mobile environment, the 'click' event
- // isn't quite translated correctly
- if(document.ontouchstart !== undefined || document.ontouchstart === null) {
- $(this.el).bind('touchstart', _(function(e) {
- $(this.el).addClass('active');
-
- Backbone.UI._activeButton = this;
- var bodyUpListener = $(document.body).bind('touchend', function(e) {
- if(Backbone.UI._activeButton) {
- if(e.target === Backbone.UI._activeButton.el || $(e.target).closest('.button.active').length > 0) {
- if(Backbone.UI._activeButton.options.onClick) Backbone.UI._activeButton.options.onClick(e);
- }
- $(Backbone.UI._activeButton.el).removeClass('active');
- }
-
- Backbone.UI._activeButton = null;
- $(document.body).unbind('touchend', bodyUpListener);
- });
-
- return false;
- }).bind(this));
- }
-
- else {
- $(this.el).bind('click', _(function(e) {
- if(!this.options.disabled && !this.options.active && this.options.onClick) {
- this.options.onClick(e);
- }
- return false;
- }).bind(this));
- }
- },
-
- render : function() {
- var labelText = this.resolveContent();
-
- this._observeModel(this.render);
-
- $(this.el).empty();
- $(this.el).toggleClass('has_border', this.options.hasBorder);
-
- if(this.options.isSubmit) {
- $.el.input({
- type : 'submit',
- value : ''
- }).appendTo(this.el);
- }
-
- // insert label
- $.el.span({
- className : 'label'
- }, labelText).appendTo(this.el);
-
- // insert glyphs
- this.insertGlyph(this.el, this.options.glyph);
- this.insertGlyphRight(this.el, this.options.glyphRight);
-
- // add appropriate class names
- this.setEnabled(!this.options.disabled);
- this.setActive(this.options.active);
-
- return this;
- },
-
- // sets the enabled state of the button
- setEnabled : function(enabled) {
- if(enabled) {
- this.el.href = '#';
- } else {
- this.el.removeAttribute('href');
- }
- this.options.disabled = !enabled;
- $(this.el)[enabled ? 'removeClass' : 'addClass']('disabled');
- },
-
- // sets the active state of the button
- setActive : function(active) {
- this.options.active = active;
- $(this.el)[active ? 'addClass' : 'removeClass']('active');
- }
- });
-}());
-
-(function() {
-
- var monthNames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
- var dayNames = ['s', 'm', 't', 'w', 't', 'f', 's'];
-
- var isLeapYear = function(year) {
- return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
- };
-
- var daysInMonth = function(date) {
- return [31, (isLeapYear(date.getYear()) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][date.getMonth()];
- };
-
- var formatDateHeading = function(date) {
- return monthNames[date.getMonth()] + ' ' + date.getFullYear();
- };
-
- var isSameMonth = function(date1, date2) {
- return date1.getFullYear() === date2.getFullYear() &&
- date1.getMonth() === date2.getMonth();
- };
-
- window.Backbone.UI.Calendar = Backbone.View.extend({
- options : {
- // the selected calendar date
- date : null,
-
- // the week's start day (0 = Sunday, 1 = Monday, etc.)
- weekStart : 0,
-
- // a callback to invoke when a new date selection is made. The selected date
- // will be passed in as the first argument
- onSelect : null
- },
-
- date : null,
-
- initialize : function() {
- $(this.el).addClass('calendar');
- _(this).bindAll('render');
- },
-
- render : function() {
- if(_(this.model).exists() && _(this.options.content).exists()) {
- this.date = this.resolveContent();
- var key = 'change:' + this.options.content;
- this.model.unbind(key, this.render);
- this.model.bind(key, this.render);
- }
-
- else {
- this.date = this.date || this.options.date || new Date();
- }
-
- this._renderDate(this.date);
-
- return this;
- },
-
- _selectDate : function(date) {
- this.date = date;
- if(_(this.model).exists() && _(this.options.content).exists()) {
-
- // we only want to set the bound property's date portion
- var boundDate = this.resolveContent();
- var updatedDate = new Date(boundDate.getTime());
- updatedDate.setMonth(date.getMonth());
- updatedDate.setDate(date.getDate());
- updatedDate.setFullYear(date.getFullYear());
-
- _(this.model).setProperty(this.options.content, updatedDate);
- }
- this.render();
- if(_(this.options.onSelect).isFunction()) {
- this.options.onSelect(date);
- }
- return false;
- },
-
- _renderDate : function(date, e) {
- if(e) e.stopPropagation();
- $(this.el).empty();
-
- var nextMonth = new Date(date.getFullYear(), date.getMonth() + 1);
- var lastMonth = new Date(date.getFullYear(), date.getMonth() - 1);
- var monthStartDay = (new Date(date.getFullYear(), date.getMonth(), 1).getDay());
- var inactiveBeforeDays = monthStartDay - this.options.weekStart - 1;
- var daysInThisMonth = daysInMonth(date);
- var today = new Date();
- var inCurrentMonth = isSameMonth(today, date);
- var inSelectedMonth = !!this.date && isSameMonth(this.date, date);
-
- var daysRow = $.el.tr({className : 'row days'});
- var names = dayNames.slice(this.options.weekStart).concat(
- dayNames.slice(0, this.options.weekStart));
- for(var i=0; i<names.length; i++) {
- $.el.td(names[i]).appendTo(daysRow);
- }
-
- var tbody, table = $.el.table(
- $.el.thead(
- $.el.th(
- $.el.a({className : 'go_back', onclick : _(this._renderDate).bind(this, lastMonth)}, '\u2039')),
- $.el.th({className : 'title', colspan : 5},
- $.el.div(formatDateHeading(date))),
- $.el.th(
- $.el.a({className : 'go_forward', onclick : _(this._renderDate).bind(this, nextMonth)}, '\u203a'))),
- tbody = $.el.tbody(daysRow));
-
- var day = inactiveBeforeDays >= 0 ? daysInMonth(lastMonth) - inactiveBeforeDays : 1;
- var daysRendered = 0;
- for(var rowIndex=0; rowIndex<6 ; rowIndex++) {
-
- var row = $.el.tr({
- className : 'row' + (rowIndex === 0 ? ' first' : rowIndex === 4 ? ' last' : '')
- });
-
- for(var colIndex=0; colIndex<7; colIndex++) {
- var inactive = daysRendered <= inactiveBeforeDays ||
- daysRendered > inactiveBeforeDays + daysInThisMonth;
-
- var callback = _(this._selectDate).bind(
- this, new Date(date.getFullYear(), date.getMonth(), day));
-
- var className = 'cell' + (inactive ? ' inactive' : '') +
- (colIndex === 0 ? ' first' : colIndex === 6 ? ' last' : '') +
- (inCurrentMonth && !inactive && day === today.getDate() ? ' today' : '') +
- (inSelectedMonth && !inactive && day == this.date.getDate() ? ' selected' : '');
-
- $.el.td({ className : className },
- inactive ?
- $.el.div({ className : 'day' }, day) :
- $.el.a({ className : 'day', onClick : callback }, day)).appendTo(row);
-
- day = (rowIndex === 0 && colIndex == inactiveBeforeDays) ||
- (rowIndex > 0 && day == daysInThisMonth) ? 1 : day + 1;
-
- daysRendered++;
- }
-
- row.appendTo(tbody);
- }
-
- this.el.appendChild(table);
-
- return false;
- }
- });
-}());
-(function(){
- window.Backbone.UI.Checkbox = Backbone.View.extend({
-
- options : {
- tagName : 'a',
-
- // The property of the model describing the label that
- // should be placed next to the checkbox
- labelContent : null,
-
- // enables / disables the checkbox
- disabled : false
- },
-
- initialize : function() {
- this.mixin([Backbone.UI.HasModel]);
- _(this).bindAll('render');
-
- $(this.el).click(_(this._onClick).bind(this));
- $(this.el).attr({href : '#'});
- $(this.el).addClass('checkbox');
- },
-
- render : function() {
-
- this._observeModel(this.render);
-
- $(this.el).empty();
-
- this.checked = this.checked || this.resolveContent();
- var mark = $.el.div({className : 'checkmark'});
- if(this.checked) {
- mark.appendChild($.el.div({className : 'checkmark_fill'}));
- }
-
- var labelText = _(this.model).resolveProperty(this.options.labelContent);
- this._label = $.el.div({className : 'label'}, labelText);
-
- this.el.appendChild(mark);
- this.el.appendChild(this._label);
- this.el.appendChild($.el.br({style : 'clear:both'}));
-
- return this;
- },
-
- _onClick : function() {
- if (this.options.disabled) {
- return false;
- }
-
- this.checked = !this.checked;
- if(_(this.model).exists() && _(this.options.content).exists()) {
- _(this.model).setProperty(this.options.content, this.checked);
- }
-
- else {
- this.render();
- }
-
- return false;
- }
- });
-}());
-(function(){
- window.Backbone.UI.CollectionView = Backbone.View.extend({
- options : {
- // The Backbone.Collection instance the view is bound to
- model : null,
-
- // The Backbone.View class responsible for rendering a single item in the collection
- itemView : null,
-
- // A string, element, or function describing what should be displayed
- // when the list is empty.
- emptyContent : null,
-
- // A callback to invoke when a row is clicked. The associated model will be
- // passed as the first argument.
- onItemClick : Backbone.UI.noop,
-
- // The maximum height in pixels that this table show grow to. If the
- // content exceeds this height, it will become scrollable.
- maxHeight : null
- },
-
- itemViews : {},
-
- _emptyContent : null,
-
- // must be over-ridden to describe how an item is rendered
- _renderItem : Backbone.UI.noop,
-
- initialize : function() {
- if(this.model) {
- this.model.bind('add', _.bind(this._onItemAdded, this));
- this.model.bind('change', _.bind(this._onItemChanged, this));
- this.model.bind('remove', _.bind(this._onItemRemoved, this));
- this.model.bind('refresh', _.bind(this.render, this));
- this.model.bind('reset', _.bind(this.render, this));
- }
- },
-
- _onItemAdded : function(model, list, options) {
- // first check if we've already rendered an item for this model
- if(!!this.itemViews[model.cid]) {
- return;
- }
-
- // remove empty content if it exists
- if(!!this._emptyContent) {
- if(!!this._emptyContent.parentNode) this._emptyContent.parentNode.removeChild(this._emptyContent);
- this._emptyContent = null;
- }
-
- // render the new item
- var el = this._renderItem(model, list.indexOf(model));
-
- // insert it into the DOM position that matches it's position in the model
- var properIndex = list.indexOf(model);
- var anchorNode = this.collectionEl.childNodes[properIndex];
- this.collectionEl.insertBefore(el, _(anchorNode).isUndefined() ? null : anchorNode);
-
- // update the first / last class names
- this._updateClassNames();
- },
-
- _onItemChanged : function(model) {
- var view = this.itemViews[model.cid];
- // re-render the individual item view if it's a backbone view
- if(!!view && view.el && view.el.parentNode) {
- view.render();
- this._ensureProperPosition(view);
- }
-
- // otherwise, we re-render the entire collection
- else {
- this.render();
- }
- },
-
- _onItemRemoved : function(model) {
- var view = this.itemViews[model.cid];
- var liOrTrElement = view.el.parentNode;
- if(!!view && !!liOrTrElement && !!liOrTrElement.parentNode) {
- liOrTrElement.parentNode.removeChild(liOrTrElement);
- }
- delete(this.itemViews[model.cid]);
-
- // update the first / last class names
- this._updateClassNames();
- },
-
- _updateClassNames : function() {
- var children = this.collectionEl.childNodes;
- if(children.length > 0) {
- _(children).each(function(child) {
- $(child).removeClass('first');
- $(child).removeClass('last');
- });
- $(children[0]).addClass('first');
- $(children[children.length - 1]).addClass('last');
- }
- },
-
- _ensureProperPosition : function(view) {
- if(_(this.model.comparator).isFunction()) {
- this.model.sort({silent : true});
- var itemEl = view.el.parentNode;
- var currentIndex = Array.prototype.indexOf.call(
- this.collectionEl.childNodes, itemEl);
- var properIndex = this.model.indexOf(view.model);
- if(currentIndex !== properIndex) {
- itemEl.parentNode.removeChild(itemEl);
- var refNode = this.collectionEl.childNodes[properIndex];
- this.collectionEl.insertBefore(itemEl, refNode);
- }
- }
- }
- });
-}());
-
-(function(){
- window.Backbone.UI.DatePicker = Backbone.View.extend({
-
- options : {
- // a moment.js format : http://momentjs.com/docs/#/display/format
- format : 'MM/DD/YYYY',
- date : null,
- name : null,
- onChange : null
- },
-
- initialize : function() {
- $(this.el).addClass('date_picker');
-
- this._calendar = new Backbone.UI.Calendar({
- className : 'date_picker_calendar',
- model : this.model,
- property : this.options.content,
- onSelect : _(this._selectDate).bind(this)
- });
- $(this._calendar.el).hide();
- document.body.appendChild(this._calendar.el);
-
- $(this._calendar.el).autohide({
- ignoreInputs : true,
- leaveOpenTargets : [this._calendar.el]
- });
-
- // listen for model changes
- if(!!this.model && this.options.content) {
- this.model.bind('change:' + this.options.content, _(this.render).bind(this));
- }
- },
-
- render : function() {
- $(this.el).empty();
-
- this._textField = new Backbone.UI.TextField({
- name : this.options.name
- }).render();
-
- $(this._textField.input).click(_(this._showCalendar).bind(this));
- $(this._textField.input).keyup(_(this._dateEdited).bind(this));
-
- this.el.appendChild(this._textField.el);
-
- this._selectedDate = (!!this.model && !!this.options.content) ?
- this.resolveContent() : this.options.date;
-
- if(!!this._selectedDate) {
- this._calendar.options.selectedDate = this._selectedDate;
- var dateString = moment(this._selectedDate).format(this.options.format);
- this._textField.setValue(dateString);
- }
- this._calendar.render();
-
- return this;
- },
-
- setEnabled : function(enabled) {
- this._textField.setEnabled(enabled);
- },
-
- getValue : function() {
- return this._selectedDate;
- },
-
- setValue : function(date) {
- this._selectedDate = date;
- var dateString = moment(date).format(this.options.format);
- this._textField.setValue(dateString);
- this._dateEdited();
- },
-
- _showCalendar : function() {
- $(this._calendar.el).show();
- $(this._calendar.el).alignTo(this._textField.el, 'bottom -left', 0, 2);
- },
-
- _hideCalendar : function() {
- $(this._calendar.el).hide();
- },
-
- _selectDate : function(date) {
- var month = date.getMonth() + 1;
- if(month < 10) month = '0' + month;
-
- var day = date.getDate();
- if(day < 10) day = '0' + day;
-
- var dateString = moment(date).format(this.options.format);
- this._textField.setValue(dateString);
- this._dateEdited();
- this._hideCalendar();
-
- return false;
- },
-
- _dateEdited : function(e) {
- var newDate = moment(this._textField.getValue(), this.options.format);
- this._selectedDate = newDate.toDate();
-
- // if the enter key was pressed or we've invoked this method manually,
- // we hide the calendar and re-format our date
- if(!e || e.keyCode == Backbone.UI.KEYS.KEY_RETURN) {
- var newValue = moment(newDate).format(this.options.format);
- this._textField.setValue(newValue);
- this._hideCalendar();
-
- // update our bound model (but only the date portion)
- if(!!this.model && this.options.content) {
- var boundDate = this.resolveContent();
- var updatedDate = new Date(boundDate.getTime());
- updatedDate.setMonth(newDate.month());
- updatedDate.setDate(newDate.date());
- updatedDate.setFullYear(newDate.year());
- _(this.model).setProperty(this.options.content, updatedDate);
- }
-
- if(_(this.options.onChange).isFunction()) {
- this.options.onChange(newValue);
- }
- }
- }
- });
-}());
-(function() {
- Backbone.UI.DragSession = function(options) {
- this.options = _.extend({
- // A mouse(move/down) event
- dragEvent : null,
-
- //The document in which the drag session should occur
- scope : null,
-
- //Sent when the session is ends up being a sloppy mouse click
- onClick: Backbone.UI.noop,
-
- // Sent when a drag session starts for real
- // (after the mouse has moved SLOP pixels)
- onStart: Backbone.UI.noop,
-
- // Sent for each mouse move event that occurs during the drag session
- onMove: Backbone.UI.noop,
-
- // Sent when the session stops normally (the mouse was released)
- onStop: Backbone.UI.noop,
-
- // Sent when the session is aborted (ESC key pressed)
- onAbort: Backbone.UI.noop,
-
- // Sent when the drag session finishes, regardless of
- // whether it stopped normally or was aborted.
- onDone: Backbone.UI.noop
- }, options);
-
- if(Backbone.UI.DragSession.currentSession) {
- // Abort any existing drag session. While this should never happen in
- // theory, in practice it happens a fair bit (e.g. if a mouseup occurs
- // outside the document). So we don't complain about.
- Backbone.UI.DragSession.currentSession.abort();
- }
-
- this._doc = this.options.scope || document;
-
- this._handleEvent = _.bind(this._handleEvent, this);
- this._handleEvent(this.options.dragEvent);
-
- // Activate handlers
- this._activate(true);
-
- this.options.dragEvent.stopPropagation();
-
- /**
- * currentSession The currently active drag session.
- */
- Backbone.UI.DragSession.currentSession = this;
- };
-
- // add class methods
- _.extend(Backbone.UI.DragSession, {
- SLOP : 2,
-
- BASIC_DRAG_CLASSNAME: 'dragging',
-
- // Enable basic draggable element behavior for absolutely positioned elements.
- // scope: The window/document to enable dragging on. Default is current document.
- // container: a container element to constrain dragging within
- // shield: if true the draggable will use a shield iframe useful for
- // covering controls that bleed through zindex layers
- enableBasicDragSupport : function(scope, container, shield) {
- var d = scope ? (scope.document || scope) : document;
- if (d._basicDragSupportEnabled) return;
- d._basicDragSupportEnabled = true;
- // Enable "draggable"/"grabbable" classes
- $(d).bind('mousedown', function(e) {
- var el = e.target;
-
- // Ignore clicks that happen on anything the user might want to
- // interact with input elements
- var IGNORE = /(input|textarea|button|select|option)/i;
- if (IGNORE.exec(el.nodeName)) return;
-
- // Find the element to drag
- if (!el.hasClassName) return; // flash objects don't support this method
- // and should not be draggable
- // this fixes a problem in Shareflow in IE7
- // with the upload button
- var del = el.hasClassName('draggable') ? el : el.up('.draggable');
- del = del ? del.up('.draggable-container') || del : null;
-
- if (del) {
- // Get the allowable bounds to drag w/in
- // if (container) container = $(container);
- // var vp = container ? container.getBounds() : zen.util.Dom.getViewport(del.ownerDocument);
- //var vp = zen.util.Dom.getViewport(del.ownerDocument);
- var elb = del.getBounds();
-
- // Create a new drag session
- var activeElement = document.activeElement;
- var ds = new Backbone.UI.DragSession({
- dragEvent : e,
- scope : del.ownerDocument,
- onStart : function(ds) {
- if (activeElement && activeElement.blur) activeElement.blur();
- ds.pos = del.positionedOffset();
- $(del).addClass(Backbone.UI.DragSession.BASIC_DRAG_CLASSNAME);
- },
- onMove : function(ds) {
- //elb.moveTo(ds.pos.left + ds.dx, ds.pos.top + ds.dy).constrainTo(vp);
- del.style.left = elb.x + 'px';
- del.style.top = elb.y + 'px';
- },
- onDone : function(ds) {
- if (activeElement && activeElement.focus) activeElement.focus();
- del.removeClassName(Backbone.UI.DragSession.BASIC_DRAG_CLASSNAME);
- }
- });
- }
- });
- }
- });
-
- // add instance methods
- _.extend(Backbone.UI.DragSession.prototype, {
-
- // Fire the onStop event and stop the drag session.
- stop: function() {
- this._stop();
- },
-
- // Fire the onAbort event and stop the drag session.
- abort: function() {
- this._stop(true);
- },
-
- // Activate the session by registering/unregistering event handlers
- _activate: function(flag) {
- var f = flag ? 'bind' : 'unbind';
- $(this._doc)[f]('mousemove', this._handleEvent);
- $(this._doc)[f]('mouseup', this._handleEvent);
- $(this._doc)[f]('keyup', this._handleEvent);
- },
-
- // All-in-one event handler for managing a drag session
- _handleEvent: function(e) {
- e.stopPropagation();
- e.preventDefault();
-
- this.x = e.pageX;
- this.y = e.pageY;
-
- if (e.type === 'mousedown') {
- // Absolute X of initial mouse down*/
- this.xStart = this.x;
-
- // Absolute Y of initial mouse down
- this.yStart = this.y;
- }
-
- // X-coord relative to initial mouse down
- this.dx = this.x - this.xStart;
-
- // Y-coord relative to initial mouse down
- this.dy = this.y - this.yStart;
-
- switch (e.type) {
- case 'mousemove':
- if (!this._dragging) {
- // Sloppy click?
- if(this.dx * this.dx + this.dy * this.dy >= Backbone.UI.DragSession.SLOP * Backbone.UI.DragSession.SLOP) {
- this._dragging = true;
- this.options.onStart(this, e);
- }
- } else {
- this.options.onMove(this, e);
- }
- break;
- case 'mouseup':
- if (!this._dragging) {
- this.options.onClick(this, e);
- } else {
- this.stop();
- }
- //this._stop();
- break;
- case 'keyup':
- if (e.keyCode !== Backbone.UI.KEYS.KEY_ESC) return;
- this.abort();
- break;
- default:
- return;
- }
- },
-
- // Stop the drag session
- _stop: function(abort) {
- Backbone.UI.DragSession.currentSession = null;
-
- // Deactivate handlers
- this._activate(false);
-
- if (this._dragging) {
- if (abort) {
- this.options.onAbort(this);
- } else {
- this.options.onStop(this);
- }
- this.options.onDone(this);
- }
- }
- });
-}());
-
- // A mixin for dealing with collection alternatives
-(function(){
- Backbone.UI.HasAlternativeProperty = {
- options : {
- // The collection of items representing alternative choices
- alternatives : null,
-
- // The property of the individual choice represent the the label to be displayed
- altLabelContent : null,
-
- // The property of the individual choice that represents the value to be stored
- // in the bound model's property. Omit this option if you'd like the choice
- // object itself to represent the value.
- altValueContent : null
- },
-
- _determineSelectedItem : function() {
- var item;
-
- // if a bound property has been given, we attempt to resolve it
- if(_(this.model).exists() && _(this.options.content).exists()) {
- item = _(this.model).resolveProperty(this.options.content);
-
- // if a value property is given, we further resolve our selected item
- if(_(this.options.altValueContent).exists()) {
- var otherItem = _(this._collectionArray()).detect(function(collectionItem) {
- return (collectionItem.attributes || collectionItem)[this.options.altValueContent] === item;
- }, this);
- if(!_(otherItem).isUndefined()) item = otherItem;
- }
- }
-
- return item || this.options.selectedItem;
- },
-
- _setSelectedItem : function(item) {
- this.selectedValue = item;
- this.selectedItem = item;
-
- if(_(this.model).exists() && _(this.options.content).exists()) {
- this.selectedValue = this._valueForItem(item);
- _(this.model).setProperty(this.options.content, this.selectedValue);
- }
- },
-
- _valueForItem : function(item) {
- return _(this.options.altValueContent).exists() ?
- _(item).resolveProperty(this.options.altValueContent) :
- item;
- },
-
- _collectionArray : function() {
- return _(this.options.alternatives).exists() ?
- this.options.alternatives.models || this.options.alternatives : [];
- },
-
- _observeCollection : function(callback) {
- if(_(this.options.alternatives).exists() && _(this.options.alternatives.bind).exists()) {
- var key = 'change';
- this.options.alternatives.unbind(key, callback);
- this.options.alternatives.bind(key, callback);
- }
- }
- };
-}());
-
-// A mixin for dealing with glyphs in widgets
-(function(){
- Backbone.UI.HasGlyph = {
- GLYPH_SIZE : 22,
-
- options : {
-
- },
-
- insertGlyph : function(el, name) {
- return this._insertGlyph(el, name, false);
- },
-
- insertGlyphRight : function(el, name) {
- return this._insertGlyph(el, name, true);
- },
-
- _insertGlyph : function(el, name, isRight) {
- var hasGlyphClassName = isRight ? 'has_glyph_right' : 'has_glyph';
- if(!name || !el) {
- $(el).removeClass(hasGlyphClassName);
- return null;
- }
- $(el).addClass(hasGlyphClassName);
-
- var className = 'glyph ' + name + (isRight ? ' right' : '');
- var image;
- if(name.length === 1) {
- var span = $.el.span({
- className : className,
- style : 'margin: 0 8px 0 0'
- }, name);
- el.insertBefore(span, isRight ? null : el.firstChild);
- }
-
- else {
- image = new Image();
- $(image).hide();
- image.onload = function() {
- // center the image inside a 28px square
- var topOffset = Math.max(1, ((28 - image.height) / 2));
- var leftOffset = Math.max(3, ((28 - image.width) / 2));
-
- $(image).css({
- top : topOffset + 'px',
- left : isRight ? 'auto' : leftOffset + 'px',
- right : isRight ? leftOffset + 'px' : 'auto'
- });
- $(image).show();
- };
- if (!!Backbone.UI.GLYPH_URL_MAP && !!Backbone.UI.GLYPH_URL_MAP[name]) {
- image.src = Backbone.UI.GLYPH_URL_MAP[name];
- } else {
- image.src = Backbone.UI.IMAGE_DIR_PATH + '/glyphs/' + name + '.png';
- }
- image.className = className;
-
- el.insertBefore(image, isRight ? null : el.firstChild);
- }
-
- return image;
- }
- };
-}());
- // A mixin for those views that are model bound
-(function(){
- Backbone.UI.HasModel = {
-
- options : {
- // The Backbone.Model instance the view is bound to
- model : null,
-
- // The property of the bound model this component should render / update.
- // If a function is given, it will be invoked with the model and will
- // expect an element to be returned. If no model is present, this
- // property may be a string or function describing the content to be rendered
- content : null
- },
-
- _observeModel : function(callback) {
- if(_(this.model).exists() && _(this.model.unbind).isFunction()) {
- _(['content', 'labelContent']).each(function(prop) {
- var key = this.options[prop];
- if(_(key).exists()) {
- key = 'change:' + key;
- this.model.unbind(key, callback);
- this.model.bind(key, callback);
- }
- }, this);
- }
- }
- };
-}());
-
-(function(){
- window.Backbone.UI.Link = Backbone.View.extend({
- options : {
- tagName : 'a',
-
- // disables the link (non-clickable)
- disabled : false,
-
- // A callback to invoke when the link is clicked
- onClick : null
- },
-
- initialize : function() {
- this.mixin([Backbone.UI.HasModel, Backbone.UI.HasGlyph]);
-
- _(this).bindAll('render');
-
- $(this.el).addClass('link');
-
- $(this.el).bind('click', _(function(e) {
- if(!this.options.disabled && this.options.onClick) {
- this.options.onClick(e);
- }
- return false;
- }).bind(this));
- },
-
- render : function() {
- var labelText = this.resolveContent();
-
- this._observeModel(this.render);
-
- $(this.el).empty();
-
- // insert label
- $.el.span({
- className : 'label'
- }, labelText).appendTo(this.el);
-
- // insert glyphs
- this.insertGlyph(this.el, this.options.glyph);
- this.insertGlyphRight(this.el, this.options.glyphRight);
-
- // add appropriate class names
- this.setEnabled(!this.options.disabled);
-
- return this;
- },
-
- // sets the enabled state of the button
- setEnabled : function(enabled) {
- if(enabled) {
- this.el.href = '#';
- } else {
- this.el.removeAttribute('href');
- }
- this.options.disabled = !enabled;
- $(this.el)[enabled ? 'removeClass' : 'addClass']('disabled');
- }
- });
-}());
-
-(function(){
- window.Backbone.UI.List = Backbone.UI.CollectionView.extend({
- options : {
- // A Backbone.View implementation describing how to render a particular
- // item in the collection. For simple use cases, you can pass a String
- // instead which will be interpreted as the property of the model to display.
- itemView : null
- },
-
- initialize : function() {
- Backbone.UI.CollectionView.prototype.initialize.call(this, arguments);
- $(this.el).addClass('list');
- },
-
- render : function() {
- $(this.el).empty();
- this.itemViews = {};
-
- this.collectionEl = $.el.ul();
-
- // if the collection is empty, we render the empty content
- if(!_(this.model).exists() || this.model.length === 0) {
- this._emptyContent = _(this.options.emptyContent).isFunction() ?
- this.options.emptyContent() : this.options.emptyContent;
- this._emptyContent = $.el.li(this._emptyContent);
-
- if(!!this._emptyContent) {
- this.collectionEl.appendChild(this._emptyContent);
- }
- }
-
- // otherwise, we render each row
- else {
- _(this.model.models).each(function(model, index) {
- var item = this._renderItem(model, index);
- this.collectionEl.appendChild(item);
- }, this);
- }
-
- // wrap the list in a scroller
- if(_(this.options.maxHeight).exists()) {
- var style = 'max-height:' + this.options.maxHeight + 'px';
- var scroller = new Backbone.UI.Scroller({
- content : $.el.div({style : style}, this.collectionEl)
- }).render();
-
- this.el.appendChild(scroller.el);
- }
- else {
- this.el.appendChild(this.collectionEl);
- }
-
- this._updateClassNames();
-
- return this;
- },
-
- // renders an item for the given model, at the given index
- _renderItem : function(model, index) {
- var content;
- if(_(this.options.itemView).exists()) {
-
- if(_(this.options.itemView).isString()) {
- content = this.resolveContent(model, this.options.itemView);
- }
-
- else {
- var view = new this.options.itemView({
- model : model
- });
- view.render();
- this.itemViews[model.cid] = view;
- content = view.el;
- }
- }
-
- var item = $.el.li(content);
-
- // bind the item click callback if given
- if(this.options.onItemClick) {
- $(item).click(_(this.options.onItemClick).bind(this, model));
- }
-
- return item;
- }
- });
-}());
-
-(function(){
- window.Backbone.UI.Menu = Backbone.View.extend({
-
- options : {
- // an additional item to render at the top of the menu to
- // denote the lack of a selection
- emptyItem : null
- },
-
- initialize : function() {
- this.mixin([Backbone.UI.HasModel, Backbone.UI.HasAlternativeProperty]);
-
- _(this).bindAll('render');
-
- $(this.el).addClass('menu');
-
- this._textField = new Backbone.UI.TextField().render();
- },
-
- scroller : null,
-
- render : function() {
- $(this.el).empty();
-
- this._observeModel(this.render);
- this._observeCollection(this.render);
-
- // create a new list of items
- var list = $.el.ul();
-
- // add entry for the empty model if it exists
- if(!!this.options.emptyItem) {
- this._addItemToMenu(list, this.options.emptyItem);
- }
-
- var selectedItem = this._determineSelectedItem();
-
- _(this._collectionArray()).each(function(item) {
- var selectedValue = this._valueForItem(selectedItem);
- var itemValue = this._valueForItem(item);
- this._addItemToMenu(list, item, _(selectedValue).isEqual(itemValue));
- }, this);
-
- // wrap them up in a scroller
- this.scroller = new Backbone.UI.Scroller({
- content : list
- }).render();
-
- // Prevent scroll events from percolating out to the enclosing doc
- $(this.scroller.el).bind('mousewheel', function(){return false;});
- $(this.scroller.el).addClass('menu_scroller');
-
- this.el.appendChild(this.scroller.el);
- this._menuWidth = $(this.scroller.el).width() + 20;
-
- return this;
- },
-
- scrollToSelectedItem : function() {
- if(!this._selectedAnchor) return;
-
- var pos = $(this._selectedAnchor.parentNode).position().top - 10;
- this.scroller.setScrollPosition(pos);
- },
-
- // Adds the given item (creating a new li element)
- // to the given menu ul element
- _addItemToMenu : function(menu, item, select) {
- var anchor = $.el.a({href : '#'},
- $.el.span(this._labelForItem(item) || '\u00a0'));
-
- var glyph;
- if(this.options.glyphProperty) {
- glyph = _(item).resolveProperty(this.options.glyphProperty);
- Backbone.UI.HasGlyph.insertGlyph(anchor, glyph);
- }
-
- if(this.options.glyphRightProperty) {
- glyph = _(item).resolveProperty(this.options.glyphRightProperty);
- Backbone.UI.HasGlyph.insertGlyphRight(anchor, glyph);
- }
-
- var liElement = $.el.li(anchor);
-
- var clickFunction = _.bind(function(e) {
- if(!!this._selectedAnchor) $(this._selectedAnchor).removeClass('selected');
-
- this._setSelectedItem(_(item).isEqual(this.options.emptyItem) ? null : item);
- this._selectedAnchor = anchor;
- $(anchor).addClass('selected');
-
- if(_(this.options.onChange).isFunction()) this.options.onChange(item);
- return false;
- }, this);
-
- $(anchor).click(clickFunction);
-
- if(select) clickFunction();
-
- menu.appendChild(liElement);
- },
-
- _labelForItem : function(item) {
- return !_(item).exists() ? this.options.placeholder :
- _(item).resolveProperty(this.options.altLabelContent);
- }
- });
-}());
-(function(){
- window.Backbone.UI.Pulldown = Backbone.View.extend({
- options : {
- // text to place in the pulldown button before a
- // selection has been made
- placeholder : 'Select...',
-
- // If true, the menu will be aligned to the right side
- alignRight : false,
-
- // A callback to invoke with a particular item when that item is
- // selected from the pulldown menu.
- onChange : Backbone.UI.noop,
-
- // A callback to invoke when the pulldown menu is shown, passing the
- // button click event.
- onMenuShow : Backbone.UI.noop,
-
- // A callback to invoke when the pulldown menu is hidden, if the menu was hidden
- // as a result of a second click on the pulldown button, the button click event
- // will be passed.
- onMenuHide : Backbone.UI.noop
- },
-
- initialize : function() {
- this.mixin([Backbone.UI.HasGlyph]);
- $(this.el).addClass('pulldown');
-
- var onChange = this.options.onChange;
- delete(this.options.onChange);
- var menuOptions = _(this.options).extend({
- onChange : _(function(item){
- this._onItemSelected(item);
- if(_(onChange).isFunction()) onChange(item);
- }).bind(this)
- });
-
- this._menu = new Backbone.UI.Menu(menuOptions).render();
- $(this._menu.el).autohide({
- ignoreKeys : [Backbone.UI.KEYS.KEY_UP, Backbone.UI.KEYS.KEY_DOWN],
- ignoreInputs : false,
- hideCallback : _.bind(this._onAutoHide, this)
- });
- $(this._menu.el).hide();
- document.body.appendChild(this._menu.el);
-
- // observe model changes
- if(_(this.model).exists() && _(this.model.bind).isFunction()) {
- this.model.unbind('change', _(this.render).bind(this));
-
- // observe model changes
- if(_(this.options.content).exists()) {
- this.model.bind('change:' + this.options.content, _(this.render).bind(this));
- }
- }
-
- // observe collection changes
- if(_(this.options.alternatives).exists() && _(this.options.alternatives.bind).isFunction()) {
- this.options.alternatives.unbind('all', _(this.render).bind(this));
- this.options.alternatives.bind('all', _(this.render).bind(this));
- }
- },
-
- // public accessors
- button : null,
-
- render : function() {
- $(this.el).empty();
-
- var item = this._menu.selectedItem;
- this.button = new Backbone.UI.Button({
- className : 'pulldown_button',
- model : {label : this._labelForItem(item)},
- content : 'label',
- glyph : _(item).resolveProperty(this.options.glyphProperty),
- glyphRight : '\u25bc',
- onClick : _.bind(this.showMenu, this)
- }).render();
- this.el.appendChild(this.button.el);
-
- return this;
- },
-
- setEnabled : function(enabled) {
- if(this.button) this.button.setEnabled(enabled);
- },
-
- _labelForItem : function(item) {
- return !_(item).exists() ? this.options.placeholder :
- _(item).resolveProperty(this.options.altLabelContent);
- },
-
- // sets the selected item
- setSelectedItem : function(item) {
- this._setSelectedItem(item);
- this.button.options.label = this._labelForItem(item);
- this.button.options.glyph = _(item).resolveProperty(this.options.glyphProperty);
- this.button.render();
- },
-
- // Forces the menu to hide
- hideMenu : function(event) {
- $(this._menu.el).hide();
- if(this.options.onMenuHide) this.options.onMenuHide(event);
- },
-
- //forces the menu to show
- showMenu : function(e) {
- var anchor = this.button.el;
- var showOnTop = $(window).height() - ($(anchor).offset().top - document.body.scrollTop) < 150;
- var position = (this.options.alignRight ? '-right' : '-left') + (showOnTop ? 'top' : ' bottom');
- $(this._menu.el).alignTo(anchor, position, 0, 1);
- $(this._menu.el).show();
- $(this._menu.el).css({width : Math.max($(this.button.el).innerWidth(), this._menuWidth)});
- if(this.options.onMenuShow) this.options.onMenuShow(e);
- this._menu.scrollToSelectedItem();
- },
-
- _onItemSelected : function(item) {
- if(!!this.button) {
- $(this.el).removeClass('placeholder');
- this.button.options.label = this._labelForItem(item);
- this.button.options.glyph = _(item).resolveProperty(this.options.glyphProperty);
- this.button.render();
- this.hideMenu();
- }
- },
-
- // notify of the menu hiding
- _onAutoHide : function() {
- if(this.options.onMenuHide) this.options.onMenuHide();
- return true;
- }
- });
-}());
-(function(){
- window.Backbone.UI.RadioGroup = Backbone.View.extend({
-
- options : {
- // A callback to invoke with the selected item whenever the selection changes
- onChange : Backbone.UI.noop
- },
-
- initialize : function() {
- this.mixin([Backbone.UI.HasGlyph, Backbone.UI.HasModel, Backbone.UI.HasAlternativeProperty]);
- _(this).bindAll('render');
- $(this.el).addClass('radio_group');
- },
-
- // public accessors
- selectedItem : null,
-
- render : function() {
-
- $(this.el).empty();
-
- this._observeModel(this.render);
- this._observeCollection(this.render);
-
- this.selectedItem = this._determineSelectedItem();
-
- var ul = $.el.ul();
- var selectedValue = this._valueForItem(this.selectedItem);
- _(this._collectionArray()).each(function(item) {
-
- var selected = selectedValue === this._valueForItem(item);
-
- var label = this.resolveContent(item, this.options.altLabelContent);
-
- var li = $.el.li(
- $.el.a({className : 'choice' + (selected ? ' selected' : '')},
- $.el.div({className : 'mark' + (selected ? ' selected' : '')},
- selected ? '\u25cf' : ''),
- $.el.div({className : 'label'}, label)));
- ul.appendChild(li);
-
- $(li).bind('click', _.bind(this._onChange, this, item));
-
- }, this);
- this.el.appendChild(ul);
-
- return this;
- },
-
- _onChange : function(item) {
- this._setSelectedItem(item);
- this.render();
-
- if(_(this.options.onChange).isFunction()) this.options.onChange(item);
- return false;
- }
- });
-}());
-(function(){
-
- window.Backbone.UI.Scroller = Backbone.View.extend({
- options : {
- className : 'scroller',
-
- // The content to be scrolled. This element should be
- // of a fixed height.
- content : null,
-
- // The amount to scroll on each wheel click
- scrollAmount : 5,
-
- // A callback to invoke when scrolling occurs
- onScroll : null
- },
-
- initialize : function() {
- Backbone.UI.DragSession.enableBasicDragSupport();
- setInterval(_(this.update).bind(this), 40);
- },
-
- render : function () {
- $(this.el).empty();
- $(this.el).addClass('scroller');
-
- this._scrollContent = this.options.content;
- $(this._scrollContent).addClass('content');
-
- this._knob = $.el.div({className : 'knob'},
- $.el.div({className : 'knob_top'}),
- $.el.div({className : 'knob_middle'}),
- $.el.div({className : 'knob_bottom'}));
-
- this._tray = $.el.div({className : 'tray'});
- this._tray.appendChild(this._knob);
-
- // for firefox on windows we need to wrap the scroller content in an overflow
- // auto div to avoid a rendering bug that causes artifacts on the screen when
- // the hidden content is scrolled...wsb
- this._scrollContentWrapper = $.el.div({className : 'content_wrapper'});
- this._scrollContentWrapper.appendChild(this._scrollContent);
-
- this.el.appendChild(this._tray);
- this.el.appendChild(this._scrollContentWrapper);
-
- // FF workaround: Set tabIndex so the user can click on the div to give
- // it focus (which allows us to capture the up/down/pageup/pagedown
- // keys). (And setting it to -1 keeps it out of the tab-navigation