Some refactoring

This commit is contained in:
jos 2017-07-19 14:31:26 +02:00
parent c5ce6525a5
commit a03d962daa
5 changed files with 72 additions and 130 deletions

View File

@ -4,7 +4,7 @@ import { createElement as h, Component } from 'react'
import ActionMenu from './menu/ActionMenu'
import { escapeHTML, unescapeHTML } from '../utils/stringUtils'
import { getInnerText, insideRect, findParentNode } from '../utils/domUtils'
import { getInnerText, insideRect, findParentWithAttribute } from '../utils/domUtils'
import { stringConvert, valueType, isUrl } from '../utils/typeUtils'
import { compileJSONPointer } from '../jsonData'
@ -417,7 +417,7 @@ export default class JSONNode extends Component {
handleOpenActionMenu = (event) => {
// TODO: don't use refs, find root purely via DOM?
const root = findParentNode(this.refs.actionMenuButton, 'data-jsoneditor', 'true')
const root = findParentWithAttribute(this.refs.actionMenuButton, 'data-jsoneditor', 'true')
this.setState({
menu: {
@ -434,7 +434,7 @@ export default class JSONNode extends Component {
handleOpenAppendActionMenu = (event) => {
// TODO: don't use refs, find root purely via DOM?
const root = findParentNode(this.refs.appendActionMenuButton, 'data-jsoneditor', 'true')
const root = findParentWithAttribute(this.refs.appendActionMenuButton, 'data-jsoneditor', 'true')
this.setState({
appendMenu: {
@ -594,32 +594,6 @@ export default class JSONNode extends Component {
? stringValue
: stringConvert(stringValue)
}
/**
* Find the root DOM element of the JSONEditor
* Search is done based on the CSS class 'jsoneditor'
* @param event
* @return {*}
*/
// TODO: make redundant and cleanup
static findRootElement (event) {
function isEditorElement (elem) {
// FIXME: this is a bit tricky. can we use a special attribute or something?
return elem.className.split(' ').indexOf('jsoneditor') !== -1
}
let elem = event.target
while (elem) {
if (isEditorElement(elem)) {
return elem
}
elem = elem.parentNode
}
return null
}
}
/**

View File

@ -1,5 +1,5 @@
import { createElement as h, Component } from 'react'
import { findParentNode } from '../../utils/domUtils'
import { findParentWithAttribute } from '../../utils/domUtils'
export let CONTEXT_MENU_HEIGHT = 240
@ -178,7 +178,7 @@ export default class Menu extends Component {
setTimeout(() => {
if (!this.handleRequestClose) {
this.handleRequestClose = (event) => {
if (!findParentNode(event.target, 'data-menu', 'true')) {
if (!findParentWithAttribute(event.target, 'data-menu', 'true')) {
this.props.onRequestClose()
}
}

View File

@ -1,12 +1,10 @@
import { createElement as h, Component } from 'react'
import { toCapital } from '../../utils/stringUtils'
import { findParentNode } from '../../utils/domUtils'
import { findParentWithAttribute } from '../../utils/domUtils'
export default class ModeMenu extends Component {
/**
* @param {{open, modes, mode, onChangeMode, onRequestClose, onError}} props
* @param {Object} state
* @return {JSX.Element}
* {{open, modes, mode, onChangeMode, onRequestClose, onError}} props
*/
render () {
if (this.props.open) {
@ -65,7 +63,7 @@ export default class ModeMenu extends Component {
setTimeout(() => {
if (!this.handleRequestClose) {
this.handleRequestClose = (event) => {
if (!findParentNode(event.target, 'data-menu', 'true')) {
if (!findParentWithAttribute(event.target, 'data-menu', 'true')) {
this.props.onRequestClose()
}
}

View File

@ -1,4 +1,7 @@
import { selectContentEditable, getSelection as getDOMSelection } from '../../utils/domUtils'
import {
selectContentEditable, hasClassName,
findParentWithAttribute, findParentWithClassName
} from '../../utils/domUtils'
import { compileJSONPointer, parseJSONPointer } from '../../jsonData'
// singleton
@ -172,21 +175,6 @@ export function findNode (container, path) {
return container.querySelector(`div[${PATH_ATTRIBUTE}="${compileJSONPointer(path)}"]`)
}
// TODO: fully implement getSelection, or cleanup if not needed
// function getSelectedElement () {
// const selection = getDOMSelection()
// return selection ? selection.startContainer : null
// }
//
// export function getSelection () {
// const element = getSelectedElement()
// const node = findBaseNode(element)
//
// return {
// path: node.getAttribute(PATH_ATTRIBUTE) // TODO: return parsed JSONPointer instead?
// }
// }
function findContentsContainer (element) {
return findParentWithClassName (element, CONTENTS_CONTAINER_CLASS_NAME)
}
@ -212,49 +200,6 @@ export function searchHasFocus () {
}
}
/**
* Find the first parent element having a specific class name
* @param {Element} element
* @param {string} className
* @return {Element} Returns the base element of the node
*/
function findParentWithClassName (element, className) {
let e = element
do {
if (hasClassName(e, className)) {
return e
}
e = e.parentNode
}
while (e)
return null
}
/**
* Find the base element of a node from one of it's childs
* @param {Element} element
* @param {string} attribute
* @param {string} value
* @return {Element} Returns the base element of the node
*/
function findParentWithAttribute (element, attribute, value) {
let e = element
do {
if (e && e.hasAttribute && e.hasAttribute(attribute)) {
if (value === undefined || e.getAttribute(attribute) === value) {
return e
}
}
e = e.parentNode
}
while (e)
return null
}
function findPreviousNode (element) {
const container = findContentsContainer(element)
const node = findBaseNode(element)
@ -341,18 +286,6 @@ function findInputName (node, name) {
return null
}
/**
* Test whether a HTML element contains a specific className
* @param {Element} element
* @param {boolean} className
* @return {boolean}
*/
function hasClassName (element, className) {
return element && element.className
? element.className.split(' ').indexOf(className) !== -1
: false
}
/**
* find the closest input that actually exists in this node
* @param {Element} node

View File

@ -5,12 +5,12 @@
* @return {String} innerText
*/
export function getInnerText (element, buffer) {
var first = (buffer == undefined)
const first = (buffer === undefined)
if (first) {
buffer = {
'text': '',
'flush': function () {
var text = this.text
const text = this.text
this.text = ''
return text
},
@ -27,23 +27,23 @@ export function getInnerText (element, buffer) {
// divs or other HTML elements
if (element.hasChildNodes()) {
var childNodes = element.childNodes
var innerText = ''
const childNodes = element.childNodes
let innerText = ''
for (var i = 0, iMax = childNodes.length; i < iMax; i++) {
var child = childNodes[i]
for (let i = 0, iMax = childNodes.length; i < iMax; i++) {
const child = childNodes[i]
if (child.nodeName == 'DIV' || child.nodeName == 'P') {
var prevChild = childNodes[i - 1]
var prevName = prevChild ? prevChild.nodeName : undefined
if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') {
if (child.nodeName === 'DIV' || child.nodeName === 'P') {
const prevChild = childNodes[i - 1]
const prevName = prevChild ? prevChild.nodeName : undefined
if (prevName && prevName !== 'DIV' && prevName !== 'P' && prevName !== 'BR') {
innerText += '\n'
buffer.flush()
}
innerText += getInnerText(child, buffer)
buffer.set('\n')
}
else if (child.nodeName == 'BR') {
else if (child.nodeName === 'BR') {
innerText += buffer.flush()
buffer.set('\n')
}
@ -55,7 +55,7 @@ export function getInnerText (element, buffer) {
return innerText
}
else {
if (element.nodeName == 'P' && getInternetExplorerVersion() != -1) {
if (element.nodeName === 'P' && getInternetExplorerVersion() !== -1) {
// On Internet Explorer, a <p> with hasChildNodes()==false is
// rendered with a new line. Note that a <p> with
// hasChildNodes()==true is rendered without a new line
@ -108,24 +108,61 @@ export function selectContentEditable(contentEditableElement) {
* Find the parent node of an element which has an attribute with given value.
* Can return the element itself too.
* @param {Element} elem
* @param {string} attr
* @param {string} value
* @param {string} attribute
* @param {string} [value]
* @return {Element | null} Returns the parent element when found,
* or null otherwise
*/
export function findParentNode (elem, attr, value) {
export function findParentWithAttribute (elem, attribute, value) {
let parent = elem
while (parent && parent.getAttribute) {
if (parent.getAttribute(attr) == value) {
const match = (value === undefined)
? parent.hasAttribute(attribute)
: parent.getAttribute(attribute) === value
if (match) {
return parent
}
parent = parent.parentNode
}
return null
}
/**
* Find the first parent element having a specific class name
* @param {Element} element
* @param {string} className
* @return {Element} Returns the base element of the node
*/
export function findParentWithClassName (element, className) {
let parent = element
while (parent) {
if (hasClassName(parent, className)) {
return parent
}
parent = parent.parentNode
}
return null
}
/**
* Test whether a HTML element contains a specific className
* @param {Element} element
* @param {boolean} className
* @return {boolean}
*/
export function hasClassName (element, className) {
return element && element.className
? element.className.split(' ').indexOf(className) !== -1
: false
}
/**
* Test whether the child rect fits completely inside the parent rect.
* @param {ClientRect} parent
@ -146,13 +183,13 @@ export function insideRect (parent, child, margin = 0) {
* @return {Number} Internet Explorer version, or -1 in case of an other browser
*/
export function getInternetExplorerVersion() {
if (_ieVersion == -1) {
var rv = -1 // Return value assumes failure.
if (navigator.appName == 'Microsoft Internet Explorer')
if (_ieVersion === -1) {
let rv = -1 // Return value assumes failure.
if (navigator.appName === 'Microsoft Internet Explorer')
{
var ua = navigator.userAgent
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})")
if (re.exec(ua) != null) {
const ua = navigator.userAgent
const re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})")
if (re.exec(ua) !== null) {
rv = parseFloat( RegExp.$1 )
}
}
@ -168,4 +205,4 @@ export function getInternetExplorerVersion() {
* @type {Number}
* @private
*/
var _ieVersion = -1
let _ieVersion = -1