react-material-editlabel
Version:
React component - label with edit mode after click
229 lines (167 loc) • 9.58 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _TextField = require('material-ui/TextField');
var _TextField2 = _interopRequireDefault(_TextField);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/**
@author Maciej Sikora
Class creates element with two states - label, and TextField in edit mode
**/
var EditLabel = function (_Component) {
_inherits(EditLabel, _Component);
//edition on double click
function EditLabel(props) {
_classCallCheck(this, EditLabel);
var _this = _possibleConstructorReturn(this, (EditLabel.__proto__ || Object.getPrototypeOf(EditLabel)).call(this, props));
_this.bodyClickEvent = null; //click event on page body
_this.changeDeffer = null;
_this.state = {
edit: false, //edit mode
value: _this.props.defValue
};
_this.lastValue = _this.props.defValue;
return _this;
}
//input value change handler
//edition on single click
_createClass(EditLabel, [{
key: 'handleChange',
value: function handleChange(e) {
var _this2 = this;
this.setState({ value: e.target.value });
//deffer to less saving in network
if (this.changeDeffer != null) clearTimeout(this.changeDeffer);
this.changeDeffer = setTimeout(function () {
if (_this2.props.onChange !== null) _this2.props.onChange(_this2.state.value, _this2.props.id);
}, 400);
}
}, {
key: 'cancelEditMode',
value: function cancelEditMode() {
//we clicked ouside current edited element
this._removeBodyListener();
this.setState({ edit: false }); //cancel edit
if (this.state.value.trim().length === 0 && !this.props.clearEnable) {
//value was cleared but it is blocked
this.setState({ value: this.lastValue }); //back to last value
} else this.lastValue = this.state.value; //save last value;
if (this.props.onEditEnd != null) {
this.props.onEditEnd(this.state.value, this.props.id);
}
}
}, {
key: '_bodyClickHandler',
value: function _bodyClickHandler(e) {
if (!e.target.dataset || typeof e.target.dataset.id === "undefined" || e.target.dataset.id != this.props.id) {
this.cancelEditMode();
}
}
}, {
key: '_removeBodyListener',
value: function _removeBodyListener() {
if (this.bodyClickEvent !== null) document.removeEventListener("click", this.bodyClickEvent, false);
}
}, {
key: '_addBodyListener',
value: function _addBodyListener() {
this._removeBodyListener();
this.bodyClickEvent = this._bodyClickHandler.bind(this);
document.addEventListener("click", this.bodyClickEvent, false);
}
}, {
key: 'handleLabelClick',
value: function handleLabelClick(type, e) {
if (this.props.initBy !== type) return; //it is not this event
//block propagate
e.stopPropagation();
e.preventDefault();
this.setState({ edit: true });
//set binding
this._addBodyListener();
if (this.props.onEditStart !== null) this.props.onEditStart(this.state.value, this.props.id);
}
}, {
key: 'handleKeyPress',
value: function handleKeyPress(e) {
if (e.charCode === 13) {
//enter
if (this.props.onEnterClick !== null) this.props.onEnterClick(this.state.value, this.props.id);
this.cancelEditMode();
}
}
}, {
key: 'handleInputClick',
value: function handleInputClick(e) {
//block events bubbling
e.stopPropagation();
}
}, {
key: 'getLabelStyle',
value: function getLabelStyle() {
return {
cursor: "pointer"
};
}
}, {
key: 'render',
value: function render() {
var props = this.props;
var tf = _objectWithoutProperties(props.input, []); //textField props
var label = _objectWithoutProperties(props.label, []); //label props
var inputJSX = void 0;
if (this.props.material) inputJSX = _react2.default.createElement(_TextField2.default, _extends({}, tf, { ref: 'input', 'data-id': props.id, name: "input_" + props.id, onClick: this.handleInputClick.bind(this), value: this.state.value, onChange: this.handleChange.bind(this), onKeyPress: this.handleKeyPress.bind(this) }));else //standard input
inputJSX = _react2.default.createElement('input', _extends({}, tf, { ref: 'input', 'data-id': props.id, name: "input_" + props.id, onClick: this.handleInputClick.bind(this), value: this.state.value, onChange: this.handleChange.bind(this), onKeyPress: this.handleKeyPress.bind(this) }));
var element = void 0;
if (this.state.edit) element = inputJSX;else element = _react2.default.createElement(
'label',
_extends({ style: this.getLabelStyle(), ref: 'label'
}, label, {
onDoubleClick: this.handleLabelClick.bind(this, EditLabel.INIT_DBCLICK),
onClick: this.handleLabelClick.bind(this, EditLabel.INIT_CLICK)
}),
this.state.value
);
return element;
}
}]);
return EditLabel;
}(_react.Component);
EditLabel.INIT_CLICK = 1;
EditLabel.INIT_DBCLICK = 2;
;
EditLabel.propTypes = {
input: _react2.default.PropTypes.object,
label: _react2.default.PropTypes.object,
initBy: _react2.default.PropTypes.number.isRequired,
id: _react2.default.PropTypes.number.isRequired,
defValue: _react2.default.PropTypes.string,
onEditEnd: _react2.default.PropTypes.func, //calls on end of edit
onChange: _react2.default.PropTypes.func, //calls on every change
onEnterClick: _react2.default.PropTypes.func, //calls after enter click
onEditStart: _react2.default.PropTypes.func, //calls when edition starts
material: _react2.default.PropTypes.bool, //if true it uses TextField from material if false <input>
clearEnable: _react2.default.PropTypes.bool //is possible to remove all text - clear it
};
EditLabel.defaultProps = {
input: { className: "editlabel-input" },
label: { className: "editlabel-label" },
initBy: EditLabel.INIT_CLICK, //default is single click
defValue: "",
clearEnable: false,
onChange: null,
onEditEnd: null, //
onEnterClick: null,
onEditStart: null,
material: true
};
exports.default = EditLabel;