1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | (function () {
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | var properties = [
|
13 | 'direction',
|
14 | 'boxSizing',
|
15 | 'width',
|
16 | 'height',
|
17 | 'overflowX',
|
18 | 'overflowY',
|
19 |
|
20 | 'borderTopWidth',
|
21 | 'borderRightWidth',
|
22 | 'borderBottomWidth',
|
23 | 'borderLeftWidth',
|
24 | 'borderStyle',
|
25 |
|
26 | 'paddingTop',
|
27 | 'paddingRight',
|
28 | 'paddingBottom',
|
29 | 'paddingLeft',
|
30 |
|
31 |
|
32 | 'fontStyle',
|
33 | 'fontVariant',
|
34 | 'fontWeight',
|
35 | 'fontStretch',
|
36 | 'fontSize',
|
37 | 'fontSizeAdjust',
|
38 | 'lineHeight',
|
39 | 'fontFamily',
|
40 |
|
41 | 'textAlign',
|
42 | 'textTransform',
|
43 | 'textIndent',
|
44 | 'textDecoration',
|
45 |
|
46 | 'letterSpacing',
|
47 | 'wordSpacing',
|
48 |
|
49 | 'tabSize',
|
50 | 'MozTabSize'
|
51 |
|
52 | ];
|
53 |
|
54 | var isBrowser = (typeof window !== 'undefined');
|
55 | var isFirefox = (isBrowser && window.mozInnerScreenX != null);
|
56 |
|
57 | function getCaretCoordinates(element, position, options) {
|
58 | if (!isBrowser) {
|
59 | throw new Error('textarea-caret-position#getCaretCoordinates should only be called in a browser');
|
60 | }
|
61 |
|
62 | var debug = options && options.debug || false;
|
63 | if (debug) {
|
64 | var el = document.querySelector('#input-textarea-caret-position-mirror-div');
|
65 | if (el) el.parentNode.removeChild(el);
|
66 | }
|
67 |
|
68 |
|
69 | var div = document.createElement('div');
|
70 | div.id = 'input-textarea-caret-position-mirror-div';
|
71 | document.body.appendChild(div);
|
72 |
|
73 | var style = div.style;
|
74 | var computed = window.getComputedStyle ? window.getComputedStyle(element) : element.currentStyle;
|
75 | var isInput = element.nodeName === 'INPUT';
|
76 |
|
77 |
|
78 | style.whiteSpace = 'pre-wrap';
|
79 | if (!isInput)
|
80 | style.wordWrap = 'break-word';
|
81 |
|
82 |
|
83 | style.position = 'absolute';
|
84 | if (!debug)
|
85 | style.visibility = 'hidden';
|
86 |
|
87 |
|
88 | properties.forEach(function (prop) {
|
89 | if (isInput && prop === 'lineHeight') {
|
90 |
|
91 | style.lineHeight = computed.height;
|
92 | } else {
|
93 | style[prop] = computed[prop];
|
94 | }
|
95 | });
|
96 |
|
97 | if (isFirefox) {
|
98 |
|
99 | if (element.scrollHeight > parseInt(computed.height))
|
100 | style.overflowY = 'scroll';
|
101 | } else {
|
102 | style.overflow = 'hidden';
|
103 | }
|
104 |
|
105 | div.textContent = element.value.substring(0, position);
|
106 |
|
107 |
|
108 | if (isInput)
|
109 | div.textContent = div.textContent.replace(/\s/g, '\u00a0');
|
110 |
|
111 | var span = document.createElement('span');
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 | span.textContent = element.value.substring(position) || '.';
|
118 | div.appendChild(span);
|
119 |
|
120 | var coordinates = {
|
121 | top: span.offsetTop + parseInt(computed['borderTopWidth']),
|
122 | left: span.offsetLeft + parseInt(computed['borderLeftWidth']),
|
123 | height: parseInt(computed['lineHeight'])
|
124 | };
|
125 |
|
126 | if (debug) {
|
127 | span.style.backgroundColor = '#aaa';
|
128 | } else {
|
129 | document.body.removeChild(div);
|
130 | }
|
131 |
|
132 | return coordinates;
|
133 | }
|
134 |
|
135 | if (typeof module != 'undefined' && typeof module.exports != 'undefined') {
|
136 | module.exports = getCaretCoordinates;
|
137 | } else if(isBrowser) {
|
138 | window.getCaretCoordinates = getCaretCoordinates;
|
139 | }
|
140 |
|
141 | }());
|