summaryrefslogtreecommitdiffstats
path: root/client/components/forms
diff options
context:
space:
mode:
Diffstat (limited to 'client/components/forms')
-rw-r--r--client/components/forms/cachedValue.js22
-rw-r--r--client/components/forms/forms.styl636
-rw-r--r--client/components/forms/inlinedform.jade6
-rw-r--r--client/components/forms/inlinedform.js93
4 files changed, 757 insertions, 0 deletions
diff --git a/client/components/forms/cachedValue.js b/client/components/forms/cachedValue.js
new file mode 100644
index 00000000..a2898d85
--- /dev/null
+++ b/client/components/forms/cachedValue.js
@@ -0,0 +1,22 @@
+var emptyValue = '';
+
+Mixins.CachedValue = BlazeComponent.extendComponent({
+ onCreated: function() {
+ this._cachedValue = emptyValue;
+ },
+
+ setCache: function(value) {
+ this._cachedValue = value;
+ },
+
+ getCache: function(defaultValue) {
+ if (this._cachedValue === emptyValue)
+ return defaultValue || '';
+ else
+ return this._cachedValue;
+ },
+
+ resetCache: function() {
+ this.setCache('');
+ }
+});
diff --git a/client/components/forms/forms.styl b/client/components/forms/forms.styl
new file mode 100644
index 00000000..1084a4a6
--- /dev/null
+++ b/client/components/forms/forms.styl
@@ -0,0 +1,636 @@
+@import 'nib'
+
+textarea,
+input:not([type=file]),
+button
+ box-sizing: border-box
+ -webkit-appearance: none
+ background-color: #ebebeb
+ border: 1px solid #ccc
+ border-radius: 3px
+ display: block
+ margin-bottom: 12px
+ min-height: 34px
+ padding: 7px
+
+ &.full
+ width: 100%
+
+ &.input-error
+ background-color: #ece9e9
+ border-color: #ba1212
+
+ &:focus
+ outline: 0
+
+input[type="file"]
+ margin-bottom: 16px
+
+input[type="radio"]
+ -webkit-appearance: radio
+ min-height: inherit
+
+input[type="checkbox"]
+ -webkit-appearance: checkbox
+ margin-right: 4px
+
+input[type="text"],
+input[type="password"],
+input[type="email"]
+ transition: background 85ms ease-in,
+ border-color 85ms ease-in
+ width: 250px
+
+ &.inline-input
+ background: none
+ border: 0
+ margin: 0
+ padding: 2px
+ min-height: 0
+ height: 18px
+ width: 200px
+
+input[type="email"]:invalid
+ box-shadow: none
+
+input[type="text"],
+input[type="password"],
+input[type="email"],
+textarea
+
+ &:hover
+ border-color: #999
+
+ &.input-error
+ border-color: #ba1212
+
+ &:focus
+ background: #fff
+ border-color: #318ec4
+ box-shadow: 0 0 2px #318ec4
+
+ &.input-error
+ background-color: #f8f7f7
+ border-color: #ba1212
+ box-shadow: 0 0 2px #d11515
+
+ &:disabled
+ background-color: #dcdcdc
+ border-color: #bfbfbf
+ color: #8c8c8c
+ -webkit-touch-callout: none
+ user-select: none
+
+select
+ max-height: 300px
+ width: 256px
+ margin-bottom: 8px
+
+option[disabled]
+ color: #8c8c8c
+
+textarea
+ height: 150px
+ transition: background 85ms ease-in,
+ border-color 85ms ease-in
+ resize: vertical
+ width: 100%
+
+.button
+ border-radius: 3px
+ text-decoration: none
+ position: relative
+
+input[type="submit"],
+button
+ background: #cfcfcf
+ background: linear-gradient(#cfcfcf, #c2c2c2)
+ border: none
+ box-shadow: 0 1px 0 #8c8c8c
+ cursor: pointer
+ display: inline-block
+ font-weight: 700
+ line-height: 22px
+ margin: 8px 4px 0 0
+ padding: 7px 20px
+ text-align: center
+
+ .wide
+ padding-left: 30px
+ padding-right: 30px
+
+ &:hover,
+ &:focus
+ background: #c2c2c2
+ background: linear-gradient(#c2c2c2, #b5b5b5)
+
+ &:active
+ background: #b5b5b5
+ background: linear-gradient(#b5b5b5, #a8a8a8)
+ box-shadow: inset 0 3px 6px rgba(0, 0, 0, .1)
+
+ &:hover,
+ &:focus,
+ &:active
+ background: #e6e6e6
+ background: linear-gradient(#e6e6e6, #e6e6e6)
+
+ &.primary
+ background: #005377
+ box-shadow: 0 1px 0 #4d4d4d
+ color: white
+
+ &:hover,
+ &:focus
+ background: #004766
+
+ &:active
+ background: #01628C
+
+ &.negate
+ &:hover,
+ &:focus
+ background: #990f0f
+ background: linear-gradient(#990f0f, #7d0c0c)
+ box-shadow: 0 1px 0 #4d4d4d
+ color: #fff
+
+ &:active
+ background: #7d0c0c
+ box-shadow: 0 1px 0 #4d4d4d
+ color: #fff
+
+input[type="submit"].disabled,
+input[type="submit"]:disabled,
+input[type="button"].disabled,
+button.disabled,
+.button.disabled
+
+ &,
+ &:hover,
+ &:active
+ background: #cfcfcf
+ cursor: default
+ box-shadow: none
+ color: #a8a8a8
+
+fieldset
+ border: 1px solid #bfbfbf
+ padding: 15px
+ margin-bottom: 15px
+
+input[type="hidden"]
+ display: none
+
+input[type="checkbox"],
+input[type="radio"]
+ display: inline
+
+.radio-div,
+.check-div
+ display: block
+ margin: 0 0 4px 20px
+ min-height: 20px
+ position: relative
+
+ input
+ left: -18px
+ min-height: 0
+ margin: 0
+ padding: 0
+ position: absolute
+ top: 2px
+
+ label
+ font-weight: 400
+
+label
+ display: block
+ font-weight: 700
+ margin-bottom: 4px
+
+ &.form-error
+ color: #ba1212
+
+input,
+textarea
+ &::-webkit-input-placeholder,
+ &::-moz-placeholder
+ color: #8c8c8c
+
+.edit-controls,
+.add-controls
+ margin-top: 0
+
+ button[type=submit]
+ float: left
+ height: 32px
+ margin-top: -2px
+ padding-top: 5px
+ padding-bottom: 5px
+
+ i.fa.fa-times
+ font-size: 20px
+
+ .option
+ border-color: transparent
+ border-radius: 3px
+ color: #8c8c8c
+ display: block
+ float: right
+ height: 30px
+ line-height: 30px
+ padding: 0 8px
+ margin: 0 2px
+
+ &:hover
+ background-color: #dbdbdb
+ color: #4d4d4d
+
+ &:active
+ background-color: #ccc
+
+.button-link
+ background: #fff
+ background: linear-gradient(#fff, #f5f5f5)
+ border-radius: 3px
+ box-sizing: border-box
+ user-select: none
+ border: 1px solid #e3e3e3
+ border-bottom-color: #c2c2c2
+ cursor: pointer
+ display: block
+ font-weight: 700
+ height: 34px
+ margin-top: 6px
+ max-width: 300px
+ padding: 7px
+ position: relative
+ text-decoration: none
+ overflow: ellipsis
+
+ .on
+ background: #48b512
+ background: linear-gradient(#48b512, #3d990f)
+ border-radius: 3px
+ color: #fff
+ display: none
+ font-size: 12px
+ font-weight: 700
+ height: 17px
+ line-height: @height
+ margin: 0
+ padding: 2px 4px
+ position: absolute
+ right: 5px
+ top: 5px
+ text-align: center
+
+ &.is-on
+ padding-right: 30px
+ max-width: 196px
+
+ .on
+ display: block
+
+ &.inline
+ color: #666
+ padding: 2px 14px
+ margin-left: 4px
+
+ &.setting
+ height: 52px
+ float: left
+ position: relative
+ margin-top: 0
+
+ &.disabled
+ background: #fff
+ border-color: #e9e9e9
+ color: #8c8c8c
+ cursor: default
+
+ select
+ display: none
+
+ &:hover .label
+ color: #8c8c8c
+
+ &,
+ &:hover,
+ &:active,
+ &.primary,
+ &.primary:hover,
+ &.primary:active
+ background: #cfcfcf
+ border-color: #c2c2c2
+ border-bottom-color: #b5b5b5
+ cursor: default
+ box-shadow: none
+ color: #a8a8a8
+
+ .label
+ color: #8c8c8c
+ display: block
+ font-size: 12px
+ line-height: 14px
+ margin-bottom: 0
+
+ &:hover .label
+ color: #eee
+
+ .value
+ display: block
+ font-size: 18px
+ line-height: 24px
+ overflow: hidden
+ text-overflow: ellipsis
+
+ label
+ display: none
+
+ select
+ border: none
+ cursor: pointer
+ height: 50px
+ left: 0
+ margin: 0
+ opacity: 0
+ position: absolute
+ top: 0
+ z-index: 2
+ width: 100%
+
+ &:hover
+ background: #318ec4
+ background: linear-gradient(#318ec4, #2b7cab)
+ border-color: #2e85b8
+ color: #fff
+
+ .on
+ background-image: none
+ background-color: rgba(255, 255, 255, .3)
+ border-color: transparent
+
+ .icon-sm
+ color: #fff
+
+ &:active
+ background: #2e85b8
+ background: linear-gradient(#2e85b8, #28739f)
+ border-color: #2b7cab
+ color: #fff
+
+ .button-link.negate
+
+ &:hover
+ background: #990f0f
+ background: linear-gradient(#990f0f, #7d0c0c)
+ border-color: @background
+
+ &:active
+ background: #7d0c0c
+ border-color: #990f0f
+
+
+ &.primary
+ background: #48b512
+ background: linear-gradient(#48b512, #3d990f)
+ border: 1px solid
+ border-color: #3d990f
+ color: #fff
+
+ &:hover
+ background: #3d990f
+ background: linear-gradient(#3d990f, #327d0c)
+ border-color: #3d990f
+
+ &.danger
+ background: #ba1212
+ background: linear-gradient(#ba1212, #8b0e0e)
+ border: 1px solid
+ border-color: #a21010
+ color: #fff
+
+ &:hover
+ background: #a21010
+ background: linear-gradient(#a21010, #740b0b)
+ border-color: #8b0e0e
+
+button
+
+ &.quiet-button,
+ &.loud-text-button
+ background: none
+ text-align: left
+ line-height: normal
+ border: none
+ box-shadow: none
+
+ &:active
+ color: #4d4d4d
+ background: #d3d3d3
+ box-shadow: none
+
+ &.quiet-button
+ font-weight: 400
+ text-decoration: underline
+
+ &.loud-text-button
+ width: 100%
+
+ &:hover
+ color: #111
+
+.emphasis-button,
+.quiet-button
+ border-radius: 3px
+ user-select: none
+ color: #8c8c8c
+ display: block
+ margin: 2px 0
+ padding: 6px 8px
+ position: relative
+
+ &.w-img
+ padding-left: 28px
+
+ .icon-sm
+ left: 6px
+ position: absolute
+ top: 6px
+
+ &:hover
+ color: #4d4d4d
+ background: #dcdcdc
+
+ &:active
+ color: #4d4d4d
+ background: #d3d3d3
+
+.quiet-button-large
+ padding: 16px 24px
+
+.emphasis-button
+ color: #74663e
+ background: #ecdfbb
+
+ &:hover
+ color: #53492d
+ background: #e7d6a7
+
+ &:active
+ color: #53492d
+ background: #e1cc93
+
+.big-link
+ border-radius: 3px
+ display: block
+ margin: 6px 0 6px 40px
+ padding: 11px
+ position: relative
+ text-decoration: none
+ font-size: 16px
+ line-height: 20px
+
+ .text
+ text-decoration: underline
+
+ &:hover
+ background: #dcdcdc
+
+ &.options
+ padding-right: 41px
+
+ .option
+ height: 30px
+ width: @height
+ position: absolute
+ right: 6px
+ top: 6px
+
+ &.none
+ color: #8c8c8c
+ text-decoration: none
+
+ &:hover
+ background: transparent
+
+ &.avatar-changer
+ padding-right: 51px
+
+ .member
+ border: 1px solid #ccc
+ border-radius: 3px
+ height: 40px
+ width: @height
+ position: absolute
+ right: 0
+ top: 0
+
+ .member-avatar
+ height: 40px
+ width: @height
+
+ .member-initials
+ font-size: 16px
+ height: 40px
+ line-height: @height
+ max-height: @height
+
+.show-more
+ border-radius: 3px
+ color: #8c8c8c
+ display: block
+ padding: 16px 8px 16px 40px
+ margin: 8px 0
+
+ &:hover
+ background: #dcdcdc
+ text-decoration: underline
+
+ &.compact
+ padding: 12px 8px
+ margin: 8px 0 0
+ text-align: center
+
+.board-widget .show-more
+ padding: 12px 8px 12px 40px
+
+.uploader
+ clear: both
+ cursor: pointer
+ position: relative
+ height: 34px
+ width: 100%
+
+ .realfile
+ cursor: pointer
+ height: 34px
+ line-height: @height
+ position: absolute
+ top: 0
+ left: 0
+ width: 100%
+ z-index: 2
+ font-size: 23px
+
+ input[type="file"]
+ cursor: pointer
+ height: 34px
+ line-height: @height
+ margin: 0
+ opacity: 0
+ padding: 0
+ width: 100%
+ z-index: 2
+ font-size: 23px
+
+ &:hover .fakefile
+ background: #318ec4
+ background: linear-gradient(#318ec4, #2b7cab)
+ border-color: #2e85b8
+ color: #fff
+
+.form-grid
+ display: flex
+ flex-wrap: wrap
+ width: 100%
+
+.form-grid-child
+ flex: 1
+ margin: 0 0 8px
+
+.form-grid-child-full
+ flex: 1 1 100%
+
+.form-grid-child-threequarters
+ flex: 3
+ margin-right: 8px
+
+.form-grid-child-twothirds
+ flex: 2
+ margin-right: 8px
+
+.dropdown-menu
+ border-radius: 2px
+ // padding-bottom: 3px
+ overflow: hidden
+
+ li
+ border-top: none
+
+ a
+ padding: 4px 12px 4px 8px
+
+ img
+ width: 18px
+ height: @width
+ margin-right: 5px
+ vertical-align: middle
+
+ &.active
+ background: #005377
+
+ a
+ color: white
diff --git a/client/components/forms/inlinedform.jade b/client/components/forms/inlinedform.jade
new file mode 100644
index 00000000..5ad9039e
--- /dev/null
+++ b/client/components/forms/inlinedform.jade
@@ -0,0 +1,6 @@
+template(name='inlinedForm')
+ if isOpen.get
+ form(id=id class=classNames)
+ +Template.contentBlock
+ else
+ +Template.elseBlock
diff --git a/client/components/forms/inlinedform.js b/client/components/forms/inlinedform.js
new file mode 100644
index 00000000..2e2b2eba
--- /dev/null
+++ b/client/components/forms/inlinedform.js
@@ -0,0 +1,93 @@
+// A inlined form is used to provide a quick edition of single field for a given
+// document. Clicking on a edit button should display the form to edit the field
+// value. The form can then be submited, or just closed.
+//
+// When the form is closed we save non-submitted values in memory to avoid any
+// data loss.
+//
+// Usage:
+//
+// +inlineForm
+// // the content when the form is open
+// else
+// // the content when the form is close (optional)
+
+// We can only have one inlined form element opened at a time
+// XXX Could we avoid using a global here ? This is used in Mousetrap
+// keyboard.js
+currentlyOpenedForm = new ReactiveVar(null);
+
+BlazeComponent.extendComponent({
+ template: function() {
+ return 'inlinedForm';
+ },
+
+ mixins: function() {
+ return [Mixins.CachedValue];
+ },
+
+ onCreated: function() {
+ this.isOpen = new ReactiveVar(false);
+ },
+
+ open: function() {
+ // Close currently opened form, if any
+ if (currentlyOpenedForm.get() !== null) {
+ currentlyOpenedForm.get().close();
+ }
+ this.isOpen.set(true);
+ currentlyOpenedForm.set(this);
+ },
+
+ close: function() {
+ this.saveValue();
+ this.isOpen.set(false);
+ currentlyOpenedForm.set(null);
+ },
+
+ getValue: function() {
+ return this.isOpen.get() && this.find('textarea,input[type=text]').value;
+ },
+
+ saveValue: function() {
+ this.callFirstWith(this, 'setCache', this.getValue());
+ },
+
+ events: function() {
+ return [{
+ 'click .js-close-inlined-form': this.close,
+ 'click .js-open-inlined-form': this.open,
+
+ // Close the inlined form by pressing escape.
+ //
+ // Keydown (and not keypress) in necessary here because the `keyCode`
+ // property is consistent in all browsers, (there is not keyCode for the
+ // `keypress` event in firefox)
+ 'keydown form input, keydown form textarea': function(evt) {
+ if (evt.keyCode === 27) {
+ evt.preventDefault();
+ this.close();
+ }
+ },
+
+ // Pressing Ctrl+Enter should submit the form
+ 'keydown form textarea': function(evt) {
+ if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
+ $(evt.currentTarget).parents('form:first').submit();
+ }
+ },
+
+ // Close the inlined form when after its submission
+ submit: function() {
+ var self = this;
+ // XXX Swith to an arrow function here when we'll have ES6
+ if (this.currentData().autoclose !== false) {
+ Tracker.afterFlush(function() {
+ self.close();
+ self.callFirstWith(self, 'resetCache');
+ });
+ }
+ }
+ }];
+ }
+}).register('inlinedForm');