Permalink
Browse files

Add popovers to allow elements to be edited and deleted. Implement de…

…letion.
  • Loading branch information...
1 parent 6893c76 commit 4cdf1a5c0c9660d70485b2ffebc581b16bc5fe71 Karthik Viswanathan committed Jul 12, 2012
Showing with 848 additions and 104 deletions.
  1. +1 −0 .jshintignore
  2. +2 −2 lib/elements.js
  3. +2 −2 lib/scaffold.js
  4. +14 −10 lib/utils.js
  5. +5 −0 public/javascripts/.jshintrc
  6. +442 −0 public/javascripts/bootstrap.js
  7. +18 −7 public/javascripts/bootstrap.min.js
  8. +2 −2 public/javascripts/example.js
  9. +2 −2 public/javascripts/main.js
  10. +176 −34 public/javascripts/prototype.js
  11. +24 −0 public/stylesheets/bootstrap-stripped.css
  12. +1 −1 public/stylesheets/bootstrap-stripped.min.css
  13. +32 −1 public/stylesheets/main.styl
  14. +23 −11 test/test.components.js
  15. +17 −11 test/test.elements.js
  16. +1 −0 todo.txt
  17. +2 −2 views/index.jade
  18. +19 −10 views/prototype.jade
  19. 0 views/templates/{ → collections}/project.jade
  20. 0 views/templates/{ → collections}/screen.jade
  21. +3 −3 views/templates/{heading-element.jade → elements/heading.jade}
  22. +1 −1 views/templates/{input-checkbox-element.jade → elements/input-checkbox.jade}
  23. +1 −1 views/templates/{input-radio-element.jade → elements/input-radio.jade}
  24. +1 −1 views/templates/{input-text-element.jade → elements/input-text.jade}
  25. +1 −1 views/templates/{paragraph-element.jade → elements/paragraph.jade}
  26. +1 −1 views/templates/{textarea-element.jade → elements/textarea.jade}
  27. 0 views/templates/{ → layouts}/layout.jade
  28. 0 views/templates/{article-element-list.jade → lists/article-element.jade}
  29. 0 views/templates/{component-list.jade → lists/component.jade}
  30. +0 −1 views/templates/{form-element-list.jade → lists/form-element.jade}
  31. +10 −0 views/templates/popovers/footer.jade
  32. +17 −0 views/templates/popovers/heading.jade
  33. +6 −0 views/templates/popovers/input-checkbox.jade
  34. +6 −0 views/templates/popovers/input-radio.jade
  35. +6 −0 views/templates/popovers/input-text.jade
  36. +6 −0 views/templates/popovers/paragraph.jade
  37. +6 −0 views/templates/popovers/textarea.jade
View
1 .jshintignore
@@ -2,4 +2,5 @@ node_modules
public/javascripts/backbone.min.js
public/javascripts/underscore.min.js
public/javascripts/bootstrap.min.js
+public/javascripts/bootstrap.js
public/javascripts/json2.js
View
4 lib/elements.js
@@ -5,7 +5,7 @@ const ALLOWED_FIELDS = {
head: undefined,
// > id of next element to form a linked list
- next: undefined,
+ nextId: undefined,
// input fields
name: undefined,
@@ -31,7 +31,7 @@ function getDefaultElement(req) {
return {
type: req.body.type,
head: req.body.head,
- next: req.body.next,
+ nextId: req.body.nextId,
name: req.body.name,
required: req.body.required || false,
src: req.body.src,
View
4 lib/scaffold.js
@@ -115,11 +115,11 @@ exports.generate = function(parents, children, name, getDefault,
callback = callback || utils.noop;
crud.update(req, key, id, allowedFields, db,
- function(err, project) {
+ function(err, object) {
if (err) {
callback(err);
} else {
- callback(null, project);
+ callback(null, object);
}
});
};
View
24 lib/utils.js
@@ -15,22 +15,26 @@ exports.generateUniqueId = function(name, id) {
return name.toString().toLowerCase().replace(ALPHANUM_MATCH, '_') + id;
};
-/* Generically map object to req.body
+/* Generically map curObject to req.body. If a property exists in curObject,
+ * req.body, and allowedFields, curObject's value is updated to equal
+ * req.body's value. If a property exists in req.body and allowedFields, but
+ * not in curObject, it is added to curObject with req.body's value.
+ *
* Requires: web request, current object, allowed fields
* Returns: The updated object if it exists, else false
*/
-exports.updateObject = function(req, currObject, allowedFields) {
- if (typeof currObject !== 'object') {
- currObject = JSON.parse(currObject);
+exports.updateObject = function(req, curObject, allowedFields) {
+ if (typeof curObject !== 'object') {
+ curObject = JSON.parse(curObject);
}
- if (currObject) {
- var setFields = function(currObject, from, allowedFields) {
+ if (curObject) {
+ var setFields = function(curObject, from, allowedFields) {
var props = Object.getOwnPropertyNames(from);
- var dest = currObject;
+ var dest = curObject;
props.forEach(function(name) {
- if (name in dest && name in allowedFields) {
+ if (name in allowedFields) {
var destination = Object.getOwnPropertyDescriptor(from, name);
if (destination) {
@@ -39,10 +43,10 @@ exports.updateObject = function(req, currObject, allowedFields) {
}
});
- return currObject;
+ return curObject;
};
- return setFields(currObject, req.body, allowedFields);
+ return setFields(curObject, req.body, allowedFields);
}
return false;
View
5 public/javascripts/.jshintrc
@@ -0,0 +1,5 @@
+{
+ "node": true,
+ "strict": false,
+ "esnext": true
+}
View
442 public/javascripts/bootstrap.js
@@ -0,0 +1,442 @@
+/* ===================================================
+ * bootstrap-transition.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * 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 ($) {
+
+ $(function () {
+
+ "use strict"; // jshint ;_;
+
+
+ /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+ * ======================================================= */
+
+ $.support.transition = (function () {
+
+ var transitionEnd = (function () {
+
+ var el = document.createElement('bootstrap')
+ , transEndEventNames = {
+ 'WebkitTransition' : 'webkitTransitionEnd'
+ , 'MozTransition' : 'transitionend'
+ , 'OTransition' : 'oTransitionEnd'
+ , 'msTransition' : 'MSTransitionEnd'
+ , 'transition' : 'transitionend'
+ }
+ , name
+
+ for (name in transEndEventNames){
+ if (el.style[name] !== undefined) {
+ return transEndEventNames[name]
+ }
+ }
+
+ }())
+
+ return transitionEnd && {
+ end: transitionEnd
+ }
+
+ })()
+
+ })
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-tooltip.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * 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 ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Tooltip = function (element, options) {
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.prototype = {
+
+ constructor: Tooltip
+
+ , init: function (type, element, options) {
+ var eventIn
+ , eventOut
+
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.enabled = true
+
+ if (this.options.trigger != 'manual') {
+ eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
+ eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
+ this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ , getOptions: function (options) {
+ options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay
+ , hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ , enter: function (e) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ clearTimeout(this.timeout)
+ self.hoverState = 'in'
+ this.timeout = setTimeout(function() {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ , leave: function (e) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (this.timeout) clearTimeout(this.timeout)
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.hoverState = 'out'
+ this.timeout = setTimeout(function() {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ , show: function () {
+ var $tip
+ , inside
+ , pos
+ , actualWidth
+ , actualHeight
+ , placement
+ , tp
+
+ if (this.hasContent() && this.enabled) {
+ $tip = this.tip()
+ this.setContent()
+
+ if (this.options.animation) {
+ $tip.addClass('fade')
+ }
+
+ placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ inside = /in/.test(placement)
+
+ $tip
+ .remove()
+ .css({ top: 0, left: 0, display: 'block' })
+ .data('element', this.$element)
+ .appendTo(inside ? this.$element : document.body)
+
+ pos = this.getPosition(inside)
+
+ actualWidth = $tip[0].offsetWidth
+ actualHeight = $tip[0].offsetHeight
+
+ switch (inside ? placement.split(' ')[1] : placement) {
+ case 'bottom':
+ tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'top':
+ tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'left':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+ break
+ case 'right':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+ break
+ }
+
+ $tip
+ .css(tp)
+ .addClass(placement)
+ .addClass('in')
+ }
+ }
+
+ , isHTML: function(text) {
+ // html string detection logic adapted from jQuery
+ return typeof text != 'string'
+ || ( text.charAt(0) === "<"
+ && text.charAt( text.length - 1 ) === ">"
+ && text.length >= 3
+ ) || /^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(text)
+ }
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.isHTML(title) ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ , hide: function () {
+ var that = this
+ , $tip = this.tip()
+
+ $tip.removeClass('in')
+
+ function removeWithAnimation() {
+ var timeout = setTimeout(function () {
+ $tip.off($.support.transition.end).remove()
+ }, 500)
+
+ $tip.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ $tip.remove()
+ })
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ removeWithAnimation() :
+ $tip.remove()
+ }
+
+ , fixTitle: function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
+ }
+ }
+
+ , hasContent: function () {
+ return this.getTitle()
+ }
+
+ , getPosition: function (inside) {
+ return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
+ width: this.$element[0].offsetWidth
+ , height: this.$element[0].offsetHeight
+ })
+ }
+
+ , getTitle: function () {
+ var title
+ , $e = this.$element
+ , o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ , tip: function () {
+ return this.$tip = this.$tip || $(this.options.template)
+ }
+
+ , validate: function () {
+ if (!this.$element[0].parentNode) {
+ this.hide()
+ this.$element = null
+ this.options = null
+ }
+ }
+
+ , enable: function () {
+ this.enabled = true
+ }
+
+ , disable: function () {
+ this.enabled = false
+ }
+
+ , toggleEnabled: function () {
+ this.enabled = !this.enabled
+ }
+
+ , toggle: function () {
+ this[this.tip().hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+ * ========================= */
+
+ $.fn.tooltip = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tooltip')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tooltip.Constructor = Tooltip
+
+ $.fn.tooltip.defaults = {
+ animation: true
+ , placement: 'top'
+ , selector: false
+ , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+ , trigger: 'hover'
+ , title: ''
+ , delay: 0
+ }
+
+}(window.jQuery);
+
+/* ===========================================================
+ * bootstrap-popover.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * 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 ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Popover = function ( element, options ) {
+ this.init('popover', element, options)
+ }
+
+
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+ ========================================== */
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+ constructor: Popover
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+ , content = this.getContent()
+ , self = this
+
+ $tip.find('.popover-title')[this.isHTML(title) ? 'html' : 'text'](title)
+
+ if (this.isHTML(content)) {
+ $tip.find('.popover-content')['html'](content)
+ } else {
+ $tip.find('.popover-content > *')['text'](content)
+ }
+
+ $tip.removeClass('fade top bottom left right in')
+ }
+
+ , hasContent: function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ , getContent: function () {
+ var content
+ , $e = this.$element
+ , o = this.options
+
+ content = $e.attr('data-content')
+ || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
+
+ return content
+ }
+
+ , tip: function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ this.$tip.data('popover', this);
+ }
+ return this.$tip
+ }
+ })
+
+
+ /* POPOVER PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.popover = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('popover')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.popover.Constructor = Popover
+
+ $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+ placement: 'right'
+ , content: ''
+ , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
+ })
+
+}(window.jQuery);
View
25 public/javascripts/bootstrap.min.js
@@ -1,7 +1,18 @@
-/**
-* Bootstrap.js by @fat & @mdo
-* plugins: bootstrap-transition.js, bootstrap-tooltip.js, bootstrap-popover.js
-* Copyright 2012 Twitter, Inc.
-* http://www.apache.org/licenses/LICENSE-2.0.txt
-*/
-!function(a){a(function(){a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){var b=function(a,b){this.init("tooltip",a,b)};b.prototype={constructor:b,init:function(b,c,d){var e,f;this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.enabled=!0,this.options.trigger!="manual"&&(e=this.options.trigger=="hover"?"mouseenter":"focus",f=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(e,this.options.selector,a.proxy(this.enter,this)),this.$element.on(f,this.options.selector,a.proxy(this.leave,this))),this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(b){return b=a.extend({},a.fn[this.type].defaults,b,this.$element.data()),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},enter:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);if(!c.options.delay||!c.options.delay.show)return c.show();clearTimeout(this.timeout),c.hoverState="in",this.timeout=setTimeout(function(){c.hoverState=="in"&&c.show()},c.options.delay.show)},leave:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!c.options.delay||!c.options.delay.hide)return c.hide();c.hoverState="out",this.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},show:function(){var a,b,c,d,e,f,g;if(this.hasContent()&&this.enabled){a=this.tip(),this.setContent(),this.options.animation&&a.addClass("fade"),f=typeof this.options.placement=="function"?this.options.placement.call(this,a[0],this.$element[0]):this.options.placement,b=/in/.test(f),a.remove().css({top:0,left:0,display:"block"}).appendTo(b?this.$element:document.body),c=this.getPosition(b),d=a[0].offsetWidth,e=a[0].offsetHeight;switch(b?f.split(" ")[1]:f){case"bottom":g={top:c.top+c.height,left:c.left+c.width/2-d/2};break;case"top":g={top:c.top-e,left:c.left+c.width/2-d/2};break;case"left":g={top:c.top+c.height/2-e/2,left:c.left-d};break;case"right":g={top:c.top+c.height/2-e/2,left:c.left+c.width}}a.css(g).addClass(f).addClass("in")}},isHTML:function(a){return typeof a!="string"||a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3||/^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(a)},setContent:function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.isHTML(b)?"html":"text"](b),a.removeClass("fade in top bottom left right")},hide:function(){function d(){var b=setTimeout(function(){c.off(a.support.transition.end).remove()},500);c.one(a.support.transition.end,function(){clearTimeout(b),c.remove()})}var b=this,c=this.tip();c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d():c.remove()},fixTitle:function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(b){return a.extend({},b?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a},tip:function(){return this.$tip=this.$tip||a(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()}},a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("tooltip"),f=typeof c=="object"&&c;e||d.data("tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover",title:"",delay:0}}(window.jQuery),!function(a){var b=function(a,b){this.init("popover",a,b)};b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype,{constructor:b,setContent:function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.isHTML(b)?"html":"text"](b),a.find(".popover-content > *")[this.isHTML(c)?"html":"text"](c),a.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-content")||(typeof c.content=="function"?c.content.call(b[0]):c.content),a},tip:function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip}}),a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("popover"),f=typeof c=="object"&&c;e||d.data("popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.defaults=a.extend({},a.fn.tooltip.defaults,{placement:"right",content:"",template:'<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'})}(window.jQuery)
+/* ===================================================
+ * bootstrap-transition.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * 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(e){e(function(){"use strict";e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,this.options.trigger!="manual"&&(i=this.options.trigger=="hover"?"mouseenter":"focus",s=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(i,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s,this.options.selector,e.proxy(this.leave,this))),this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,t,this.$element.data()),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.show)return n.show();clearTimeout(this.timeout),n.hoverState="in",this.timeout=setTimeout(function(){n.hoverState=="in"&&n.show()},n.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var e,t,n,r,i,s,o;if(this.hasContent()&&this.enabled){e=this.tip(),this.setContent(),this.options.animation&&e.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,t=/in/.test(s),e.remove().css({top:0,left:0,display:"block"}).data("element",this.$element).appendTo(t?this.$element:document.body),n=this.getPosition(t),r=e[0].offsetWidth,i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.css(o).addClass(s).addClass("in")}},isHTML:function(e){return typeof e!="string"||e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3||/^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(e)},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.isHTML(t)?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function r(){var t=setTimeout(function(){n.off(e.support.transition.end).remove()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.remove()})}var t=this,n=this.tip();n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?r():n.remove()},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(t){return e.extend({},t?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()}},e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover",title:"",delay:0}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent(),r=this;e.find(".popover-title")[this.isHTML(t)?"html":"text"](t),this.isHTML(n)?e.find(".popover-content").html(n):e.find(".popover-content > *").text(n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-content")||(typeof n.content=="function"?n.content.call(t[0]):n.content),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template),this.$tip.data("popover",this)),this.$tip}}),e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",content:"",template:'<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'})}(window.jQuery);
View
4 public/javascripts/example.js
@@ -23,7 +23,7 @@
// outerWidth/outerHeight = width/height with padding/border
width: $sidebar.outerWidth(),
height: $sidebar.outerHeight() - 70,
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
+ backgroundColor: 'rgba(0, 0, 0, 0.4)'
}).appendTo('body');
$('<div/>').css({
@@ -33,7 +33,7 @@
// outerWidth/outerHeight = width/height with padding/border
width: $body.outerWidth() - $sidebar.outerWidth(),
height: $sidebar.outerHeight(),
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
+ backgroundColor: 'rgba(0, 0, 0, 0.4)'
}).appendTo('body');
$loginForm.children('a').popover({
View
4 public/javascripts/main.js
@@ -288,7 +288,7 @@ function NapkinClient(window, document, $, data, undefined) {
var that = this;
projects.create({
- title: this.$projectInput.val().trim(),
+ title: this.$projectInput.val().trim()
}, {
error: tooltipErrorHandler(this.$projectInput),
success: function(model) {
@@ -303,7 +303,7 @@ function NapkinClient(window, document, $, data, undefined) {
var that = this;
screens.create({
- title: this.$screenInput.val().trim(),
+ title: this.$screenInput.val().trim()
}, {
error: tooltipErrorHandler(this.$screenInput),
success: function(model) {
View
210 public/javascripts/prototype.js
@@ -83,7 +83,7 @@ function NapkinClient(window, document, $, data, undefined) {
var $element = $target.siblings('.element').clone();
$element.removeClass('element')
- .addClass('active-element');
+ .addClass('live-element');
this.trigger('createElement', $element);
}
});
@@ -97,24 +97,18 @@ function NapkinClient(window, document, $, data, undefined) {
$componentClicked: null,
events: {
- 'click [class^="span"]': 'recordActiveComponentClick',
- 'click': 'blurComponent'
+ 'click [class^="span"]': 'recordComponentClick',
+ 'click .live-element': 'recordElementClick',
+ 'click': 'switchFocus'
},
- selectComponent: function($component, model) {
- $component.data('model', model);
- $component.addClass(model.get('type') + '-container');
- $component.addClass('active');
+ initialize: function() {
+ componentGroup.bind('add', this.addComponent, this);
+ componentGroup.bind('reset', this.addAllComponents, this);
- // trigger a selectComponent event which the AppView will handle
- this.$activeComponent = $component;
- this.trigger('selectComponent', $component);
- },
-
- resetComponent: function($component, type) {
- $component.removeClass(type + '-container');
- $component.removeClass('active');
- $component.empty();
+ this.bind('closePopover', this.resetActiveElement, this);
+ this.bind('applyEdits', this.applyEdits, this);
+ this.bind('removeElement', this.removeElement, this);
},
getDropOptions: function(layoutView) {
@@ -167,11 +161,6 @@ function NapkinClient(window, document, $, data, undefined) {
};
},
- initialize: function() {
- componentGroup.bind('add', this.addComponent, this);
- componentGroup.bind('reset', this.addAllComponents, this);
- },
-
render: function() {
var that = this;
this.$el.html(this.template({}));
@@ -198,6 +187,22 @@ function NapkinClient(window, document, $, data, undefined) {
return this;
},
+ selectComponent: function($component, model) {
+ $component.data('model', model);
+ $component.addClass(model.get('type') + '-container');
+ $component.addClass('active');
+
+ // trigger a selectComponent event which the AppView will handle
+ this.$activeComponent = $component;
+ this.trigger('selectComponent', $component);
+ },
+
+ resetComponent: function($component, type) {
+ $component.removeClass(type + '-container');
+ $component.removeClass('active');
+ $component.empty();
+ },
+
addComponent: function(componentModel) {
var layout = componentModel.get('layout');
var selector = '[data-position="' + layout.row + ':' + layout.col +'"]';
@@ -231,16 +236,25 @@ function NapkinClient(window, document, $, data, undefined) {
});
},
- recordActiveComponentClick: function(event) {
- var $component = $(event.currentTarget);
- if ($component.is(this.$activeComponent)) {
+ recordComponentClick: function(event) {
+ var $target = $(event.currentTarget);
+ this.$componentClicked = $target;
+
+ if ($target.is(this.$activeComponent)) {
this.clickedActiveComponent = true;
}
+ },
- this.$componentClicked = $component;
+ recordElementClick: function(event) {
+ var $target = $(event.currentTarget);
+ this.$elementClicked = $target;
+
+ if ($target.is(this.$activeElement)) {
+ this.clickedActiveElement = true;
+ }
},
- blurComponent: function(event) {
+ switchFocus: function(event) {
// note that clickedActiveComponent will be set by the
// recordComponentClick function due to event bubbling
if (!this.clickedActiveComponent) {
@@ -250,6 +264,7 @@ function NapkinClient(window, document, $, data, undefined) {
if (this.$activeComponent) {
this.$activeComponent.removeClass('active');
this.trigger('blurComponent');
+ this.$activeComponent = null;
}
// if a component was clicked, put it in focus
@@ -259,14 +274,45 @@ function NapkinClient(window, document, $, data, undefined) {
this.trigger('selectComponent', $component);
$component.addClass('active');
this.$activeComponent = $component;
- } else {
- this.$activeComponent = null;
}
}
}
+ if (!this.clickedActiveElement) {
+ var $element = this.$elementClicked;
+
+ // active element may not be defined if nothing is in focus
+ this.resetActiveElement();
+
+ // if an element was clicked, put it in focus
+ if ($element) {
+ this.setActiveElement($element);
+ }
+ }
+
+ // reset click data
this.clickedActiveComponent = false;
+ this.clickedActiveElement = false;
this.$componentClicked = null;
+ this.$elementClicked = null;
+ },
+
+ setActiveElement: function($element) {
+ $element.popover('show');
+ $element.addClass('active');
+ this.$activeElement = $element;
+ },
+
+ resetActiveElement: function() {
+ var $element = this.$activeElement;
+ if ($element) {
+ $element.popover('hide');
+ $element.removeClass('active');
+ }
+
+ this.$activeElement = null;
+ this.clickedActiveElement = false;
+ this.$elementClicked = null;
},
createElement: function($element) {
@@ -281,7 +327,7 @@ function NapkinClient(window, document, $, data, undefined) {
var elementAttrs = {
type: $element.data('type'),
- next: null,
+ nextId: null,
name: $element.data('name'),
required: false,
src: $element.data('src'),
@@ -290,7 +336,7 @@ function NapkinClient(window, document, $, data, undefined) {
};
// if there's no last element, this must be the head
- var last = elementGroup.where({ next: null })[0];
+ var last = elementGroup.where({ nextId: null })[0];
if (!last) {
elementAttrs.head = true;
}
@@ -299,7 +345,7 @@ function NapkinClient(window, document, $, data, undefined) {
// TODO: handle error
success: function(model) {
if (last) {
- last.set('next', model.id);
+ last.set('nextId', model.id);
last.save();
}
}
@@ -308,25 +354,93 @@ function NapkinClient(window, document, $, data, undefined) {
addElement: function(element, $component) {
var templateId = element.get('type') + '-element-template';
- var template = _.template($('#' + templateId).html());
- $(template(element.toJSON())).appendTo($component);
+ var elementTemplate = _.template($('#' + templateId).html());
+
+ templateId = element.get('type') + '-popover-template';
+ var popoverTemplate = _.template($('#' + templateId).html());
+
+ var $element = $(elementTemplate(element.toJSON()));
+ var row = $component.data('position').row;
+
+ var placement = 'right';
+ if (row === 0) {
+ placement = 'bottom';
+ } else if (row === 2) {
+ placement = 'top';
+ }
+
+ $element.appendTo($component);
+ $element.data('model', element);
+
+ $element.popover({
+ title: 'Edit Element',
+ trigger: 'manual',
+ placement: placement,
+ content: popoverTemplate(element.toJSON())
+ });
},
addAllElements: function($component) {
+ // clear out any leftover elements
+ $component.empty();
+
var elementGroup = $component.data('elementGroup');
var element = elementGroup.where({ head: true })[0];
// go through each element in the linked list
while (element) {
this.addElement(element, $component);
- element = elementGroup.get(element.get('next'));
+ element = elementGroup.get(element.get('nextId'));
}
+ },
+
+ applyEdits: function() {
+ var $element = this.$activeElement;
+
+ },
+
+ removeElement: function() {
+ var $element = this.$activeElement;
+ this.resetActiveElement();
+ var model = $element.data('model');
+
+ // $element.parent() is the component
+ var elementGroup = $element.parent().data('elementGroup');
+
+ var previous = elementGroup.where({ nextId: model.id })[0];
+ var nextId = model.get('nextId');
+
+ model.destroy({
+ success: function() {
+ if (previous) {
+ // rearrange links in the linked list
+ previous.set('nextId', nextId);
+ previous.save();
+ } else {
+ // removing the first element, so reset the head
+ var next = elementGroup.get(nextId);
+ if (next) { // may also be the last element
+ next.set('head', true);
+ next.save();
+ }
+ }
+
+ $element.remove();
+ }
+ });
}
});
var AppView = Backbone.View.extend({
el: $('body'),
+ events: {
+ 'click .close-popover': 'closePopover',
+ 'click .popover-content .btn-primary': 'applyEdits',
+ 'click .popover-content .btn-danger': 'removeElement',
+ 'keydown': 'processKeyShortcuts'
+ },
+
initialize: function() {
this.componentListView = new ComponentListView();
$('#sidebar').append(this.componentListView.render().$el);
@@ -359,6 +473,34 @@ function NapkinClient(window, document, $, data, undefined) {
this.elementListView.unbind('addElement');
this.elementListView.remove();
}
+ },
+
+ // close popover when close popover link is clicked
+ closePopover: function(event) {
+ event.preventDefault();
+ this.layoutView.trigger('closePopover');
+ },
+
+ // apply edits to element when apply button is clicked
+ applyEdits: function(event) {
+ this.layoutView.trigger('applyEdits');
+ },
+
+ // remove element when delete button is clicked
+ removeElement: function(event) {
+ this.layoutView.trigger('removeElement');
+ },
+
+ // process key presses for shortcuts; e.g. backspace deletes an element
+ processKeyShortcuts: function(event) {
+ // ignore key presses in input fields
+ if ($('input[type="text"]:focus, textarea:focus').length === 0) {
+ // if the user hit backspace and has an element focused, remove it
+ if (event.which === 8 && this.layoutView.$activeElement) {
+ this.layoutView.trigger('removeElement');
+ event.preventDefault();
+ }
+ }
}
});
View
24 public/stylesheets/bootstrap-stripped.css
@@ -219,6 +219,24 @@ textarea {
.offset1 {
margin-left: 100px;
}
+.form-actions {
+ padding: 17px 20px 18px;
+ margin-top: 18px;
+ margin-bottom: 18px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #e5e5e5;
+ *zoom: 1;
+}
+
+.form-actions:before,
+.form-actions:after {
+ display: table;
+ content: "";
+}
+
+.form-actions:after {
+ clear: both;
+}
select,
input[type="text"],
textarea {
@@ -662,6 +680,12 @@ input[type="submit"].btn::-moz-focus-inner {
.icon-plus-sign {
background-position: 0 -96px;
}
+.icon-remove {
+ background-position: -312px 0;
+}
+.icon-refresh {
+ background-position: -240px -24px;
+}
.tooltip {
position: absolute;
z-index: 1020;
View
2 public/stylesheets/bootstrap-stripped.min.css
@@ -1 +1 @@
-/*!* Bootstrap v2.0.4 * * Copyright 2012 Twitter,Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ .clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";}.clearfix:after{clear:both;}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}audio:not([controls]){display:none;}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}a:hover,a:active{outline:0;}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}#map_canvas img{max-width:none;}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}button,input{*overflow:visible;line-height:normal;}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield;}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;}textarea{overflow:auto;vertical-align:top;}.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";}.row:after{clear:both;}[class*="span"]{float:left;margin-left:20px;}.span12{width:940px;}.span11{width:860px;}.span10{width:780px;}.span9{width:700px;}.span8{width:620px;}.span7{width:540px;}.span6{width:460px;}.span5{width:380px;}.span4{width:300px;}.span3{width:220px;}.span2{width:140px;}.span1{width:60px;}.offset12{margin-left:980px;}.offset11{margin-left:900px;}.offset10{margin-left:820px;}.offset9{margin-left:740px;}.offset8{margin-left:660px;}.offset7{margin-left:580px;}.offset6{margin-left:500px;}.offset5{margin-left:420px;}.offset4{margin-left:340px;}.offset3{margin-left:260px;}.offset2{margin-left:180px;}.offset1{margin-left:100px;}select,input[type="text"],textarea{display:inline-block;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555;}input,textarea{width:210px;}input[type="text"],textarea{background-color:#fff;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-ms-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s;}input[type="text"]:focus,textarea:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);}input[type="radio"],input[type="checkbox"]{margin:3px 0;*margin-top:0;line-height:normal;cursor:pointer;}input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto;}.uneditable-textarea{width:auto;height:auto;}select{height:28px;*margin-top:4px;line-height:28px;}select{width:220px;border:1px solid #bbb;}select[multiple],select[size]{height:auto;}select:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}.radio,.checkbox{min-height:18px;padding-left:18px;}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px;}.btn{display:inline-block;*display:inline;*zoom:1;padding:4px 10px 4px;margin-bottom:0;font-size:13px;line-height:18px;*line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#e6e6e6',GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #ccc;*border:0;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{background-color:#e6e6e6;*background-color:#d9d9d9;}.btn:active,.btn.active{background-color:#ccc \9;}.btn:first-child{*margin-left:0;}.btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-ms-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear;}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}.btn.active,.btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05);}.btn.disabled,.btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover,.btn-inverse,.btn-inverse:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75);}.btn{border-color:#ccc;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);}.btn-primary{background-color:#0074cc;background-image:-moz-linear-gradient(top,#08c,#05c);background-image:-ms-linear-gradient(top,#08c,#05c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#05c));background-image:-webkit-linear-gradient(top,#08c,#05c);background-image:-o-linear-gradient(top,#08c,#05c);background-image:linear-gradient(top,#08c,#05c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0055cc',GradientType=0);border-color:#05c #0055cc #003580;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#05c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#05c;*background-color:#004ab3;}.btn-primary:active,.btn-primary.active{background-color:#004099 \9;}.btn-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;*background-color:#df8505;}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9;}.btn-danger{background-color:#da4f49;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-ms-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#bd362f',GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;*background-color:#a9302a;}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9;}.btn-success{background-color:#5bb75b;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-ms-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462',endColorstr='#51a351',GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;*background-color:#499249;}.btn-success:active,.btn-success.active{background-color:#408140 \9;}.btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-ms-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de',endColorstr='#2f96b4',GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;*background-color:#2a85a0;}.btn-info:active,.btn-info.active{background-color:#24748c \9;}.btn-inverse{background-color:#414141;background-image:-moz-linear-gradient(top,#555,#222);background-image:-ms-linear-gradient(top,#555,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#555),to(#222));background-image:-webkit-linear-gradient(top,#555,#222);background-image:-o-linear-gradient(top,#555,#222);background-image:linear-gradient(top,#555,#222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#555555',endColorstr='#222222',GradientType=0);border-color:#222 #222222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{background-color:#222;*background-color:#151515;}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9;}button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../images/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;}[class^="icon-"]:last-child,[class*=" icon-"]:last-child{*margin-left:0;}.icon-white{background-image:url("../images/glyphicons-halflings-white.png");}.icon-chevron-right{background-position:-456px -72px;}.icon-pencil{background-position:0 -72px;}.icon-trash{background-position:-456px 0;}.icon-plus-sign{background-position:0 -96px;}.tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:.8;filter:alpha(opacity=80);}.tooltip.top{margin-top:-2px;}.tooltip.right{margin-left:2px;}.tooltip.bottom{margin-top:2px;}.tooltip.left{margin-left:-2px;}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000;}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000;}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000;}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000;}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.tooltip-arrow{position:absolute;width:0;height:0;}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-ms-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear;}.fade.in{opacity:1;}.modal-open .popover{z-index:2060;}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}.popover.top{margin-top:-5px;}.popover.right{margin-left:5px;}.popover.bottom{margin-top:5px;}.popover.left{margin-left:-5px;}.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-top:5px solid #000;border-right:5px solid transparent;border-left:5px solid transparent;}.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-right:5px solid #000;border-bottom:5px solid transparent;}.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-right:5px solid transparent;border-bottom:5px solid #000;border-left:5px solid transparent;}.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000;}.popover .arrow{position:absolute;width:0;height:0;}.popover-inner{width:280px;padding:3px;overflow:hidden;background:#000;background:rgba(0,0,0,0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);}.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;}.popover-content{padding:14px;background-color:#fff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0;}
+/*!* Bootstrap v2.0.4 * * Copyright 2012 Twitter,Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ .clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";}.clearfix:after{clear:both;}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}audio:not([controls]){display:none;}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}a:hover,a:active{outline:0;}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}#map_canvas img{max-width:none;}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}button,input{*overflow:visible;line-height:normal;}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield;}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;}textarea{overflow:auto;vertical-align:top;}.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";}.row:after{clear:both;}[class*="span"]{float:left;margin-left:20px;}.span12{width:940px;}.span11{width:860px;}.span10{width:780px;}.span9{width:700px;}.span8{width:620px;}.span7{width:540px;}.span6{width:460px;}.span5{width:380px;}.span4{width:300px;}.span3{width:220px;}.span2{width:140px;}.span1{width:60px;}.offset12{margin-left:980px;}.offset11{margin-left:900px;}.offset10{margin-left:820px;}.offset9{margin-left:740px;}.offset8{margin-left:660px;}.offset7{margin-left:580px;}.offset6{margin-left:500px;}.offset5{margin-left:420px;}.offset4{margin-left:340px;}.offset3{margin-left:260px;}.offset2{margin-left:180px;}.offset1{margin-left:100px;}.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1;}.form-actions:before,.form-actions:after{display:table;content:"";}.form-actions:after{clear:both;}select,input[type="text"],textarea{display:inline-block;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555;}input,textarea{width:210px;}input[type="text"],textarea{background-color:#fff;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-ms-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s;}input[type="text"]:focus,textarea:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);}input[type="radio"],input[type="checkbox"]{margin:3px 0;*margin-top:0;line-height:normal;cursor:pointer;}input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto;}.uneditable-textarea{width:auto;height:auto;}select{height:28px;*margin-top:4px;line-height:28px;}select{width:220px;border:1px solid #bbb;}select[multiple],select[size]{height:auto;}select:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}.radio,.checkbox{min-height:18px;padding-left:18px;}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px;}.btn{display:inline-block;*display:inline;*zoom:1;padding:4px 10px 4px;margin-bottom:0;font-size:13px;line-height:18px;*line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#e6e6e6',GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #ccc;*border:0;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{background-color:#e6e6e6;*background-color:#d9d9d9;}.btn:active,.btn.active{background-color:#ccc \9;}.btn:first-child{*margin-left:0;}.btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-ms-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear;}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}.btn.active,.btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05);}.btn.disabled,.btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover,.btn-inverse,.btn-inverse:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75);}.btn{border-color:#ccc;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);}.btn-primary{background-color:#0074cc;background-image:-moz-linear-gradient(top,#08c,#05c);background-image:-ms-linear-gradient(top,#08c,#05c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#05c));background-image:-webkit-linear-gradient(top,#08c,#05c);background-image:-o-linear-gradient(top,#08c,#05c);background-image:linear-gradient(top,#08c,#05c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0055cc',GradientType=0);border-color:#05c #0055cc #003580;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#05c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#05c;*background-color:#004ab3;}.btn-primary:active,.btn-primary.active{background-color:#004099 \9;}.btn-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-ms-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450',endColorstr='#f89406',GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;*background-color:#df8505;}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9;}.btn-danger{background-color:#da4f49;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-ms-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#bd362f',GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;*background-color:#a9302a;}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9;}.btn-success{background-color:#5bb75b;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-ms-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462',endColorstr='#51a351',GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;*background-color:#499249;}.btn-success:active,.btn-success.active{background-color:#408140 \9;}.btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-ms-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de',endColorstr='#2f96b4',GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;*background-color:#2a85a0;}.btn-info:active,.btn-info.active{background-color:#24748c \9;}.btn-inverse{background-color:#414141;background-image:-moz-linear-gradient(top,#555,#222);background-image:-ms-linear-gradient(top,#555,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#555),to(#222));background-image:-webkit-linear-gradient(top,#555,#222);background-image:-o-linear-gradient(top,#555,#222);background-image:linear-gradient(top,#555,#222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#555555',endColorstr='#222222',GradientType=0);border-color:#222 #222222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{background-color:#222;*background-color:#151515;}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9;}button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../images/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;}[class^="icon-"]:last-child,[class*=" icon-"]:last-child{*margin-left:0;}.icon-white{background-image:url("../images/glyphicons-halflings-white.png");}.icon-chevron-right{background-position:-456px -72px;}.icon-pencil{background-position:0 -72px;}.icon-trash{background-position:-456px 0;}.icon-plus-sign{background-position:0 -96px;}.icon-remove{background-position:-312px 0;}.icon-refresh{background-position:-240px -24px;}.tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:.8;filter:alpha(opacity=80);}.tooltip.top{margin-top:-2px;}.tooltip.right{margin-left:2px;}.tooltip.bottom{margin-top:2px;}.tooltip.left{margin-left:-2px;}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000;}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000;}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000;}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000;}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.tooltip-arrow{position:absolute;width:0;height:0;}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-ms-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear;}.fade.in{opacity:1;}.modal-open .popover{z-index:2060;}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}.popover.top{margin-top:-5px;}.popover.right{margin-left:5px;}.popover.bottom{margin-top:5px;}.popover.left{margin-left:-5px;}.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-top:5px solid #000;border-right:5px solid transparent;border-left:5px solid transparent;}.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-right:5px solid #000;border-bottom:5px solid transparent;}.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-right:5px solid transparent;border-bottom:5px solid #000;border-left:5px solid transparent;}.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000;}.popover .arrow{position:absolute;width:0;height:0;}.popover-inner{width:280px;padding:3px;overflow:hidden;background:#000;background:rgba(0,0,0,0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);}.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;}.popover-content{padding:14px;background-color:#fff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0;}
View
33 public/stylesheets/main.styl
@@ -295,10 +295,15 @@ header a
float left
width 190px
-.active-element:hover
+.live-element:hover, .live-element.active
background rgba(78, 150, 0, 0.3)
background #F7F3C5
+.live-element.active
+ padding 5px 10px
+ margin-left -10px
+ margin-right -10px
+
.elements .btn
float right
font-size 110%
@@ -338,3 +343,29 @@ header a
#prototype #content h2
margin-bottom 20px
+
+.popover-inner
+ width 260px
+
+.popover-content .form-actions
+ margin 10px -14px -14px
+
+.popover-content .form-actions .btn-primary
+ margin-right 10px
+
+.popover-content .form-actions i
+ margin-top 1px
+ margin-right 3px
+
+.close-popover
+ position absolute
+ right -5px
+ top -5px
+ padding 5px 5px 2px
+ background-color rgba(0, 0, 0, 0.9)
+ border-radius(15px)
+
+#level
+ width 45px
+ margin-left 10px
+ margin-top 7px
View
34 test/test.components.js
@@ -45,7 +45,10 @@ var componentReq = {
},
body: {
type: 'form',
- layout: 'row1',
+ layout: {
+ row: 1,
+ col: 0
+ },
action: '/'
},
params: {
@@ -60,7 +63,10 @@ var otherComponentReq = {
},
body: {
type: 'authentication',
- layout: 'row1',
+ layout: {
+ row: 1,
+ col: 1
+ },
action: '/auth'
},
params: {
@@ -107,7 +113,7 @@ describe('component', function() {
components.add(req, db, function(err, component) {
component.type.should.equal(req.body.type);
- component.layout.should.equal(req.body.layout);
+ component.layout.should.eql(req.body.layout);
component.action.should.equal(req.body.action);
done();
});
@@ -121,7 +127,7 @@ describe('component', function() {
setTimeout(function() {
components.get(req, db, 2, function(err, component) {
component.type.should.equal(req.body.type);
- component.layout.should.equal(req.body.layout);
+ component.layout.should.eql(req.body.layout);
component.action.should.equal(req.body.action);
done();
});
@@ -136,12 +142,12 @@ describe('component', function() {
components.list(req, db, function(errList, componentList) {
componentList[0].type.should.equal(req.body.type);
- componentList[0].layout.should.equal(req.body.layout);
+ componentList[0].layout.should.eql(req.body.layout);
componentList[0].action.should.equal(req.body.action);
req = otherComponentReq;
componentList[1].type.should.equal(req.body.type);
- componentList[1].layout.should.equal(req.body.layout);
+ componentList[1].layout.should.eql(req.body.layout);
componentList[1].action.should.equal(req.body.action);
done();
});
@@ -155,7 +161,7 @@ describe('component', function() {
it('returns a specific component', function(done) {
components.get(req, db, 1, function(err, component) {
component.type.should.equal(req.body.type);
- component.layout.should.equal(req.body.layout);
+ component.layout.should.eql(req.body.layout);
component.action.should.equal(req.body.action);
done();
});
@@ -174,21 +180,27 @@ describe('component', function() {
var req = componentReq;
it('updates a component', function(done) {
- req.body.layout = 'row2';
+ req.body.layout = {
+ row: 2,
+ col: 1,
+ };
components.update(req, db, 1, function(err, component) {
- component.layout.should.equal(req.body.layout);
+ component.layout.should.eql(req.body.layout);
done();
});
});
it('accepts an empty callback', function(done) {
- req.body.layout = 'row3';
+ req.body.layout = {
+ row: 2,
+ col: 2
+ };
components.update(req, db, 1);
// wait 10ms for db transaction to complete
setTimeout(function() {
components.get(req, db, 1, function(err, component) {
- component.layout.should.equal(req.body.layout);
+ component.layout.should.eql(req.body.layout);
done();
});
}, 10);
View
28 test/test.elements.js
@@ -60,7 +60,8 @@ var elementReq = {
},
body: {
type: 'input_text',
- layout: 'row1',
+ head: true,
+ nextId: 1,
required: true,
src: ''
},
@@ -77,7 +78,7 @@ var otherElementReq = {
},
body: {
type: 'input_radio',
- layout: 'col1',
+ nextId: null,
required: true,
src: ''
},
@@ -112,7 +113,8 @@ describe('element', function() {
var req = elementReq;
elements.add(req, db, function(err, element) {
element.type.should.equal(req.body.type);
- element.layout.should.equal(req.body.layout);
+ element.head.should.equal(req.body.head);
+ element.nextId.should.equal(req.body.nextId);
element.required.should.equal(req.body.required);
element.src.should.equal(req.body.src);
done();
@@ -127,7 +129,8 @@ describe('element', function() {
setTimeout(function() {
elements.get(req, db, 2, function(err, element) {
element.type.should.equal(req.body.type);
- element.layout.should.equal(req.body.layout);
+ should.not.exist(element.head);
+ should.not.exist(element.nextId);
element.required.should.equal(req.body.required);
element.src.should.equal(req.body.src);
done();
@@ -143,13 +146,15 @@ describe('element', function() {
elements.list(req, db, function(errList, elementList) {
elementList[0].type.should.equal(req.body.type);
- elementList[0].layout.should.equal(req.body.layout);
+ elementList[0].head.should.equal(req.body.head);
+ elementList[0].nextId.should.equal(req.body.nextId);
elementList[0].required.should.equal(req.body.required);
elementList[0].src.should.equal(req.body.src);
req = otherElementReq;
elementList[1].type.should.equal(req.body.type);
- elementList[1].layout.should.equal(req.body.layout);
+ should.not.exist(elementList[1].head);
+ should.not.exist(elementList[1].nextId);
elementList[1].required.should.equal(req.body.required);
elementList[1].src.should.equal(req.body.src);
done();
@@ -164,7 +169,8 @@ describe('element', function() {
it('returns a specific element', function(done) {
elements.get(req, db, 1, function(err, element) {
element.type.should.equal(req.body.type);
- element.layout.should.equal(req.body.layout);
+ element.head.should.equal(req.body.head);
+ element.nextId.should.equal(req.body.nextId);
element.required.should.equal(req.body.required);
element.src.should.equal(req.body.src);
done();
@@ -184,21 +190,21 @@ describe('element', function() {
var req = elementReq;
it('updates a specific element', function(done) {
- req.body.layout = 'row2';
+ req.body.nextId = 2;
elements.update(req, db, 1, function(err, element) {
- element.layout.should.equal(req.body.layout);
+ element.nextId.should.equal(req.body.nextId);
done();
});
});
it('accepts an empty callback', function(done) {
- req.body.layout = 'row3';
+ req.body.nextId = 3;
elements.update(req, db, 1);
// wait 10ms for db transaction to complete
setTimeout(function() {
elements.get(req, db, 1, function(err, element) {
- element.layout.should.equal(req.body.layout);
+ element.nextId.should.equal(req.body.nextId);
done();
});
}, 10);
View
1 todo.txt
@@ -0,0 +1 @@
+- Restructure files in new folders before commit
View
4 views/index.jade
@@ -7,8 +7,8 @@ block sidebar
block content
!=partial('forms/add-screen')
- !=partial('templates/project')
- !=partial('templates/screen')
+ !=partial('templates/collections/project')
+ !=partial('templates/collections/screen')
block scripts
script(src='/javascripts/json2.js')
View
29 views/prototype.jade
@@ -14,15 +14,24 @@ block scripts
});
});
- != partial('templates/layout')
- != partial('templates/component-list')
- != partial('templates/article-element-list')
- != partial('templates/form-element-list')
+ // layouts and lists
+ != partial('templates/layouts/layout')
+ != partial('templates/lists/component')
+ != partial('templates/lists/article-element')
+ != partial('templates/lists/form-element')
- != partial('templates/heading-element')
- != partial('templates/paragraph-element')
+ // article elements and popovers
+ != partial('templates/elements/heading')
+ != partial('templates/popovers/heading')
+ != partial('templates/elements/paragraph')
+ != partial('templates/popovers/paragraph')
- != partial('templates/input-text-element')
- != partial('templates/input-radio-element')
- != partial('templates/input-checkbox-element')
- != partial('templates/textarea-element')
+ // form elements and popovers
+ != partial('templates/elements/input-text')
+ != partial('templates/popovers/input-text')
+ != partial('templates/elements/input-radio')
+ != partial('templates/popovers/input-radio')
+ != partial('templates/elements/input-checkbox')
+ != partial('templates/popovers/input-checkbox')
+ != partial('templates/elements/textarea')
+ != partial('templates/popovers/textarea')
View
0 views/templates/project.jade → views/templates/collections/project.jade
File renamed without changes.
View
0 views/templates/screen.jade → views/templates/collections/screen.jade
File renamed without changes.
View
6 views/templates/heading-element.jade → views/templates/elements/heading.jade
@@ -1,8 +1,8 @@
script#heading-element-template(type='text/template')
<% if (level === 1) { %>
- h1.active-element(data-type='heading') <%- text %>
+ h1.live-element(data-type='heading') <%- text %>
<% } else if (level === 2) { %>
- h2.active-element(data-type='heading') <%- text %>
+ h2.live-element(data-type='heading') <%- text %>
<% } else if (level === 3) { %>
- h3.active-element(data-type='heading') <%- text %>
+ h3.live-element(data-type='heading') <%- text %>
<% } %>
View
2 views/templates/input-checkbox-element.jade → views/templates/elements/input-checkbox.jade
@@ -1,5 +1,5 @@
script#input-checkbox-element-template(type='text/template')
// TODO: make names unique and id-ize them for inputs
- .active-element.field
+ .live-element.field
label(for!='<%- name %>') <%- name %>:
input(type='checkbox', name!='<%- name %>', id!='<%- name %>')
View
2 views/templates/input-radio-element.jade → views/templates/elements/input-radio.jade
@@ -1,5 +1,5 @@
script#input-radio-element-template(type='text/template')
// TODO: make names unique and id-ize them for inputs
- .active-element.field
+ .live-element.field
label(for!='<%- name %>') <%- name %>:
input(type='radio', name!='<%- name %>', id!='<%- name %>')
View
2 views/templates/input-text-element.jade → views/templates/elements/input-text.jade
@@ -1,5 +1,5 @@
script#input-text-element-template(type='text/template')
// TODO: make names unique and id-ize them for inputs
- .active-element.field
+ .live-element.field
label(for!='<%- name %>') <%- name %>:
input(type='text', name!='<%- name %>', id!='<%- name %>')
View
2 views/templates/paragraph-element.jade → views/templates/elements/paragraph.jade
@@ -1,2 +1,2 @@
script#paragraph-element-template(type='text/template')
- p.active-element(data-type='paragraph') <%- text %>
+ p.live-element(data-type='paragraph') <%- text %>
View
2 views/templates/textarea-element.jade → views/templates/elements/textarea.jade
@@ -1,5 +1,5 @@
script#textarea-element-template(type='text/template')
// TODO: make names unique and id-ize them for textarea
- .active-element.field
+ .live-element.field
label(for!='<%- name %>') <%- name %>:
textarea(rows='8', cols='20', name!='<%- name %>', id!='<%- name %>')
View
0 views/templates/layout.jade → views/templates/layouts/layout.jade
File renamed without changes.
View
0 views/templates/article-element-list.jade → views/templates/lists/article-element.jade
File renamed without changes.
View
0 views/templates/component-list.jade → views/templates/lists/component.jade
File renamed without changes.
View
1 views/templates/form-element-list.jade → views/templates/lists/form-element.jade
@@ -22,4 +22,3 @@ script#form-element-list(type='text/template')
label(for='textarea') Textarea:
textarea(rows='8', cols='20', name='textarea')
a.btn.btn-success +
-
View
10 views/templates/popovers/footer.jade
@@ -0,0 +1,10 @@
+.form-actions
+ a.btn.btn-primary
+ i.icon-refresh.icon-white
+ | Apply
+ a.btn.btn-danger
+ i.icon-trash.icon-white
+ | Delete
+
+a.close-popover(href='#close')
+ i.icon-remove.icon-white
View
17 views/templates/popovers/heading.jade
@@ -0,0 +1,17 @@
+script#heading-popover-template(type='text/template')
+ .field
+ label(for='text') Text:
+ input#text(name='text', type='text', value!='<%- text %>')
+
+ .field
+ label(for='level') Level:
+ select#level(name='level')
+ <% for(var i = 1; i <= 6; i++) { %>
+ <% if(i === level) { %>
+ option(value!='<%- i %>', selected='true') <%- i %>
+ <% } else { %>
+ option(value!='<%- i %>') <%- i %>
+ <% } %>
+ <% } %>
+
+ != partial('templates/popovers/footer')
View
6 views/templates/popovers/input-checkbox.jade
@@ -0,0 +1,6 @@
+script#input-checkbox-popover-template(type='text/template')
+ .field
+ label(for='name') Name:
+ input#name(name='name', type='text', value!='<%- name %>')
+
+ != partial('templates/popovers/footer')
View
6 views/templates/popovers/input-radio.jade
@@ -0,0 +1,6 @@
+script#input-radio-popover-template(type='text/template')
+ .field
+ label(for='name') Name:
+ input#name(name='name', type='text', value!='<%- name %>')
+
+ != partial('templates/popovers/footer')
View
6 views/templates/popovers/input-text.jade
@@ -0,0 +1,6 @@
+script#input-text-popover-template(type='text/template')
+ .field
+ label(for='name') Name:
+ input#name(name='name', type='text', value!='<%- name %>')
+
+ != partial('templates/popovers/footer')
View
6 views/templates/popovers/paragraph.jade
@@ -0,0 +1,6 @@
+script#paragraph-popover-template(type='text/template')
+ .field
+ label(for='text') Text:
+ textarea#text(name='text', type='text', value!='<%- text %>')
+
+ != partial('templates/popovers/footer')
View
6 views/templates/popovers/textarea.jade
@@ -0,0 +1,6 @@
+script#textarea-popover-template(type='text/template')
+ .field
+ label(for='name') Name:
+ input#name(name='name', type='text', value!='<%- name %>')
+
+ != partial('templates/popovers/footer')

0 comments on commit 4cdf1a5

Please sign in to comment.