From e494018870dcc42b6f6198e1d99a1ecd94fa071e Mon Sep 17 00:00:00 2001 From: Sean Adkinson Date: Wed, 29 Jul 2015 15:20:20 -0700 Subject: [PATCH 1/4] Support static field rendering --- src/index.jsx | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/index.jsx b/src/index.jsx index bd48bc0..f256ce4 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -6,7 +6,8 @@ var cloneWithProps = React.addons.cloneWithProps var { BooleanField, BoundField, CheckboxChoiceInput, CheckboxFieldRenderer, CheckboxSelectMultiple, ChoiceFieldRenderer, FileField, Form, - MultiValueField, MultiWidget, RadioChoiceInput, RadioFieldRenderer, RadioSelect + MultiValueField, MultiWidget, RadioChoiceInput, RadioFieldRenderer, + RadioSelect, Widget } = require('newforms') var SPINNER = 'data:image/gif;base64,R0lGODlhDgAOANU%2FAJ2rtf39%2FfL09a65wvX2993i5qq2v9Ta35CgrLjCyuTo6%2Bfq7aGvub3Hzs7V2vX3%2BI6eq9rf47rEzOvu8NLZ3ens7u7w8sDJ0ODl6MfP1aazvYqbqNDX3Pr7%2FLW%2Fx4iZpomap%2BPn6vHz9Y2dqqSxu%2FT19%2Bjr7tfd4dvg5KOwuvj5%2BeLm6ae0vd%2Fk5%2Fj5%2BvHz9Nbc4Nbc4Y2dqff4%2Bebp7NXb3%2FDy9Iqbp%2BXp7Pv8%2FL%2FIz%2Fn6%2B7nDy%2FDy84%2Bfq%2F%2F%2F%2FyH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FwtYTVAgRGF0YVhNUDw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyNzA4MjZFM0EyRUExMUUzQjE2OUQwNUQ1MzZBQ0M2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyNzA4MjZFNEEyRUExMUUzQjE2OUQwNUQ1MzZBQ0M2NyI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjk2NDkzOTlDQTJBOTExRTNCMTY5RDA1RDUzNkFDQzY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjI3MDgyNkUyQTJFQTExRTNCMTY5RDA1RDUzNkFDQzY3Ii8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2BAf%2F%2B%2Ffz7%2Bvn49%2Fb19PPy8fDv7u3s6%2Brp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M%2FOzczLysnIx8bFxMPCwcC%2Fvr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ%2BenZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8%2BPTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEBQMAPwAsAAAAAA4ADgAABhTAn3BILBqPyKRyyWw6n9CodGoMAgAh%2BQQFAwA%2FACwHAAAAAQADAAAGBcCOrRMEACH5BAUDAD8ALAcAAAABAAMAAAYFwNKhFAQAIfkEBQMAPwAsBwAAAAEAAwAABgXABQkXBAAh%2BQQFAwA%2FACwHAAAAAgADAAAGB8DQ7FOLPYIAIfkEBQMAPwAsBwAAAAMAAwAABgrAX%2Bn3%2B0xOmV8QACH5BAUDAD8ALAcAAAAEAAMAAAYLQMxvOCSJfjpNIAgAIfkEBQMAPwAsBwAAAAUABAAABg%2FA0G9I%2FCmGDR%2BoMiRQfkEAIfkEBQMAPwAsBwAAAAYABQAABhNAzG9IHIaGNcnQQXwwPotm7RcEACH5BAUDAD8ALAcAAAAHAAYAAAYVwNVvSCwSTw3ExzgECYkEBMOYMXSCACH5BAUDAD8ALAcAAAAHAAgAAAYcwNBvSCQqij8fiFMkDIXIFPLyERRRn1axl1gEAQAh%2BQQFAwA%2FACwLAAcAAwADAAAGCsDIB3P5CFCeXxAAIfkEBQMAPwAsCgAHAAQABQAABhHAn7Al%2FIkeiNTP8An9MA5hEAAh%2BQQFAwA%2FACwIAAMABgAKAAAGHMCf8LcaGo9II%2BpXOL6MDCGBASrWEKBhjRQaBgEAIfkEBQMAPwAsBgAAAAgADgAABirA3%2BRHLP4YxJCxYGw6i4%2BndEpsPQVGwi%2F1VE5ODd%2BPQxx8Pj9FsRIqNYMAIfkECQMAPwAsAwAAAAkADgAABiLAn%2FA3Gxp%2FjuNw8kMgldAhIUqtWq%2FKC692DLA%2BHyhhdQwCACH5BAkDAD8ALAAAAAAOAA4AAAZGwJ9wKOwQj0QGKYQ8XnwgR5NIYHymxAeCgR1efqLuDyUWkstfYgBJQBAdgPCwCiLWQBAJ7NSAco4VBh%2BDHyQKUw8KISVHQQAh%2BQQJAwA%2FACwAAAAADgAOAAAGUcCfcEgsGn%2BBQehItCBADubwwQCtpMIHgoEVXj6vLupTEH9aP1OE%2BRX8DCORkYBICU0bgHtIqC6FNRsQEicnDT4gHEULGh%2BOHyQKTA8hISVFQQAh%2BQQJAwA%2FACwAAAAADgAOAAAGVsCfcEgsGoe9Y1EBciiHDwYI8xSWEIyqUPexBVQBZeRTWHwoStSn5QIllJeP4GeQvYwEREpY2QBERARSIUMwGyMSMScNPiAcRSYsH5MfJApKDwohJUVBACH5BAkDAD8ALAAAAAAOAA4AAAZRwJ9wSCwaj8ghLTl0gFbMHwGR%2Bs0GCuTlI8B9DkjUp7X4UMJjFyih5f4MspdxWv1VNgARkcAAhYYwGyMSMScNPiAcRSYsH44fJFlHDwohJUVBACH5BAkDAD8ALAAAAAAOAA4AAAZVwJ9wSCwaj8gjIZBk%2FlgaZCb1m30kSN3HhvvUkJFPYfGhIFGflguUQF4%2Bgp9B9jISENRfZQMQEQkMICFDMBsjEjEnDT4gHEUmLB%2BSHyQKSA8KISVFQQAh%2BQQJAwA%2FACwAAAAADgAOAAAGUcCfcEgsGo%2FCCZJo2nCWQsNIBHWBeEvLjvY5IAuf1uJDQaLC1gTy8hH8DLKXkYBICSsbAHVIYIBCQzAbIxIxJw0%2BIE9MLB%2BOHyQKSA8KISVFQQAh%2BQQJAwA%2FACwAAAAADgAOAAAGU8CfcEgsCnNGYw3gSg5NG0DJKWSNetTf7JPI%2FhQfincRdgoUOReom7x8BD%2BD7GV8IBjCSlREJDA%2BIUMwGyMSMScNPiAORSYsH5AfKYFJDwohU0RBACH5BAkDAD8ALAAAAAAOAA4AAAZPwJ9wSCwKFyhjsXYDKIemDUDwFLJG1Orsw6sKcZ%2BD97f4UMYuUGL8M8hexkemI6xIRcQHA7QawjYjEjE1Ej4gDkUmLB%2BMHyQhTw8KGCVFQQAh%2BQQJAwA%2FACwAAAAADgAOAAAGSsCfcEgsChcajJFY20BOS6FpAxBEhYaR6PqbfXjcH%2B5zCC8%2BlLALlAj%2FDLJXuELdDh%2BBImwzksRODQgNRiYsH4cfJCFRDworJUVBACH5BAkDAD8ALAAAAAAOAA4AAAZGwJ9Q2BkajQsN4nisbUaSAFNougEE06FhJMoKZyCeV0j7HMa%2FxYeCdoES6J9B9kJXNoDuGPaUxGA2WSYsH4UZYw8KGARHQQAh%2BQQJAwA%2FACwAAAAADgAOAAAGPMCfUPhQDY%2FDBetzQB5rN4hk4hRWNgBBdWgYibZCFYgHFtKY5d%2B5WRaT091v%2BQqQg6HSV1n5MaV%2FDwFVQQAh%2BQQJAwA%2FACwAAAAADgAOAAAGPMCfUPiwDI%2FDBetjQB5rG4ik5RSaNgBRdWgYabc%2FF4gHFtI%2Bh%2FIP96GoZ5%2BE%2Bsca9dQLrEBdA6HmRnNqQQAh%2BQQJAwA%2FACwAAAAADgAOAAAGN8CfUPgwDY9DE%2BvjQx5jm5Ek4hSaNgBRdWiQvbZCF4gHFtI%2Bh%2FIPh1bPPmS1YURQmxzqvH4%2FDAIAIfkECQMAPwAsAAAAAA4ADgAABjXAn1D4UASGSKGJ9fmokkPYZiSJHaGmDUAERRpkr%2B7QBeKJh4sP5SzEfWrs38yziNvv%2BLw%2BCAAh%2BQQJAwA%2FACwAAAAADgAOAAAGL8CfUPhQBIZIoYn1%2BaiSQ9hmJIkdoaYNQARFGmTcrlAF4omHFhLqzG673%2FC4%2FBwEACH5BAkDAD8ALAAAAAAOAA4AAAYqwJ9Q%2BAgFhkjhQvP5qJLD2gYiOR2hpg1AAEUaRqIu8rESm8%2FotHrNbrODACH5BAkDAD8ALAAAAAAOAA4AAAYowJ9QSFgFhkghTfP5qJLD2g3Cqx2hOQDABk3uSt2weEwum8%2FotBoZBAAh%2BQQJAwA%2FACwAAAAADgAOAAAGI8CfUEgIBYZI4ULz%2BaiSwx1iJDkdoUKTCMvter%2FgsHhMLpeDACH5BAkDAD8ALAAAAAAOAA4AAAYgwJ9QSFgFhkihSvP5qJLJAe9whFqv2Kx2y%2B16v%2BDwMAgAIfkECQMAPwAsAAAAAA4ADgAABh7An1BICAWGyKHl81Eln5nT8UmtWq%2FYrHbL7Xq%2FwyAAIfkECQMAPwAsAAAAAA4ADgAABh3An1D4WAWGSCTno0o6S7Wjc0qtWq%2FYrHbL7XqHQQAh%2BQQFAwA%2FACwAAAAADgAOAAAGGsCfcIgLDI9IgArJ%2FBWb0Kh0Sq1ar9isVhoEACH5BAUDAD8ALAYAAAABAAMAAAYFQAFHEAQAIfkECQMAPwAsBgAAAAEAAwAABgXAnK0TBAAh%2BQQJAwA%2FACwAAAAADgAOAAAGFMCfcEgsGo%2FIpHLJbDqf0Kh0agwCACH5BAUDAD8ALAAAAAAOAA4AAAYUwJ9wSCwaj8ikcslsOp%2FQqHRqDAIAIfkEBQMAPwAsAAAAAAEAAQAABgPAXxAAIfkEBQMAPwAsAAAAAAEAAQAABgPAXxAAIfkEBQMAPwAsAAAAAAEAAQAABgPAXxAAIfkEBQMAPwAsAAAAAAEAAQAABgPAXxAAOw%3D%3D' @@ -150,6 +151,19 @@ var BootstrapRadioInlineRenderer = RadioFieldRenderer.extend({ } }) +var BootstrapStaticWidget = Widget.extend({ + constructor: function BootstrapStaticWidget(kwargs) { + if (!(this instanceof BootstrapStaticWidget)) { return new BootstrapStaticWidget(kwargs) } + this.convertStatic = kwargs && kwargs.convertStatic || ((value) => value); + Widget.call(this, kwargs) + }, + render(name, value, kwargs) { + return ( +

{this.convertStatic(value)}

+ ) + } +}) + // ========================================================= Form Components === var BootstrapForm = React.createClass({ @@ -186,7 +200,8 @@ var BootstrapForm = React.createClass({ propTypes: { form: React.PropTypes.instanceOf(Form).isRequired, - spinner: React.PropTypes.string + spinner: React.PropTypes.string, + static: React.PropTypes.bool }, getDefaultProps() { @@ -212,7 +227,7 @@ var BootstrapForm = React.createClass({ ) } rows.push.apply(rows, form.visibleFields().map(field => - + )) var hiddenFields = form.hiddenFields() if (hiddenFields.length > 0) { @@ -233,6 +248,7 @@ var BootstrapField = React.createClass({ propTypes: { field: React.PropTypes.instanceOf(BoundField).isRequired , spinner: React.PropTypes.string + , static: React.PropTypes.bool }, getDefaultProps() { @@ -258,6 +274,9 @@ var BootstrapField = React.createClass({ !(field.field.widget instanceof RadioSelect) && !(field.field.widget instanceof CheckboxSelectMultiple) })}} + if (this.props.static) { + widgetAttrs.widget = field.field.widgetAttrs.staticWidget || BootstrapStaticWidget(field.field.widgetAttrs) + } // Always show help text for empty fields, regardless of status var showHelpText = field.helpText && (field.isEmpty() || status == 'default') @@ -414,13 +433,12 @@ var Container = React.createClass({ , className: React.PropTypes.string , fluid: React.PropTypes.bool , spinner: React.PropTypes.string + , static: React.PropTypes.bool }, getDefaultProps() { return { - autoColumns: null - , fluid: false - , spinner: SPINNER + spinner: SPINNER } }, @@ -433,10 +451,9 @@ var Container = React.createClass({ {formErrors.messages().map(errorMessage)} } {React.Children.map(this.props.children, (row, index) => cloneWithProps(row, { - autoColumns: this.props.autoColumns - , form: this.props.form + ...this.props , index: index - , spinner: this.props.spinner + , className: null // Don't propagate className }))} {form.nonFieldPending() && Validating… @@ -449,6 +466,7 @@ var Row = React.createClass({ propTypes: { autoColumns: React.PropTypes.oneOf(BOOTSTRAP_COLUMN_SIZES) , className: React.PropTypes.string + , static: React.PropTypes.bool }, render() { @@ -466,8 +484,8 @@ var Row = React.createClass({ return
{React.Children.map(this.props.children, (child, index) => { return cloneWithProps(child, extend({ - form: this.props.form - , spinner: this.props.spinner + ...this.props + , className: null // Don't propagate className }, columnProps[index])) })}
@@ -489,12 +507,13 @@ var Field = React.createClass({ propTypes: { name: React.PropTypes.string.isRequired + , static: React.PropTypes.bool }, render() { var field = this.props.form.boundField(this.props.name) return
- +
} }) From 9a9f07ca2020e3ee47cbb1bc0268aed570766720 Mon Sep 17 00:00:00 2001 From: Sean Adkinson Date: Wed, 29 Jul 2015 15:28:04 -0700 Subject: [PATCH 2/4] Docs --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index be62acd..7d2c962 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,21 @@ first grid layout example above: ![spinner](https://github.com/insin/newforms-bootstrap/raw/master/spinner.gif "Default async validation spinner") +* `static` - set to `true` to render fields using a static display control: `

{value}

` + + Provide a `widgetAttrs.convertStatic` function on a field to convert the value when displaying statically. The following + would render a cost value with a dollar sign in front when `static=true`, but would otherwise just render an integer field: + + ```javascript + var ProductForm = forms.Form.extend({ + cost: forms.IntegerField({ + widgetAttrs: { + convertStatic: (value) => '$' + value + } + }) + }) + ``` + ### Bootstrap-compatible choice field renderers The following custom renderers are available for use. Note that the non-inline From 42959c82d81215aa69ac45c42862fd509595428c Mon Sep 17 00:00:00 2001 From: Sean Adkinson Date: Wed, 29 Jul 2015 18:09:56 -0700 Subject: [PATCH 3/4] Horizontal forms --- README.md | 35 +++++++ newforms-bootstrap.iml | 8 ++ npm-debug.log | 27 ++++++ src/index.jsx | 214 +++++++++++++++++++++++++++++++++-------- 4 files changed, 244 insertions(+), 40 deletions(-) create mode 100644 newforms-bootstrap.iml create mode 100644 npm-debug.log diff --git a/README.md b/README.md index 7d2c962..c6d26f8 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,12 @@ first grid layout example above: ![spinner](https://github.com/insin/newforms-bootstrap/raw/master/spinner.gif "Default async validation spinner") * `static` - set to `true` to render fields using a static display control: `

{value}

` + + This is useful if you want to have readonly forms, and switch to editable given a flag: + + ```html + + ``` Provide a `widgetAttrs.convertStatic` function on a field to convert the value when displaying statically. The following would render a cost value with a dollar sign in front when `static=true`, but would otherwise just render an integer field: @@ -190,6 +196,35 @@ first grid layout example above: }) ``` +* `horizontal` - An object for specifying `form-horizontal` classes. Keys are one of the bootstrap + sizes (xs, sm, md, lg), and values are the number given to the form control. + + So for example: + + ```html + + ``` + + This would produce fields such as: + + ```html +
+ +
+ +
+
+
+
+
+ +
+
+
+ ``` + ### Bootstrap-compatible choice field renderers The following custom renderers are available for use. Note that the non-inline diff --git a/newforms-bootstrap.iml b/newforms-bootstrap.iml new file mode 100644 index 0000000..80cc739 --- /dev/null +++ b/newforms-bootstrap.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/npm-debug.log b/npm-debug.log new file mode 100644 index 0000000..e25bbfd --- /dev/null +++ b/npm-debug.log @@ -0,0 +1,27 @@ +0 info it worked if it ends with ok +1 verbose cli [ 'node', '/usr/local/bin/npm', 'run', 'dist' ] +2 info using npm@1.4.28 +3 info using node@v0.10.38 +4 verbose node symlink /usr/local/bin/node +5 verbose run-script [ 'predist', 'dist', 'postdist' ] +6 info predist newforms-bootstrap@1.1.1 +7 info dist newforms-bootstrap@1.1.1 +8 verbose unsafe-perm in lifecycle true +9 info newforms-bootstrap@1.1.1 Failed to exec dist script +10 error newforms-bootstrap@1.1.1 dist: `gulp bundle-js --production --release && gulp bundle-js --development --release` +10 error Exit status 127 +11 error Failed at the newforms-bootstrap@1.1.1 dist script. +11 error This is most likely a problem with the newforms-bootstrap package, +11 error not with npm itself. +11 error Tell the author that this fails on your system: +11 error gulp bundle-js --production --release && gulp bundle-js --development --release +11 error You can get their info via: +11 error npm owner ls newforms-bootstrap +11 error There is likely additional logging output above. +12 error System Darwin 14.4.0 +13 error command "node" "/usr/local/bin/npm" "run" "dist" +14 error cwd /Users/seanadkinson/code/newforms-bootstrap +15 error node -v v0.10.38 +16 error npm -v 1.4.28 +17 error code ELIFECYCLE +18 verbose exit [ 1, true ] diff --git a/src/index.jsx b/src/index.jsx index f256ce4..2bb51a9 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -166,6 +166,13 @@ var BootstrapStaticWidget = Widget.extend({ // ========================================================= Form Components === +var HorizontalPropType = React.PropTypes.shape({ + xs: React.PropTypes.number, + sm: React.PropTypes.number, + md: React.PropTypes.number, + lg: React.PropTypes.number +}); + var BootstrapForm = React.createClass({ statics: { patchFields(form) { @@ -201,7 +208,8 @@ var BootstrapForm = React.createClass({ propTypes: { form: React.PropTypes.instanceOf(Form).isRequired, spinner: React.PropTypes.string, - static: React.PropTypes.bool + static: React.PropTypes.bool, + horizontal: HorizontalPropType }, getDefaultProps() { @@ -246,57 +254,180 @@ var BootstrapForm = React.createClass({ var BootstrapField = React.createClass({ propTypes: { - field: React.PropTypes.instanceOf(BoundField).isRequired - , spinner: React.PropTypes.string - , static: React.PropTypes.bool + field: React.PropTypes.instanceOf(BoundField).isRequired, + spinner: React.PropTypes.string, + static: React.PropTypes.bool, + horizontal: HorizontalPropType }, getDefaultProps() { return { - spinner: SPINNER - } + spinner: SPINNER, + horizontal: {} + }; }, render() { - var field = this.props.field - var status = field.status() - var isBooleanField = field.field.constructor === BooleanField - var isFileField = field.field instanceof FileField - var isSpecialCaseWidget = isBooleanField || isFileField - var containerClasses = cx({ - 'checkbox': isBooleanField - , 'form-group': !isBooleanField - , 'has-error': status == 'error' - , 'has-success': status == 'valid' - }) - var widgetAttrs = {attrs: {className: cx({ - 'form-control': !isFileField && - !(field.field.widget instanceof RadioSelect) && - !(field.field.widget instanceof CheckboxSelectMultiple) - })}} + var field = this.props.field; + var status = field.status(); + + return ( +
+ {this.getControlWithLabel(field, status)} + {this.getHelpText(field, status)} + {this.getSpinner(status)} + {this.getError(status)} +
+ ); + }, + + getContainerClasses(field, status) { + var isBooleanField = this.isBooleanField(field); + var isHorizontal = this.isHorizontalForm(); + return cx({ + 'checkbox': !isHorizontal && isBooleanField, + 'form-group': isHorizontal || !isBooleanField, + 'has-error': status == 'error', + 'has-success': status == 'valid' + }); + }, + + isBooleanField(field) { + return field.field.constructor === BooleanField; + }, + + isFileField(field) { + return field.field instanceof FileField; + }, + + isRadioSelect(field) { + return field.field.widget instanceof RadioSelect; + }, + + isCheckboxSelectMultipleField(field) { + return field.field.widget instanceof CheckboxSelectMultiple; + }, + + getControlWithLabel(field) { + + if (this.isBooleanField(field)) { + var checkbox = ( + + ); + + if (!this.isHorizontalForm()) { + return checkbox; + } + + return ( +
+
+ {checkbox} +
+
+ ); + } + + if (this.isFileField(field)) { + return ( +
+ {field.labelTag({attrs: {className: 'control-label ' + this.getHorizontalLabelClasses()}})} +
+ {field.asWidget(this.getWidgetAttrs(field))} +
+
+ ); + } + + return ( +
+ {field.labelTag({attrs: {className: 'control-label ' + this.getHorizontalLabelClasses()}})} +
+ {field.asWidget(this.getWidgetAttrs(field))} +
+
+ ); + }, + + getWidgetAttrs(field) { + var widgetAttrs = { + attrs: { + className: cx({ + 'form-control': !this.isFileField(field) + && !this.isRadioSelect(field) + && !this.isCheckboxSelectMultipleField(field) + }) + } + }; + if (this.props.static) { widgetAttrs.widget = field.field.widgetAttrs.staticWidget || BootstrapStaticWidget(field.field.widgetAttrs) } + + return widgetAttrs; + }, + + getHelpText(field, status) { + // Always show help text for empty fields, regardless of status - var showHelpText = field.helpText && (field.isEmpty() || status == 'default') - - return
- {!isBooleanField && field.labelTag({attrs: {className: 'control-label'}})} - {!isSpecialCaseWidget && field.asWidget(widgetAttrs)} - {isBooleanField && } - {isFileField &&
- {field.asWidget(widgetAttrs)} -
} - {showHelpText && field.helpTextTag({attrs: {className: 'help-block'}})} - {status == 'pending' && - Validating… - } - {status == 'error' && field.errors().messages().map(errorMessage)} -
+ var showHelpText = field.helpText && (field.isEmpty() || status == 'default'); + + return showHelpText && field.helpTextTag({attrs: {className: 'help-block'}}); + }, + + getSpinner(status) { + if (status == 'pending') { + return ( + + Validating… + + ); + } + }, + + getError(status) { + if (status == 'error') { + return field.errors().messages().map(errorMessage); + } + }, + + isHorizontalForm() { + return this.props.horizontal.length > 0; + }, + + getHorizontalLabelClasses() { + var classes = []; + var h = this.props.horizontal; + + for (var size in h) { + if (h.hasOwnProperty(size)) { + classes.push(`col-${size}-${12-h[size]}`); + } + } + + return classes.join(' '); + }, + + getHorizontalControlClasses(field) { + var classes = []; + var isBooleanField = this.isBooleanField(field); + var h = this.props.horizontal; + + for (var size in h) { + if (h.hasOwnProperty(size)) { + classes.push(`col-${size}-${h[size]}`); + if (isBooleanField) { + classes.push(`col-${size}-offset-${12-h[size]}`); + } + } + } + + return classes.join(' '); } -}) + +}); // ========================================================= Grid Components === @@ -434,6 +565,7 @@ var Container = React.createClass({ , fluid: React.PropTypes.bool , spinner: React.PropTypes.string , static: React.PropTypes.bool + , horizontal: HorizontalPropType }, getDefaultProps() { @@ -467,6 +599,7 @@ var Row = React.createClass({ autoColumns: React.PropTypes.oneOf(BOOTSTRAP_COLUMN_SIZES) , className: React.PropTypes.string , static: React.PropTypes.bool + , horizontal: HorizontalPropType }, render() { @@ -508,6 +641,7 @@ var Field = React.createClass({ propTypes: { name: React.PropTypes.string.isRequired , static: React.PropTypes.bool + , horizontal: HorizontalPropType }, render() { From 504b0b15d7578cd03191355465e14c3df296b701 Mon Sep 17 00:00:00 2001 From: Sean Adkinson Date: Wed, 29 Jul 2015 18:11:15 -0700 Subject: [PATCH 4/4] Deleting files that shouldnt be there --- newforms-bootstrap.iml | 8 -------- npm-debug.log | 27 --------------------------- 2 files changed, 35 deletions(-) delete mode 100644 newforms-bootstrap.iml delete mode 100644 npm-debug.log diff --git a/newforms-bootstrap.iml b/newforms-bootstrap.iml deleted file mode 100644 index 80cc739..0000000 --- a/newforms-bootstrap.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/npm-debug.log b/npm-debug.log deleted file mode 100644 index e25bbfd..0000000 --- a/npm-debug.log +++ /dev/null @@ -1,27 +0,0 @@ -0 info it worked if it ends with ok -1 verbose cli [ 'node', '/usr/local/bin/npm', 'run', 'dist' ] -2 info using npm@1.4.28 -3 info using node@v0.10.38 -4 verbose node symlink /usr/local/bin/node -5 verbose run-script [ 'predist', 'dist', 'postdist' ] -6 info predist newforms-bootstrap@1.1.1 -7 info dist newforms-bootstrap@1.1.1 -8 verbose unsafe-perm in lifecycle true -9 info newforms-bootstrap@1.1.1 Failed to exec dist script -10 error newforms-bootstrap@1.1.1 dist: `gulp bundle-js --production --release && gulp bundle-js --development --release` -10 error Exit status 127 -11 error Failed at the newforms-bootstrap@1.1.1 dist script. -11 error This is most likely a problem with the newforms-bootstrap package, -11 error not with npm itself. -11 error Tell the author that this fails on your system: -11 error gulp bundle-js --production --release && gulp bundle-js --development --release -11 error You can get their info via: -11 error npm owner ls newforms-bootstrap -11 error There is likely additional logging output above. -12 error System Darwin 14.4.0 -13 error command "node" "/usr/local/bin/npm" "run" "dist" -14 error cwd /Users/seanadkinson/code/newforms-bootstrap -15 error node -v v0.10.38 -16 error npm -v 1.4.28 -17 error code ELIFECYCLE -18 verbose exit [ 1, true ]