]> git.mxchange.org Git - friendica.git/blob - view/theme/frio/frameworks/autosize/autosize.js
Merge pull request #6541 from annando/mentions
[friendica.git] / view / theme / frio / frameworks / autosize / autosize.js
1 /*!
2         Autosize 3.0.17
3         license: MIT
4         http://www.jacklmoore.com/autosize
5 */
6 (function (global, factory) {
7         if (typeof define === 'function' && define.amd) {
8                 define(['exports', 'module'], factory);
9         } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
10                 factory(exports, module);
11         } else {
12                 var mod = {
13                         exports: {}
14                 };
15                 factory(mod.exports, mod);
16                 global.autosize = mod.exports;
17         }
18 })(this, function (exports, module) {
19         'use strict';
20
21         var set = typeof Set === 'function' ? new Set() : (function () {
22                 var list = [];
23
24                 return {
25                         has: function has(key) {
26                                 return Boolean(list.indexOf(key) > -1);
27                         },
28                         add: function add(key) {
29                                 list.push(key);
30                         },
31                         'delete': function _delete(key) {
32                                 list.splice(list.indexOf(key), 1);
33                         } };
34         })();
35
36         var createEvent = function createEvent(name) {
37                 return new Event(name);
38         };
39         try {
40                 new Event('test');
41         } catch (e) {
42                 // IE does not support `new Event()`
43                 createEvent = function (name) {
44                         var evt = document.createEvent('Event');
45                         evt.initEvent(name, true, false);
46                         return evt;
47                 };
48         }
49
50         function assign(ta) {
51                 if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || set.has(ta)) return;
52
53                 var heightOffset = null;
54                 var clientWidth = ta.clientWidth;
55                 var cachedHeight = null;
56
57                 function init() {
58                         var style = window.getComputedStyle(ta, null);
59
60                         if (style.resize === 'vertical') {
61                                 ta.style.resize = 'none';
62                         } else if (style.resize === 'both') {
63                                 ta.style.resize = 'horizontal';
64                         }
65
66                         if (style.boxSizing === 'content-box') {
67                                 heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
68                         } else {
69                                 heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
70                         }
71                         // Fix when a textarea is not on document body and heightOffset is Not a Number
72                         if (isNaN(heightOffset)) {
73                                 heightOffset = 0;
74                         }
75
76                         update();
77                 }
78
79                 function changeOverflow(value) {
80                         {
81                                 // Chrome/Safari-specific fix:
82                                 // When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
83                                 // made available by removing the scrollbar. The following forces the necessary text reflow.
84                                 var width = ta.style.width;
85                                 ta.style.width = '0px';
86                                 // Force reflow:
87                                 /* jshint ignore:start */
88                                 ta.offsetWidth;
89                                 /* jshint ignore:end */
90                                 ta.style.width = width;
91                         }
92
93                         ta.style.overflowY = value;
94
95                         resize();
96                 }
97
98                 function getParentOverflows(el) {
99                         var arr = [];
100
101                         while (el && el.parentNode && el.parentNode instanceof Element) {
102                                 if (el.parentNode.scrollTop) {
103                                         arr.push({
104                                                 node: el.parentNode,
105                                                 scrollTop: el.parentNode.scrollTop });
106                                 }
107                                 el = el.parentNode;
108                         }
109
110                         return arr;
111                 }
112
113                 function resize() {
114                         var originalHeight = ta.style.height;
115                         var overflows = getParentOverflows(ta);
116                         var docTop = document.documentElement && document.documentElement.scrollTop; // Needed for Mobile IE (ticket #240)
117
118                         ta.style.height = 'auto';
119
120                         var endHeight = ta.scrollHeight + heightOffset;
121
122                         if (ta.scrollHeight === 0) {
123                                 // If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
124                                 ta.style.height = originalHeight;
125                                 return;
126                         }
127
128                         ta.style.height = endHeight + 'px';
129
130                         // used to check if an update is actually necessary on window.resize
131                         clientWidth = ta.clientWidth;
132
133                         // prevents scroll-position jumping
134                         overflows.forEach(function (el) {
135                                 el.node.scrollTop = el.scrollTop;
136                         });
137
138                         if (docTop) {
139                                 document.documentElement.scrollTop = docTop;
140                         }
141                 }
142
143                 function update() {
144                         resize();
145
146                         var computed = window.getComputedStyle(ta, null);
147                         var computedHeight = Math.round(parseFloat(computed.height));
148                         var styleHeight = Math.round(parseFloat(ta.style.height));
149
150                         // The computed height not matching the height set via resize indicates that
151                         // the max-height has been exceeded, in which case the overflow should be set to visible.
152                         if (computedHeight !== styleHeight) {
153                                 if (computed.overflowY !== 'visible') {
154                                         changeOverflow('visible');
155                                 }
156                         } else {
157                                 // Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
158                                 if (computed.overflowY !== 'hidden') {
159                                         changeOverflow('hidden');
160                                 }
161                         }
162
163                         if (cachedHeight !== computedHeight) {
164                                 cachedHeight = computedHeight;
165                                 var evt = createEvent('autosize:resized');
166                                 ta.dispatchEvent(evt);
167                         }
168                 }
169
170                 var pageResize = function pageResize() {
171                         if (ta.clientWidth !== clientWidth) {
172                                 update();
173                         }
174                 };
175
176                 var destroy = (function (style) {
177                         window.removeEventListener('resize', pageResize, false);
178                         ta.removeEventListener('input', update, false);
179                         ta.removeEventListener('keyup', update, false);
180                         ta.removeEventListener('autosize:destroy', destroy, false);
181                         ta.removeEventListener('autosize:update', update, false);
182                         set['delete'](ta);
183
184                         Object.keys(style).forEach(function (key) {
185                                 ta.style[key] = style[key];
186                         });
187                 }).bind(ta, {
188                         height: ta.style.height,
189                         resize: ta.style.resize,
190                         overflowY: ta.style.overflowY,
191                         overflowX: ta.style.overflowX,
192                         wordWrap: ta.style.wordWrap });
193
194                 ta.addEventListener('autosize:destroy', destroy, false);
195
196                 // IE9 does not fire onpropertychange or oninput for deletions,
197                 // so binding to onkeyup to catch most of those events.
198                 // There is no way that I know of to detect something like 'cut' in IE9.
199                 if ('onpropertychange' in ta && 'oninput' in ta) {
200                         ta.addEventListener('keyup', update, false);
201                 }
202
203                 window.addEventListener('resize', pageResize, false);
204                 ta.addEventListener('input', update, false);
205                 ta.addEventListener('autosize:update', update, false);
206                 set.add(ta);
207                 ta.style.overflowX = 'hidden';
208                 ta.style.wordWrap = 'break-word';
209
210                 init();
211         }
212
213         function destroy(ta) {
214                 if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
215                 var evt = createEvent('autosize:destroy');
216                 ta.dispatchEvent(evt);
217         }
218
219         function update(ta) {
220                 if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
221                 var evt = createEvent('autosize:update');
222                 ta.dispatchEvent(evt);
223         }
224
225         var autosize = null;
226
227         // Do nothing in Node.js environment and IE8 (or lower)
228         if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
229                 autosize = function (el) {
230                         return el;
231                 };
232                 autosize.destroy = function (el) {
233                         return el;
234                 };
235                 autosize.update = function (el) {
236                         return el;
237                 };
238         } else {
239                 autosize = function (el, options) {
240                         if (el) {
241                                 Array.prototype.forEach.call(el.length ? el : [el], function (x) {
242                                         return assign(x, options);
243                                 });
244                         }
245                         return el;
246                 };
247                 autosize.destroy = function (el) {
248                         if (el) {
249                                 Array.prototype.forEach.call(el.length ? el : [el], destroy);
250                         }
251                         return el;
252                 };
253                 autosize.update = function (el) {
254                         if (el) {
255                                 Array.prototype.forEach.call(el.length ? el : [el], update);
256                         }
257                         return el;
258                 };
259         }
260
261         module.exports = autosize;
262 });