Adds Bootstrap color and date pickers.
authordsc <dsc@wikimedia.org>
Mon, 7 May 2012 14:13:17 +0000 (07:13 -0700)
committerdsc <dsc@wikimedia.org>
Mon, 7 May 2012 14:13:17 +0000 (07:13 -0700)
12 files changed:
static/vendor/bootstrap-colorpicker.js [new symlink]
static/vendor/bootstrap-colorpicker/css/_colorpicker.css [new file with mode: 0644]
static/vendor/bootstrap-colorpicker/css/colorpicker.css [new file with mode: 0644]
static/vendor/bootstrap-colorpicker/img/alpha.png [new file with mode: 0644]
static/vendor/bootstrap-colorpicker/img/hue.png [new file with mode: 0644]
static/vendor/bootstrap-colorpicker/img/saturation.png [new file with mode: 0644]
static/vendor/bootstrap-colorpicker/js/bootstrap-colorpicker.js [new file with mode: 0644]
static/vendor/bootstrap-colorpicker/less/colorpicker.less [new file with mode: 0644]
static/vendor/bootstrap-datepicker.js [new symlink]
static/vendor/bootstrap-datepicker/css/datepicker.css [new file with mode: 0644]
static/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js [new file with mode: 0644]
static/vendor/bootstrap-datepicker/less/datepicker.less [new file with mode: 0644]

diff --git a/static/vendor/bootstrap-colorpicker.js b/static/vendor/bootstrap-colorpicker.js
new file mode 120000 (symlink)
index 0000000..fac3e6f
--- /dev/null
@@ -0,0 +1 @@
+bootstrap-colorpicker/js/bootstrap-colorpicker.js
\ No newline at end of file
diff --git a/static/vendor/bootstrap-colorpicker/css/_colorpicker.css b/static/vendor/bootstrap-colorpicker/css/_colorpicker.css
new file mode 100644 (file)
index 0000000..82dfa7d
--- /dev/null
@@ -0,0 +1,127 @@
+/*!
+* Colorpicker for Bootstrap
+*
+* Copyright 2012 Stefan Petre
+* Licensed under the Apache License v2.0
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+*/
+.colorpicker-saturation {
+width: 100px;
+height: 100px;
+background-image: url(../img/saturation.png);
+cursor: crosshair;
+float: left;
+}
+.colorpicker-saturation i {
+display: block;
+height: 5px;
+width: 5px;
+border: 1px solid #000;
+-webkit-border-radius: 5px;
+-moz-border-radius: 5px;
+border-radius: 5px;
+position: absolute;
+top: 0;
+left: 0;
+margin: -4px 0 0 -4px;
+}
+.colorpicker-saturation i b {
+display: block;
+height: 5px;
+width: 5px;
+border: 1px solid #fff;
+-webkit-border-radius: 5px;
+-moz-border-radius: 5px;
+border-radius: 5px;
+}
+.colorpicker-hue, .colorpicker-alpha {
+width: 15px;
+height: 100px;
+float: left;
+cursor: row-resize;
+margin-left: 4px;
+margin-bottom: 4px;
+}
+.colorpicker-hue i, .colorpicker-alpha i {
+display: block;
+height: 1px;
+background: #000;
+border-top: 1px solid #fff;
+position: absolute;
+top: 0;
+left: 0;
+width: 100%;
+margin-top: -1px;
+}
+.colorpicker-hue {
+background-image: url(../img/hue.png);
+}
+.colorpicker-alpha {
+background-image: url(../img/alpha.png);
+display: none;
+}
+.colorpicker {
+*zoom: 1;
+top: 0;
+left: 0;
+padding: 4px;
+min-width: 120px;
+margin-top: 1px;
+-webkit-border-radius: 4px;
+-moz-border-radius: 4px;
+border-radius: 4px;
+}
+.colorpicker:before, .colorpicker:after {
+display: table;
+content: "";
+}
+.colorpicker:after {
+clear: both;
+}
+.colorpicker:before {
+content: '';
+display: inline-block;
+border-left: 7px solid transparent;
+border-right: 7px solid transparent;
+border-bottom: 7px solid #ccc;
+border-bottom-color: rgba(0, 0, 0, 0.2);
+position: absolute;
+top: -7px;
+left: 6px;
+}
+.colorpicker:after {
+content: '';
+display: inline-block;
+border-left: 6px solid transparent;
+border-right: 6px solid transparent;
+border-bottom: 6px solid #ffffff;
+position: absolute;
+top: -6px;
+left: 7px;
+}
+.colorpicker div {
+position: relative;
+}
+.colorpicker.alpha {
+min-width: 140px;
+}
+.colorpicker.alpha .colorpicker-alpha {
+display: block;
+}
+.colorpicker-color {
+height: 10px;
+margin-top: 5px;
+clear: both;
+background-image: url(../img/alpha.png);
+background-position: 0 100%;
+}
+.colorpicker-color div {
+height: 10px;
+}
+.input-append.color .add-on i, .input-prepend.color .add-on i {
+display: block;
+cursor: pointer;
+width: 16px;
+height: 16px;
+} 
\ No newline at end of file
diff --git a/static/vendor/bootstrap-colorpicker/css/colorpicker.css b/static/vendor/bootstrap-colorpicker/css/colorpicker.css
new file mode 100644 (file)
index 0000000..141bb06
--- /dev/null
@@ -0,0 +1,109 @@
+.clearfix {
+  *zoom: 1;
+}
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  content: "";
+}
+.clearfix:after {
+  clear: both;
+}
+.colorpicker-saturation {
+  width: 100px;
+  height: 100px;
+  background-image: url(../img/saturation.png);
+  cursor: crosshair;
+  float: left;
+}
+.colorpicker-saturation i {
+  display: block;
+  height: 5px;
+  width: 5px;
+  border: 1px solid #000;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+  position: absolute;
+  top: 0;
+  left: 0;
+  margin: -6px 0 0 -6px;
+}
+.colorpicker-saturation i b {
+  display: block;
+  height: 5px;
+  width: 5px;
+  border: 1px solid #fff;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+}
+.colorpicker-hue,
+.colorpicker-alpha {
+  width: 15px;
+  height: 100px;
+  float: left;
+  cursor: row-resize;
+  margin-left: 6px;
+}
+.colorpicker-hue i,
+.colorpicker-alpha i {
+  display: block;
+  height: 1px;
+  background: #000;
+  border-top: 1px solid #fff;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  margin-top: -1px;
+}
+.colorpicker-hue {
+  background-image: url(../img/hue.png);
+}
+.colorpicker-alpha {
+  background-image: url(../img/alpha.png);
+  display: none;
+  margin-top: 6px;
+}
+.colorpicker {
+  *zoom: 1;
+  top: 0;
+  left: 0;
+  padding: 6px;
+  min-width: 120px;
+}
+.colorpicker:before,
+.colorpicker:after {
+  display: table;
+  content: "";
+}
+.colorpicker:after {
+  clear: both;
+}
+.colorpicker div {
+  position: relative;
+}
+.colorpicker.alpha {
+  min-width: 140px;
+}
+.colorpicker.alpha .colorpicker-alpha {
+  display: block;
+}
+.colorpicker-color {
+  height: 10px;
+  margin-top: 5px;
+  clear: both;
+  background-image: url(../img/alpha.png);
+  background-position: 0 100%;
+}
+.colorpicker-color div {
+  height: 10px;
+}
+.input-append.color .add-on i,
+.input-prepend.color .add-on i {
+  display: block;
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+}
diff --git a/static/vendor/bootstrap-colorpicker/img/alpha.png b/static/vendor/bootstrap-colorpicker/img/alpha.png
new file mode 100644 (file)
index 0000000..38043f1
Binary files /dev/null and b/static/vendor/bootstrap-colorpicker/img/alpha.png differ
diff --git a/static/vendor/bootstrap-colorpicker/img/hue.png b/static/vendor/bootstrap-colorpicker/img/hue.png
new file mode 100644 (file)
index 0000000..d89560e
Binary files /dev/null and b/static/vendor/bootstrap-colorpicker/img/hue.png differ
diff --git a/static/vendor/bootstrap-colorpicker/img/saturation.png b/static/vendor/bootstrap-colorpicker/img/saturation.png
new file mode 100644 (file)
index 0000000..594ae50
Binary files /dev/null and b/static/vendor/bootstrap-colorpicker/img/saturation.png differ
diff --git a/static/vendor/bootstrap-colorpicker/js/bootstrap-colorpicker.js b/static/vendor/bootstrap-colorpicker/js/bootstrap-colorpicker.js
new file mode 100644 (file)
index 0000000..093f25a
--- /dev/null
@@ -0,0 +1,520 @@
+/* =========================================================
+ * bootstrap-colorpicker.js 
+ * http://www.eyecon.ro/bootstrap-colorpicker
+ * =========================================================
+ * Copyright 2012 Stefan Petre
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+!function( $ ) {
+       
+       // Color object
+       
+       var Color = function(val) {
+               this.value = {
+                       h: 1,
+                       s: 1,
+                       b: 1,
+                       a: 1
+               };
+               this.setColor(val);
+       };
+       
+       Color.prototype = {
+               constructor: Color,
+               
+               //parse a string to HSB
+               setColor: function(val){
+                       val = val.toLowerCase();
+                       var that = this;
+                       $.each( CPGlobal.stringParsers, function( i, parser ) {
+                               var match = parser.re.exec( val ),
+                                       values = match && parser.parse( match ),
+                                       space = parser.space||'rgba';
+                               if ( values ) {
+                                       if (space == 'hsla') {
+                                               that.value = CPGlobal.RGBtoHSB.apply(null, CPGlobal.HSLtoRGB.apply(null, values));
+                                       } else {
+                                               that.value = CPGlobal.RGBtoHSB.apply(null, values);
+                                       }
+                                       return false;
+                               }
+                       });
+               },
+               
+               setHue: function(h) {
+                       this.value.h = 1- h;
+               },
+               
+               setSaturation: function(s) {
+                       this.value.s = s;
+               },
+               
+               setLightness: function(b) {
+                       this.value.b = 1- b;
+               },
+               
+               setAlpha: function(a) {
+                       this.value.a = parseInt((1 - a)*100, 10)/100;
+               },
+               
+               // HSBtoRGB from RaphaelJS
+               // https://github.com/DmitryBaranovskiy/raphael/
+               toRGB: function(h, s, b, a) {
+                       if (!h) {
+                               h = this.value.h;
+                               s = this.value.s;
+                               b = this.value.b;
+                       }
+                       h *= 360;
+                       var R, G, B, X, C;
+                       h = (h % 360) / 60;
+                       C = b * s;
+                       X = C * (1 - Math.abs(h % 2 - 1));
+                       R = G = B = b - C;
+
+                       h = ~~h;
+                       R += [C, X, 0, 0, X, C][h];
+                       G += [X, C, C, X, 0, 0][h];
+                       B += [0, 0, X, C, C, X][h];
+                       return {
+                               r: Math.round(R*255),
+                               g: Math.round(G*255),
+                               b: Math.round(B*255),
+                               a: a||this.value.a
+                       };
+               },
+               
+               toHex: function(h, s, b, a){
+                       var rgb = this.toRGB(h, s, b, a);
+                       return '#'+((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1);
+               },
+               
+               toHSL: function(h, s, b, a){
+                       if (!h) {
+                               h = this.value.h;
+                               s = this.value.s;
+                               b = this.value.b;
+                       }
+                       var H = h,
+                               L = (2 - s) * b,
+                               S = s * b;
+                       if (L > 0 && L <= 1) {
+                               S /= L;
+                       } else {
+                               S /= 2 - L;
+                       }
+                       L /= 2;
+                       if (S > 1) {
+                               S = 1;
+                       }
+                       return {
+                               h: H,
+                               s: S,
+                               l: L,
+                               a: a||this.value.a
+                       };
+               }
+       };
+       
+       // Picker object
+       
+       var Colorpicker = function(element, options){
+               this.element = $(element);
+               var format = options.format||this.element.data('color-format')||'hex';
+               this.format = CPGlobal.translateFormats[format];
+               this.isInput = this.element.is('input');
+               this.component = this.element.is('.color') ? this.element.find('.add-on') : false;
+               
+               this.picker = $(CPGlobal.template)
+                                                       .appendTo('body')
+                                                       .on('mousedown', $.proxy(this.mousedown, this));
+               
+               if (this.isInput) {
+                       this.element.on({
+                               'focus': $.proxy(this.show, this),
+                               'keyup': $.proxy(this.update, this)
+                       });
+               } else if (this.component){
+                       this.component.on({
+                               'click': $.proxy(this.show, this)
+                       });
+               } else {
+                       this.element.on({
+                               'click': $.proxy(this.show, this)
+                       });
+               }
+               if (format == 'rgba' || format == 'hsla') {
+                       this.picker.addClass('alpha');
+                       this.alpha = this.picker.find('.colorpicker-alpha')[0].style;
+               }
+               
+               if (this.component){
+                       this.picker.find('.colorpicker-color').hide();
+                       this.preview = this.element.find('i')[0].style;
+               } else {
+                       this.preview = this.picker.find('div:last')[0].style;
+               }
+               
+               this.base = this.picker.find('div:first')[0].style;
+               this.update();
+       };
+       
+       Colorpicker.prototype = {
+               constructor: Colorpicker,
+               
+               show: function(e) {
+                       this.picker.show();
+                       this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
+                       this.place();
+                       $(window).on('resize', $.proxy(this.place, this));
+                       if (!this.isInput) {
+                               if (e) {
+                                       e.stopPropagation();
+                                       e.preventDefault();
+                               }
+                       }
+                       $(document).on({
+                               'mousedown': $.proxy(this.hide, this)
+                       });
+                       this.element.trigger({
+                               type: 'show',
+                               color: this.color
+                       });
+               },
+               
+               update: function(){
+                       this.color = new Color(this.isInput ? this.element.prop('value') : this.element.data('color'));
+                       this.picker.find('i')
+                               .eq(0).css({left: this.color.value.s*100, top: 100 - this.color.value.b*100}).end()
+                               .eq(1).css('top', 100 * (1 - this.color.value.h)).end()
+                               .eq(2).css('top', 100 * (1 - this.color.value.a));
+                       this.previewColor();
+               },
+               
+               hide: function(){
+                       this.picker.hide();
+                       $(window).off('resize', this.place);
+                       if (!this.isInput) {
+                               $(document).off({
+                                       'mousedown': this.hide
+                               });
+                               if (this.component){
+                                       this.element.find('input').prop('value', this.format.call(this));
+                               }
+                               this.element.data('color', this.format.call(this));
+                       } else {
+                               this.element.prop('value', this.format.call(this));
+                       }
+                       this.element.trigger({
+                               type: 'hide',
+                               color: this.color
+                       });
+               },
+               
+               place: function(){
+                       var offset = this.component ? this.component.offset() : this.element.offset();
+                       this.picker.css({
+                               top: offset.top + this.height,
+                               left: offset.left
+                       });
+               },
+               
+               //preview color change
+               previewColor: function(){
+                       this.preview.backgroundColor = this.format.call(this);
+                       //set the color for brightness/saturation slider
+                       this.base.backgroundColor = this.color.toHex(this.color.value.h, 1, 1, 1);
+                       //set te color for alpha slider
+                       if (this.alpha) {
+                               this.alpha.backgroundColor = this.color.toHex();
+                       }
+               },
+               
+               pointer: null,
+               
+               slider: null,
+               
+               mousedown: function(e){
+                       e.stopPropagation();
+                       e.preventDefault();
+                       
+                       var target = $(e.target);
+                       
+                       //detect the slider and set the limits and callbacks
+                       var zone = target.closest('div');
+                       if (!zone.is('.colorpicker')) {
+                               if (zone.is('.colorpicker-saturation')) {
+                                       this.slider = $.extend({}, CPGlobal.sliders['saturation']);
+                               } 
+                               else if (zone.is('.colorpicker-hue')) {
+                                       this.slider = $.extend({}, CPGlobal.sliders['hue']);
+                               }
+                               else if (zone.is('.colorpicker-alpha')) {
+                                       this.slider = $.extend({}, CPGlobal.sliders['alpha']);
+                               }
+                               var offset = zone.offset();
+                               //reference to knob's style
+                               this.slider.knob = zone.find('i')[0].style;
+                               this.slider.left = e.pageX - offset.left;
+                               this.slider.top = e.pageY - offset.top;
+                               this.pointer = {
+                                       left: e.pageX,
+                                       top: e.pageY
+                               };
+                               //trigger mousemove to move the knob to the current position
+                               $(document).on({
+                                       mousemove: $.proxy(this.mousemove, this),
+                                       mouseup: $.proxy(this.mouseup, this)
+                               }).trigger('mousemove');
+                       }
+                       return false;
+               },
+               
+               mousemove: function(e){
+                       e.stopPropagation();
+                       e.preventDefault();
+                       var left = Math.max(
+                               0,
+                               Math.min(
+                                       this.slider.maxLeft,
+                                       this.slider.left + ((e.pageX||this.pointer.left) - this.pointer.left)
+                               )
+                       );
+                       var top = Math.max(
+                               0,
+                               Math.min(
+                                       this.slider.maxTop,
+                                       this.slider.top + ((e.pageY||this.pointer.top) - this.pointer.top)
+                               )
+                       );
+                       this.slider.knob.left = left + 'px';
+                       this.slider.knob.top = top + 'px';
+                       if (this.slider.callLeft) {
+                               this.color[this.slider.callLeft].call(this.color, left/100);
+                       }
+                       if (this.slider.callTop) {
+                               this.color[this.slider.callTop].call(this.color, top/100);
+                       }
+                       this.previewColor();
+                       this.element.trigger({
+                               type: 'changeColor',
+                               color: this.color
+                       });
+                       return false;
+               },
+               
+               mouseup: function(e){
+                       e.stopPropagation();
+                       e.preventDefault();
+                       $(document).off({
+                               mousemove: this.mousemove,
+                               mouseup: this.mouseup
+                       });
+                       return false;
+               }
+       }
+
+       $.fn.colorpicker = function ( option ) {
+               return this.each(function () {
+                       var $this = $(this),
+                               data = $this.data('colorpicker'),
+                               options = typeof option == 'object' && option;
+                       if (!data) {
+                               $this.data('colorpicker', (data = new Colorpicker(this, $.extend({}, $.fn.colorpicker.defaults, options))));
+                       }
+                       if (typeof option == 'string') data[option]();
+               });
+       };
+
+       $.fn.colorpicker.defaults = {
+       };
+       
+       $.fn.colorpicker.Constructor = Colorpicker;
+       
+       var CPGlobal = {
+       
+               // translate a format from Color object to a string
+               translateFormats: {
+                       'rgb': function(){
+                               var rgb = this.color.toRGB();
+                               return 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')';
+                       },
+                       
+                       'rgba': function(){
+                               var rgb = this.color.toRGB();
+                               return 'rgba('+rgb.r+','+rgb.g+','+rgb.b+','+rgb.a+')';
+                       },
+                       
+                       'hsl': function(){
+                               var hsl = this.color.toHSL();
+                               return 'hsl('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%)';
+                       },
+                       
+                       'hsla': function(){
+                               var hsl = this.color.toHSL();
+                               return 'hsla('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%,'+hsl.a+')';
+                       },
+                       
+                       'hex': function(){
+                               return  this.color.toHex();
+                       }
+               },
+               
+               sliders: {
+                       saturation: {
+                               maxLeft: 100,
+                               maxTop: 100,
+                               callLeft: 'setSaturation',
+                               callTop: 'setLightness'
+                       },
+                       
+                       hue: {
+                               maxLeft: 0,
+                               maxTop: 100,
+                               callLeft: false,
+                               callTop: 'setHue'
+                       },
+                       
+                       alpha: {
+                               maxLeft: 0,
+                               maxTop: 100,
+                               callLeft: false,
+                               callTop: 'setAlpha'
+                       }
+               },
+               
+               // HSBtoRGB from RaphaelJS
+               // https://github.com/DmitryBaranovskiy/raphael/
+               RGBtoHSB: function (r, g, b, a){
+                       r /= 255;
+                       g /= 255;
+                       b /= 255;
+
+                       var H, S, V, C;
+                       V = Math.max(r, g, b);
+                       C = V - Math.min(r, g, b);
+                       H = (C == 0 ? null :
+                                V == r ? (g - b) / C :
+                                V == g ? (b - r) / C + 2 :
+                                                 (r - g) / C + 4
+                               );
+                       H = ((H + 360) % 6) * 60 / 360;
+                       S = C == 0 ? 0 : C / V;
+                       return {h: H||1, s: S, b: V, a: a||1};
+               },
+               
+               HueToRGB: function (p, q, h) {
+                       if (h < 0)
+                               h += 1;
+                       else if (h > 1)
+                               h -= 1;
+
+                       if ((h * 6) < 1)
+                               return p + (q - p) * h * 6;
+                       else if ((h * 2) < 1)
+                               return q;
+                       else if ((h * 3) < 2)
+                               return p + (q - p) * ((2 / 3) - h) * 6;
+                       else
+                               return p;
+               },
+       
+               HSLtoRGB: function (h, s, l, a)
+               {
+
+                       if (s < 0)
+                               s = 0;
+
+                       if (l <= 0.5)
+                               var q = l * (1 + s);
+                       else
+                               var q = l + s - (l * s);
+
+                       var p = 2 * l - q;
+
+                       var tr = h + (1 / 3);
+                       var tg = h;
+                       var tb = h - (1 / 3);
+
+                       var r = Math.round(CPGlobal.HueToRGB(p, q, tr) * 255);
+                       var g = Math.round(CPGlobal.HueToRGB(p, q, tg) * 255);
+                       var b = Math.round(CPGlobal.HueToRGB(p, q, tb) * 255);
+                       return [r, g, b, a||1];
+               },
+               
+               // a set of RE's that can match strings and generate color tuples.
+               // from John Resig color plugin
+               // https://github.com/jquery/jquery-color/
+               stringParsers: [
+                       {
+                               re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+                               parse: function( execResult ) {
+                                       return [
+                                               execResult[ 1 ],
+                                               execResult[ 2 ],
+                                               execResult[ 3 ],
+                                               execResult[ 4 ]
+                                       ];
+                               }
+                       }, {
+                               re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+                               parse: function( execResult ) {
+                                       return [
+                                               2.55 * execResult[1],
+                                               2.55 * execResult[2],
+                                               2.55 * execResult[3],
+                                               execResult[ 4 ]
+                                       ];
+                               }
+                       }, {
+                               re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
+                               parse: function( execResult ) {
+                                       return [
+                                               parseInt( execResult[ 1 ], 16 ),
+                                               parseInt( execResult[ 2 ], 16 ),
+                                               parseInt( execResult[ 3 ], 16 )
+                                       ];
+                               }
+                       }, {
+                               re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
+                               parse: function( execResult ) {
+                                       return [
+                                               parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
+                                               parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
+                                               parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
+                                       ];
+                               }
+                       }, {
+                               re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+                               space: 'hsla',
+                               parse: function( execResult ) {
+                                       return [
+                                               execResult[1]/360,
+                                               execResult[2] / 100,
+                                               execResult[3] / 100,
+                                               execResult[4]
+                                       ];
+                               }
+                       }
+               ],
+               template: '<div class="colorpicker dropdown-menu">'+
+                                                       '<div class="colorpicker-saturation"><i><b></b></i></div>'+
+                                                       '<div class="colorpicker-hue"><i></i></div>'+
+                                                       '<div class="colorpicker-alpha"><i></i></div>'+
+                                                       '<div class="colorpicker-color"><div /></div>'+
+                                               '</div>'
+       };
+
+}( window.jQuery )
\ No newline at end of file
diff --git a/static/vendor/bootstrap-colorpicker/less/colorpicker.less b/static/vendor/bootstrap-colorpicker/less/colorpicker.less
new file mode 100644 (file)
index 0000000..ebef70a
--- /dev/null
@@ -0,0 +1,128 @@
+
+// VARIABLES
+// --------------------------------------------------
+
+@spacing: 6px;
+
+
+
+
+// UTILITY MIXINS
+// --------------------------------------------------
+
+
+// Border Radius
+.border-radius(@radius: 5px) {
+  -webkit-border-radius: @radius;
+     -moz-border-radius: @radius;
+          border-radius: @radius;
+}
+
+// Clearfix
+// --------
+// For clearing floats like a boss h5bp.com/q
+.clearfix {
+  *zoom: 1;
+  &:before,
+  &:after {
+    display: table;
+    content: "";
+  }
+  &:after {
+    clear: both;
+  }
+}
+
+
+// COLORPICKER STYLES
+// --------------------------------------------------
+
+.colorpicker-saturation {
+       width: 100px;
+       height: 100px;
+       background-image: url(../img/saturation.png);
+       cursor: crosshair;
+       float: left;
+       i {
+               display: block;
+               height: 5px;
+               width: 5px;
+               border: 1px solid #000;
+               .border-radius();
+               position: absolute;
+               top: 0;
+               left: 0;
+               margin: -@spacing 0 0 -@spacing;
+               b {
+                       display: block;
+                       height: 5px;
+                       width: 5px;
+                       border: 1px solid #fff;
+                       .border-radius();
+               }
+       }
+}
+.colorpicker-hue,
+.colorpicker-alpha {
+       width: 15px;
+       height: 100px;
+       float: left;
+       cursor: row-resize;
+       margin-left: @spacing;
+       i {
+               display: block;
+               height: 1px;
+               background: #000;
+               border-top: 1px solid #fff;
+               position: absolute;
+               top: 0;
+               left: 0;
+               width: 100%;
+               margin-top: -1px;
+       }
+}
+.colorpicker-hue {
+       background-image: url(../img/hue.png);
+}
+.colorpicker-alpha {
+       background-image: url(../img/alpha.png);
+       display:none;
+       margin-top: @spacing;
+}
+.colorpicker {
+       .clearfix();
+       top: 0;
+       left: 0;
+       padding: @spacing;
+       min-width: 120px;
+       div {
+               position: relative;
+       }
+       &.alpha {
+               min-width: 140px;
+               .colorpicker-alpha {
+                       display: block;
+               }
+       }
+}
+.colorpicker-color {
+       height: 10px;
+       margin-top: 5px;
+       clear: both;
+       background-image: url(../img/alpha.png);
+       background-position: 0 100%;
+       div {
+               height: 10px;
+       }
+}
+.input-append,
+.input-prepend {
+       &.color {
+               .add-on i {
+                       display: block;
+                       cursor: pointer;
+                       width: 16px;
+                       height: 16px;
+               }
+       }
+}
\ No newline at end of file
diff --git a/static/vendor/bootstrap-datepicker.js b/static/vendor/bootstrap-datepicker.js
new file mode 120000 (symlink)
index 0000000..e087bfc
--- /dev/null
@@ -0,0 +1 @@
+bootstrap-datepicker/js/bootstrap-datepicker.js
\ No newline at end of file
diff --git a/static/vendor/bootstrap-datepicker/css/datepicker.css b/static/vendor/bootstrap-datepicker/css/datepicker.css
new file mode 100644 (file)
index 0000000..f1f3d57
--- /dev/null
@@ -0,0 +1,156 @@
+/*!
+* Datepicker for Bootstrap
+*
+* Copyright 2012 Stefan Petre
+* Licensed under the Apache License v2.0
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+*/
+.datepicker {
+top: 0;
+left: 0;
+padding: 4px;
+margin-top: 1px;
+-webkit-border-radius: 4px;
+-moz-border-radius: 4px;
+border-radius: 4px;
+/*.dow {
+border-top: 1px solid #ddd !important;
+}*/
+}
+.datepicker:before {
+content: '';
+display: inline-block;
+border-left: 7px solid transparent;
+border-right: 7px solid transparent;
+border-bottom: 7px solid #ccc;
+border-bottom-color: rgba(0, 0, 0, 0.2);
+position: absolute;
+top: -7px;
+left: 6px;
+}
+.datepicker:after {
+content: '';
+display: inline-block;
+border-left: 6px solid transparent;
+border-right: 6px solid transparent;
+border-bottom: 6px solid #ffffff;
+position: absolute;
+top: -6px;
+left: 7px;
+}
+.datepicker > div {
+display: none;
+}
+.datepicker table {
+width: 100%;
+margin: 0;
+}
+.datepicker td, .datepicker th {
+text-align: center;
+width: 20px;
+height: 20px;
+-webkit-border-radius: 4px;
+-moz-border-radius: 4px;
+border-radius: 4px;
+}
+.datepicker td.day:hover {
+background: #eeeeee;
+cursor: pointer;
+}
+.datepicker td.old, .datepicker td.new {
+color: #999999;
+}
+.datepicker td.active, .datepicker td.active:hover {
+background-color: #006dcc;
+background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
+background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+background-image: linear-gradient(top, #0088cc, #0044cc);
+background-repeat: repeat-x;
+filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
+border-color: #0044cc #0044cc #002a80;
+border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+color: #fff;
+text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.datepicker td.active:hover,
+.datepicker td.active:hover:hover,
+.datepicker td.active:active,
+.datepicker td.active:hover:active,
+.datepicker td.active.active,
+.datepicker td.active:hover.active,
+.datepicker td.active.disabled,
+.datepicker td.active:hover.disabled,
+.datepicker td.active[disabled],
+.datepicker td.active:hover[disabled] {
+background-color: #0044cc;
+}
+.datepicker td.active:active,
+.datepicker td.active:hover:active,
+.datepicker td.active.active,
+.datepicker td.active:hover.active {
+background-color: #003399 \9;
+}
+.datepicker td span {
+display: block;
+width: 47px;
+height: 54px;
+line-height: 54px;
+float: left;
+margin: 2px;
+cursor: pointer;
+-webkit-border-radius: 4px;
+-moz-border-radius: 4px;
+border-radius: 4px;
+}
+.datepicker td span:hover {
+background: #eeeeee;
+}
+.datepicker td span.active {
+background-color: #006dcc;
+background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
+background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+background-image: linear-gradient(top, #0088cc, #0044cc);
+background-repeat: repeat-x;
+filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
+border-color: #0044cc #0044cc #002a80;
+border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+color: #fff;
+text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.datepicker td span.active:hover,
+.datepicker td span.active:active,
+.datepicker td span.active.active,
+.datepicker td span.active.disabled,
+.datepicker td span.active[disabled] {
+background-color: #0044cc;
+}
+.datepicker td span.active:active, .datepicker td span.active.active {
+background-color: #003399 \9;
+}
+.datepicker td span.old {
+color: #999999;
+}
+.datepicker th.switch {
+width: 145px;
+}
+.datepicker thead tr:first-child th {
+cursor: pointer;
+}
+.datepicker thead tr:first-child th:hover {
+background: #eeeeee;
+}
+.input-append.date .add-on i, .input-prepend.date .add-on i {
+display: block;
+cursor: pointer;
+width: 16px;
+height: 16px;
+}
\ No newline at end of file
diff --git a/static/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js b/static/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js
new file mode 100644 (file)
index 0000000..c3630ea
--- /dev/null
@@ -0,0 +1,401 @@
+/* =========================================================
+ * bootstrap-datepicker.js 
+ * http://www.eyecon.ro/bootstrap-datepicker
+ * =========================================================
+ * Copyright 2012 Stefan Petre
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+!function( $ ) {
+       
+       // Picker object
+       
+       var Datepicker = function(element, options){
+               this.element = $(element);
+               this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
+               this.picker = $(DPGlobal.template)
+                                                       .appendTo('body')
+                                                       .on({
+                                                               click: $.proxy(this.click, this),
+                                                               mousedown: $.proxy(this.mousedown, this)
+                                                       });
+               this.isInput = this.element.is('input');
+               this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
+               
+               if (this.isInput) {
+                       this.element.on({
+                               focus: $.proxy(this.show, this),
+                               blur: $.proxy(this.hide, this),
+                               keyup: $.proxy(this.update, this)
+                       });
+               } else {
+                       if (this.component){
+                               this.component.on('click', $.proxy(this.show, this));
+                       } else {
+                               this.element.on('click', $.proxy(this.show, this));
+                       }
+               }
+               
+               this.viewMode = 0;
+               this.weekStart = options.weekStart||this.element.data('date-weekstart')||0;
+               this.weekEnd = this.weekStart == 0 ? 6 : this.weekStart - 1;
+               this.fillDow();
+               this.fillMonths();
+               this.update();
+               this.showMode();
+       };
+       
+       Datepicker.prototype = {
+               constructor: Datepicker,
+               
+               show: function(e) {
+                       this.picker.show();
+                       this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
+                       this.place();
+                       $(window).on('resize', $.proxy(this.place, this));
+                       if (e ) {
+                               e.stopPropagation();
+                               e.preventDefault();
+                       }
+                       if (!this.isInput) {
+                               $(document).on('mousedown', $.proxy(this.hide, this));
+                       }
+                       this.element.trigger({
+                               type: 'show',
+                               date: this.date
+                       });
+               },
+               
+               hide: function(){
+                       this.picker.hide();
+                       $(window).off('resize', this.place);
+                       this.viewMode = 0;
+                       this.showMode();
+                       if (!this.isInput) {
+                               $(document).off('mousedown', this.hide);
+                       }
+                       this.setValue();
+                       this.element.trigger({
+                               type: 'hide',
+                               date: this.date
+                       });
+               },
+               
+               setValue: function() {
+                       var formated = DPGlobal.formatDate(this.date, this.format);
+                       if (!this.isInput) {
+                               if (this.component){
+                                       this.element.find('input').prop('value', formated);
+                               }
+                               this.element.data('date', formated);
+                       } else {
+                               this.element.prop('value', formated);
+                       }
+               },
+               
+               place: function(){
+                       var offset = this.component ? this.component.offset() : this.element.offset();
+                       this.picker.css({
+                               top: offset.top + this.height,
+                               left: offset.left
+                       });
+               },
+               
+               update: function(){
+                       this.date = DPGlobal.parseDate(
+                               this.isInput ? this.element.prop('value') : this.element.data('date'),
+                               this.format
+                       );
+                       this.viewDate = new Date(this.date);
+                       this.fill();
+               },
+               
+               fillDow: function(){
+                       var dowCnt = this.weekStart;
+                       var html = '<tr>';
+                       while (dowCnt < this.weekStart + 7) {
+                               html += '<th class="dow">'+DPGlobal.dates.daysMin[(dowCnt++)%7]+'</th>';
+                       }
+                       html += '</tr>';
+                       this.picker.find('.datepicker-days thead').append(html);
+               },
+               
+               fillMonths: function(){
+                       var html = '';
+                       var i = 0
+                       while (i < 12) {
+                               html += '<span class="month">'+DPGlobal.dates.monthsShort[i++]+'</span>';
+                       }
+                       this.picker.find('.datepicker-months td').append(html);
+               },
+               
+               fill: function() {
+                       var d = new Date(this.viewDate),
+                               year = d.getFullYear(),
+                               month = d.getMonth(),
+                               currentDate = this.date.valueOf();
+                       this.picker.find('.datepicker-days th:eq(1)')
+                                               .text(DPGlobal.dates.months[month]+' '+year);
+                       var prevMonth = new Date(year, month-1, 28,0,0,0,0),
+                               day = DPGlobal.getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());
+                       prevMonth.setDate(day);
+                       prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7)%7);
+                       var nextMonth = new Date(prevMonth);
+                       nextMonth.setDate(nextMonth.getDate() + 42);
+                       nextMonth = nextMonth.valueOf();
+                       html = [];
+                       var clsName;
+                       while(prevMonth.valueOf() < nextMonth) {
+                               if (prevMonth.getDay() == this.weekStart) {
+                                       html.push('<tr>');
+                               }
+                               clsName = '';
+                               if (prevMonth.getMonth() < month) {
+                                       clsName += ' old';
+                               } else if (prevMonth.getMonth() > month) {
+                                       clsName += ' new';
+                               }
+                               if (prevMonth.valueOf() == currentDate) {
+                                       clsName += ' active';
+                               }
+                               html.push('<td class="day'+clsName+'">'+prevMonth.getDate() + '</td>');
+                               if (prevMonth.getDay() == this.weekEnd) {
+                                       html.push('</tr>');
+                               }
+                               prevMonth.setDate(prevMonth.getDate()+1);
+                       }
+                       this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
+                       var currentYear = this.date.getFullYear();
+                       
+                       var months = this.picker.find('.datepicker-months')
+                                               .find('th:eq(1)')
+                                                       .text(year)
+                                                       .end()
+                                               .find('span').removeClass('active');
+                       if (currentYear == year) {
+                               months.eq(this.date.getMonth()).addClass('active');
+                       }
+                       
+                       html = '';
+                       year = parseInt(year/10, 10) * 10;
+                       var yearCont = this.picker.find('.datepicker-years')
+                                                               .find('th:eq(1)')
+                                                                       .text(year + '-' + (year + 9))
+                                                                       .end()
+                                                               .find('td');
+                       year -= 1;
+                       for (var i = -1; i < 11; i++) {
+                               html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+'">'+year+'</span>';
+                               year += 1;
+                       }
+                       yearCont.html(html);
+               },
+               
+               click: function(e) {
+                       e.stopPropagation();
+                       e.preventDefault();
+                       var target = $(e.target).closest('span, td, th');
+                       if (target.length == 1) {
+                               switch(target[0].nodeName.toLowerCase()) {
+                                       case 'th':
+                                               switch(target[0].className) {
+                                                       case 'switch':
+                                                               this.showMode(1);
+                                                               break;
+                                                       case 'prev':
+                                                       case 'next':
+                                                               this.viewDate['set'+DPGlobal.modes[this.viewMode].navFnc].call(
+                                                                       this.viewDate,
+                                                                       this.viewDate['get'+DPGlobal.modes[this.viewMode].navFnc].call(this.viewDate) + 
+                                                                       DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1)
+                                                               );
+                                                               this.fill();
+                                                               break;
+                                               }
+                                               break;
+                                       case 'span':
+                                               if (target.is('.month')) {
+                                                       var month = target.parent().find('span').index(target);
+                                                       this.viewDate.setMonth(month);
+                                               } else {
+                                                       var year = parseInt(target.text(), 10)||0;
+                                                       this.viewDate.setFullYear(year);
+                                               }
+                                               this.showMode(-1);
+                                               this.fill();
+                                               break;
+                                       case 'td':
+                                               if (target.is('.day')){
+                                                       var day = parseInt(target.text(), 10)||1;
+                                                       var month = this.viewDate.getMonth();
+                                                       if (target.is('.old')) {
+                                                               month -= 1;
+                                                       } else if (target.is('.new')) {
+                                                               month += 1;
+                                                       }
+                                                       var year = this.viewDate.getFullYear();
+                                                       this.date = new Date(year, month, day,0,0,0,0);
+                                                       this.viewDate = new Date(year, month, day,0,0,0,0);
+                                                       this.fill();
+                                                       this.setValue();
+                                                       this.element.trigger({
+                                                               type: 'changeDate',
+                                                               date: this.date
+                                                       });
+                                               }
+                                               break;
+                               }
+                       }
+               },
+               
+               mousedown: function(e){
+                       e.stopPropagation();
+                       e.preventDefault();
+               },
+               
+               showMode: function(dir) {
+                       if (dir) {
+                               this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
+                       }
+                       this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
+               }
+       };
+       
+       $.fn.datepicker = function ( option ) {
+               return this.each(function () {
+                       var $this = $(this),
+                               data = $this.data('datepicker'),
+                               options = typeof option == 'object' && option;
+                       if (!data) {
+                               $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
+                       }
+                       if (typeof option == 'string') data[option]();
+               });
+       };
+
+       $.fn.datepicker.defaults = {
+       };
+       $.fn.datepicker.Constructor = Datepicker;
+       
+       var DPGlobal = {
+               modes: [
+                       {
+                               clsName: 'days',
+                               navFnc: 'Month',
+                               navStep: 1
+                       },
+                       {
+                               clsName: 'months',
+                               navFnc: 'FullYear',
+                               navStep: 1
+                       },
+                       {
+                               clsName: 'years',
+                               navFnc: 'FullYear',
+                               navStep: 10
+               }],
+               dates:{
+                       days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
+                       daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+                       daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
+                       months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+                       monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+               },
+               isLeapYear: function (year) {
+                       return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
+               },
+               getDaysInMonth: function (year, month) {
+                       return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
+               },
+               parseFormat: function(format){
+                       var separator = format.match(/[.\/-].*?/),
+                               parts = format.split(/\W+/);
+                       if (!separator || !parts || parts.length == 0){
+                               throw new Error("Invalid date format.");
+                       }
+                       return {separator: separator, parts: parts};
+               },
+               parseDate: function(date, format) {
+                       var parts = date.split(format.separator),
+                               date = new Date(1970, 1, 1, 0, 0, 0),
+                               val;
+                       if (parts.length == format.parts.length) {
+                               for (var i=0, cnt = format.parts.length; i < cnt; i++) {
+                                       val = parseInt(parts[i], 10)||1;
+                                       switch(format.parts[i]) {
+                                               case 'dd':
+                                               case 'd':
+                                                       date.setDate(val);
+                                                       break;
+                                               case 'mm':
+                                               case 'm':
+                                                       date.setMonth(val - 1);
+                                                       break;
+                                               case 'yy':
+                                                       date.setFullYear(2000 + val);
+                                                       break;
+                                               case 'yyyy':
+                                                       date.setFullYear(val);
+                                                       break;
+                                       }
+                               }
+                       }
+                       return date;
+               },
+               formatDate: function(date, format){
+                       var val = {
+                               d: date.getDate(),
+                               m: date.getMonth() + 1,
+                               yy: date.getFullYear().toString().substring(2),
+                               yyyy: date.getFullYear()
+                       };
+                       val.dd = (val.d < 10 ? '0' : '') + val.d;
+                       val.mm = (val.m < 10 ? '0' : '') + val.m;
+                       var date = [];
+                       for (var i=0, cnt = format.parts.length; i < cnt; i++) {
+                               date.push(val[format.parts[i]]);
+                       }
+                       return date.join(format.separator);
+               },
+               headTemplate: '<thead>'+
+                                                       '<tr>'+
+                                                               '<th class="prev"><i class="icon-arrow-left"/></th>'+
+                                                               '<th colspan="5" class="switch"></th>'+
+                                                               '<th class="next"><i class="icon-arrow-right"/></th>'+
+                                                       '</tr>'+
+                                               '</thead>',
+               contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
+       };
+       DPGlobal.template = '<div class="datepicker dropdown-menu">'+
+                                                       '<div class="datepicker-days">'+
+                                                               '<table class=" table-condensed">'+
+                                                                       DPGlobal.headTemplate+
+                                                                       '<tbody></tbody>'+
+                                                               '</table>'+
+                                                       '</div>'+
+                                                       '<div class="datepicker-months">'+
+                                                               '<table class="table-condensed">'+
+                                                                       DPGlobal.headTemplate+
+                                                                       DPGlobal.contTemplate+
+                                                               '</table>'+
+                                                       '</div>'+
+                                                       '<div class="datepicker-years">'+
+                                                               '<table class="table-condensed">'+
+                                                                       DPGlobal.headTemplate+
+                                                                       DPGlobal.contTemplate+
+                                                               '</table>'+
+                                                       '</div>'+
+                                               '</div>';
+
+}( window.jQuery )
\ No newline at end of file
diff --git a/static/vendor/bootstrap-datepicker/less/datepicker.less b/static/vendor/bootstrap-datepicker/less/datepicker.less
new file mode 100644 (file)
index 0000000..1e8cd3f
--- /dev/null
@@ -0,0 +1,122 @@
+/*!
+ * Datepicker for Bootstrap
+ *
+ * Copyright 2012 Stefan Petre
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+.datepicker {
+       top: 0;
+       left: 0;
+       padding: 4px;
+       margin-top: 1px;
+       .border-radius(4px);
+       &:before {
+               content: '';
+               display: inline-block;
+               border-left:   7px solid transparent;
+               border-right:  7px solid transparent;
+               border-bottom: 7px solid #ccc;
+               border-bottom-color: rgba(0,0,0,.2);
+               position: absolute;
+               top: -7px;
+               left: 6px;
+       }
+       &:after {
+               content: '';
+               display: inline-block;
+               border-left:   6px solid transparent;
+               border-right:  6px solid transparent;
+               border-bottom: 6px solid @white;
+               position: absolute;
+               top: -6px;
+               left: 7px;
+       }
+       >div {
+               display: none;
+       }
+       &.days div.datepicker-days {
+               display: block;
+       }
+       &.months div.datepicker-months {
+               display: block;
+       }
+       &.years div.datepicker-years {
+               display: block;
+       }
+       table{
+               width: 100%;
+               margin: 0;
+       }
+       td,
+       th{
+               text-align: center;
+               width: 20px;
+               height: 20px;
+               .border-radius(4px);
+       }
+       td {
+               &.day:hover {
+                       background: @grayLighter;
+                       cursor: pointer;
+               }
+               &.old,
+               &.new {
+                       color: @grayLight;
+               }
+               &.active,
+               &.active:hover {
+                       .buttonBackground(@primaryButtonBackground, spin(@primaryButtonBackground, 20));
+                       color: #fff;
+                       text-shadow: 0 -1px 0 rgba(0,0,0,.25);
+               }
+               span {
+                       display: block;
+                       width: 47px;
+                       height: 54px;
+                       line-height: 54px;
+                       float: left;
+                       margin: 2px;
+                       cursor: pointer;
+                       .border-radius(4px);
+                       &:hover {
+                               background: @grayLighter;
+                       }
+                       &.active {
+                               .buttonBackground(@primaryButtonBackground, spin(@primaryButtonBackground, 20));
+                               color: #fff;
+                               text-shadow: 0 -1px 0 rgba(0,0,0,.25);
+                       }
+                       &.old {
+                               color: @grayLight;
+                       }
+               }
+       }
+       
+       th.switch {
+               width: 145px;
+       }
+       
+       thead tr:first-child th {
+               cursor: pointer;
+               &:hover{
+                       background: @grayLighter;
+               }
+       }
+       /*.dow {
+               border-top: 1px solid #ddd !important;
+       }*/
+}
+.input-append,
+.input-prepend {
+       &.date {
+               .add-on i {
+                       display: block;
+                       cursor: pointer;
+                       width: 16px;
+                       height: 16px;
+               }
+       }
+}
\ No newline at end of file