Skip to content

Commit

Permalink
fix: column resizing
Browse files Browse the repository at this point in the history
feat: disable form action buttons
  • Loading branch information
kevinchappell committed Mar 8, 2020
1 parent df59eae commit 9c8a800
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 63 deletions.
18 changes: 10 additions & 8 deletions docs/options/controls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

Control options can be used to disable, extend and modify the Formeo's control panel.

| Option | Type | Description | Example | Default |
| ----------------------------- | ------ | ----------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------ |
| [sortable](#sortable) | String | allow controls to be reordered by users | `true` | `false` |
| [disable](#disable) | Object | disable built-in elements or groups | `{elements: ['number']}` | `{}` |
| [elements](#elements) | Array | define custom elements | [see below](#elements) | `[]` |
| [elementOrder](#elementOrder) | Object | set order of elements in a group | `{html: ['header', 'paragraph', 'divider']}` | `[]` |
| [groups](#groups) | Array | define custom [control groups](../../controls/#control-groups) beyond the default 3 | [see below](#groups) | `[]` |
| [groupOrder](#groupOrder) | Array | set order of [control groups](../../controls/#control-groups) | `['html', 'layout']` | `['common', 'html', 'layout']` |
| Option | Type | Description | Example | Default |
| ----------------------------- | ------- | ----------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------ |
| [sortable](#sortable) | String | allow controls to be reordered by users | `true` | `false` |
| [disable](#disable) | Object | disable built-in elements or groups | `{elements: ['number']}` | `{}` |
| [elements](#elements) | Array | define custom elements | [see below](#elements) | `[]` |
| [elementOrder](#elementOrder) | Object | set order of elements in a group | `{html: ['header', 'paragraph', 'divider']}` | `[]` |
| [groups](#groups) | Array | define custom [control groups](../../controls/#control-groups) beyond the default 3 | [see below](#groups) | `[]` |
| [groupOrder](#groupOrder) | Array | set order of [control groups](../../controls/#control-groups) | `['html', 'layout']` | `['common', 'html', 'layout']` |
| [ghostPreview](#ghostPreview) | Boolean | use a live preview of the control when dragging | `true` | `false` |

## sortable

Expand All @@ -34,6 +35,7 @@ const controlOptions = {
disable: {
elements: ['number'],
groups: ['layout'],
formActions: true, // cancel and save buttons will not be shown
},
}

Expand Down
6 changes: 3 additions & 3 deletions src/js/common/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
FIELD_CLASSNAME,
CONTROL_GROUP_CLASSNAME,
CHILD_CLASSNAME_MAP,
bsColRegExp,
} from '../constants'

/**
Expand Down Expand Up @@ -110,7 +111,7 @@ class DOM {
element.innerHTML += children
},
object: children => {
return element.appendChild(_this.create(children, isPreview))
return children && element.appendChild(_this.create(children, isPreview))
},
node: children => {
return element.appendChild(children)
Expand Down Expand Up @@ -765,9 +766,8 @@ class DOM {
return
}
const width = parseFloat((100 / columns.length).toFixed(1)) / 1
const bsGridRegEx = /\bcol-\w+-\d+/g

this.removeClasses(columns, bsGridRegEx)
this.removeClasses(columns, bsColRegExp)
h.forEach(columns, column => {
Columns.get(column.id).refreshFieldPanels()

Expand Down
2 changes: 0 additions & 2 deletions src/js/common/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import lodashGet from 'lodash/get'
import lodashCamelCase from 'lodash/camelCase'
import lodashLowerCase from 'lodash/lowerCase'

export const bsGridRegEx = /\bcol-\w+-\d+/g

/**
* Tests if is whole number. returns false if n is Float
* @param {String|Number} n
Expand Down
3 changes: 1 addition & 2 deletions src/js/components/columns/column.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ const DOM_CONFIGS = {
resizeHandle: () => ({
className: 'resize-x-handle',
action: {
mousedown: resize,
touchstart: resize,
pointerdown: resize,
},
content: [dom.icon('triangle-down'), dom.icon('triangle-up')],
}),
Expand Down
76 changes: 38 additions & 38 deletions src/js/components/columns/events.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import dom from '../../common/dom'
import Components from '..'
import { percent, numToPercent } from '../../common/utils'
import { ROW_CLASSNAME } from '../../constants'
import { ROW_CLASSNAME, bsColRegExp } from '../../constants'
import { map } from '../../common/helpers'

const CUSTOM_COLUMN_OPTION_CLASSNAME = 'custom-column-widths'
const COLUMN_PRESET_CLASSNAME = 'column-preset'
const COLUMN_RESIZE_CLASSNAME = 'resizing-columns'

/**
* Handle column resizing
Expand All @@ -18,74 +19,73 @@ export function resize(evt) {
const row = column.closest(`.${ROW_CLASSNAME}`)
const rowStyle = dom.getStyle(row)
const rowPadding = parseFloat(rowStyle.paddingLeft) + parseFloat(rowStyle.paddingRight)
evt.target.removeEventListener('pointerdown', resize)

/**
* Set the width before resizing so the column
* does not resize near window edges
* @param {Object} evt
*/
resize.move = evt => {
let clientX
if (evt.type === 'touchmove') {
clientX = evt.touches[0].clientX
} else {
clientX = evt.clientX
resize.move = ({ touches, type, clientX }) => {
if (type === 'touchmove') {
const [firstTouch] = touches
clientX = firstTouch.clientX
}
const newColWidth = resize.colStartWidth + clientX - resize.startX
const newSibWidth = resize.sibStartWidth - clientX + resize.startX

const colWidthPercent = parseFloat(percent(newColWidth, resize.rowWidth))
const sibWidthPercent = parseFloat(percent(newSibWidth, resize.rowWidth))

column.dataset.colWidth = numToPercent(colWidthPercent.toFixed(1))
sibling.dataset.colWidth = numToPercent(sibWidthPercent.toFixed(1))
const colWidth = numToPercent(colWidthPercent.toFixed(1))
const siblingColWidth = numToPercent(sibWidthPercent.toFixed(1))

column.style.width = numToPercent(colWidthPercent)
sibling.style.width = numToPercent(sibWidthPercent)
column.dataset.colWidth = colWidth
sibling.dataset.colWidth = siblingColWidth
column.style.width = colWidth
sibling.style.width = siblingColWidth
resize.resized = true
}

resize.stop = function() {
window.removeEventListener('mousemove', resize.move)
window.removeEventListener('mouseup', resize.stop)
window.removeEventListener('pointermove', resize.move)
window.removeEventListener('pointerup', resize.stop)
window.removeEventListener('touchmove', resize.move)
window.removeEventListener('touchend', resize.stop)
if (!resize.resized) {
return
}

setCustomWidthValue(row, resize.rowWidth)
row.classList.remove('resizing-columns')
row.classList.remove(COLUMN_RESIZE_CLASSNAME)

Components.setAddress(`columns.${column.id}.config.width`, column.dataset.colWidth)
Components.setAddress(`columns.${sibling.id}.config.width`, sibling.dataset.colWidth)
resize.resized = false
}

resize.start = (function(evt) {
if (evt.type === 'touchstart') {
resize.startX = evt.touches[0].clientX
} else {
resize.startX = evt.clientX
}
row.classList.add('resizing-columns')

// remove bootstrap column classes since we are custom sizing
const reg = /\bcol-\w+-\d+/g
column.className.replace(reg, '')
sibling.className.replace(reg, '')

// eslint-disable-next-line
resize.colStartWidth = column.offsetWidth || dom.getStyle(column, 'width')
// eslint-disable-next-line
resize.sibStartWidth = sibling.offsetWidth || dom.getStyle(sibling, 'width')
resize.rowWidth = row.offsetWidth - rowPadding // compensate for padding

window.addEventListener('mouseup', resize.stop, false)
window.addEventListener('mousemove', resize.move, false)
window.addEventListener('touchend', resize.stop, false)
window.addEventListener('touchmove', resize.move, false)
})(evt)
if (evt.type === 'touchstart') {
const [firstTouch] = evt.touches
resize.startX = firstTouch.clientX
} else {
resize.startX = evt.clientX
}
row.classList.add(COLUMN_RESIZE_CLASSNAME)

// remove bootstrap column classes since we are custom sizing
column.className.replace(bsColRegExp, '')
sibling.className.replace(bsColRegExp, '')

// eslint-disable-next-line
resize.colStartWidth = column.offsetWidth || dom.getStyle(column, 'width')
// eslint-disable-next-line
resize.sibStartWidth = sibling.offsetWidth || dom.getStyle(sibling, 'width')
resize.rowWidth = row.offsetWidth - rowPadding // compensate for padding

window.addEventListener('pointerup', resize.stop, false)
window.addEventListener('pointermove', resize.move, false)
window.addEventListener('touchend', resize.stop, false)
window.addEventListener('touchmove', resize.move, false)
}

/**
Expand Down
18 changes: 11 additions & 7 deletions src/js/components/controls/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ export class Controls {
* @return {Object} form action buttons config
*/
formActions() {
if (this.options.disable.formActions === true) {
return null
}
const clearBtn = {
...dom.btnTemplate({ content: [dom.icon('bin'), i18n.get('clear')], title: i18n.get('clearAll') }),
className: ['clear-form'],
Expand Down Expand Up @@ -227,9 +230,15 @@ export class Controls {
},
},
}

const formActions = {
className: 'form-actions f-btn-group',
content: [clearBtn, saveBtn],
content: Object.entries({ clearBtn, saveBtn }).reduce((acc, [key, value]) => {
if (!this.options.disable.formActions.includes(key)) {
acc.push(value)
}
return acc
}, []),
}

return formActions
Expand All @@ -255,14 +264,9 @@ export class Controls {
controlClass += ' formeo-sticky'
}

const content = [groupsWrap]
if (!this.options.disable.formActions) {
content.push(formActions)
}

const element = dom.create({
className: controlClass,
content,
content: [groupsWrap, formActions],
})
const groups = element.getElementsByClassName('control-group')

Expand Down
31 changes: 31 additions & 0 deletions src/js/components/controls/options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const defaultOptions = Object.freeze({
sortable: true,
elementOrder: {},
groupOrder: [],
groups: [
{
id: 'layout',
label: 'controls.groups.layout',
elementOrder: ['row', 'column'],
},
{
id: 'common',
label: 'controls.groups.form',
elementOrder: ['button', 'checkbox'],
},
{
id: 'html',
label: 'controls.groups.html',
elementOrder: ['header', 'block-text'],
},
],
disable: {
groups: [],
elements: [],
formActions: true,
},
elements: [],
container: null,
})

export default defaultOptions
5 changes: 2 additions & 3 deletions src/js/components/rows/row.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import Sortable from 'sortablejs'
import Component from '../component'
import dom from '../../common/dom'
import events from '../../common/events'
import { bsGridRegEx } from '../../common/helpers'
import { numToPercent } from '../../common/utils'
import { ROW_CLASSNAME, COLUMN_TEMPLATES, ANIMATION_SPEED_FAST, COLUMN_CLASSNAME } from '../../constants'
import { ROW_CLASSNAME, COLUMN_TEMPLATES, ANIMATION_SPEED_FAST, COLUMN_CLASSNAME, bsColRegExp } from '../../constants'
import { removeCustomOption } from '../columns/events'

const DEFAULT_DATA = () =>
Expand Down Expand Up @@ -187,7 +186,7 @@ export default class Row extends Component {
const width = parseFloat((100 / columns.length).toFixed(1)) / 1

columns.forEach(column => {
column.removeClasses(bsGridRegEx)
column.removeClasses(bsColRegExp)
const colDom = column.dom
const newColWidth = numToPercent(width)

Expand Down
2 changes: 2 additions & 0 deletions src/js/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,5 @@ export const CONDITION_TEMPLATE = () => ({
})

export const UUID_REGEXP = /(\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b)/gi

export const bsColRegExp = /\bcol-\w+-\d+/g

0 comments on commit 9c8a800

Please sign in to comment.