UNPKG

react-addons

Version:

Simple packaging of react addons to avoid fiddly 'react/addons' npm module.

141 lines (126 loc) 4.51 kB
/** * Copyright 2013-2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @providesModule ReactInputSelection */ "use strict"; var ReactDOMSelection = require("./ReactDOMSelection"); var containsNode = require("./containsNode"); var getActiveElement = require("./getActiveElement"); function isInDocument(node) { return containsNode(document.documentElement, node); } /** * @ReactInputSelection: React input selection module. Based on Selection.js, * but modified to be suitable for react and has a couple of bug fixes (doesn't * assume buttons have range selections allowed). * Input selection module for React. */ var ReactInputSelection = { hasSelectionCapabilities: function(elem) { return elem && ( (elem.nodeName === 'INPUT' && elem.type === 'text') || elem.nodeName === 'TEXTAREA' || elem.contentEditable === 'true' ); }, getSelectionInformation: function() { var focusedElem = getActiveElement(); return { focusedElem: focusedElem, selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null }; }, /** * @restoreSelection: If any selection information was potentially lost, * restore it. This is useful when performing operations that could remove dom * nodes and place them back in, resulting in focus being lost. */ restoreSelection: function(priorSelectionInformation) { var curFocusedElem = getActiveElement(); var priorFocusedElem = priorSelectionInformation.focusedElem; var priorSelectionRange = priorSelectionInformation.selectionRange; if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) { if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) { ReactInputSelection.setSelection( priorFocusedElem, priorSelectionRange ); } priorFocusedElem.focus(); } }, /** * @getSelection: Gets the selection bounds of a focused textarea, input or * contentEditable node. * -@input: Look up selection bounds of this input * -@return {start: selectionStart, end: selectionEnd} */ getSelection: function(input) { var selection; if ('selectionStart' in input) { // Modern browser with input or textarea. selection = { start: input.selectionStart, end: input.selectionEnd }; } else if (document.selection && input.nodeName === 'INPUT') { // IE8 input. var range = document.selection.createRange(); // There can only be one selection per document in IE, so it must // be in our element. if (range.parentElement() === input) { selection = { start: -range.moveStart('character', -input.value.length), end: -range.moveEnd('character', -input.value.length) }; } } else { // Content editable or old IE textarea. selection = ReactDOMSelection.getOffsets(input); } return selection || {start: 0, end: 0}; }, /** * @setSelection: Sets the selection bounds of a textarea or input and focuses * the input. * -@input Set selection bounds of this input or textarea * -@offsets Object of same form that is returned from get* */ setSelection: function(input, offsets) { var start = offsets.start; var end = offsets.end; if (typeof end === 'undefined') { end = start; } if ('selectionStart' in input) { input.selectionStart = start; input.selectionEnd = Math.min(end, input.value.length); } else if (document.selection && input.nodeName === 'INPUT') { var range = input.createTextRange(); range.collapse(true); range.moveStart('character', start); range.moveEnd('character', end - start); range.select(); } else { ReactDOMSelection.setOffsets(input, offsets); } } }; module.exports = ReactInputSelection;