@ckeditor/ckeditor5-utils 29.2.0 → 30.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-utils",
3
- "version": "29.2.0",
3
+ "version": "30.0.0",
4
4
  "description": "Miscellaneous utilities used by CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -14,10 +14,10 @@
14
14
  "lodash-es": "^4.17.15"
15
15
  },
16
16
  "devDependencies": {
17
- "@ckeditor/ckeditor5-build-classic": "^29.2.0",
18
- "@ckeditor/ckeditor5-editor-classic": "^29.2.0",
19
- "@ckeditor/ckeditor5-core": "^29.2.0",
20
- "@ckeditor/ckeditor5-engine": "^29.2.0",
17
+ "@ckeditor/ckeditor5-build-classic": "^30.0.0",
18
+ "@ckeditor/ckeditor5-editor-classic": "^30.0.0",
19
+ "@ckeditor/ckeditor5-core": "^30.0.0",
20
+ "@ckeditor/ckeditor5-engine": "^30.0.0",
21
21
  "assertion-error": "^1.1.0",
22
22
  "js-beautify": "^1.11.0"
23
23
  },
@@ -85,6 +85,7 @@ export default class CKEditorError extends Error {
85
85
 
86
86
  /**
87
87
  * Checks if the error is of the `CKEditorError` type.
88
+ * @returns {Boolean}
88
89
  */
89
90
  is( type ) {
90
91
  return type === 'CKEditorError';
@@ -142,7 +143,6 @@ export default class CKEditorError extends Error {
142
143
  *
143
144
  * @param {String} errorName The error name to be logged.
144
145
  * @param {Object} [data] Additional data to be logged.
145
- * @returns {String}
146
146
  */
147
147
  export function logWarning( errorName, data ) {
148
148
  console.warn( ...formatConsoleArguments( errorName, data ) );
@@ -167,7 +167,6 @@ export function logWarning( errorName, data ) {
167
167
  *
168
168
  * @param {String} errorName The error name to be logged.
169
169
  * @param {Object} [data] Additional data to be logged.
170
- * @returns {String}
171
170
  */
172
171
  export function logError( errorName, data ) {
173
172
  console.error( ...formatConsoleArguments( errorName, data ) );
package/src/collection.js CHANGED
@@ -56,7 +56,7 @@ export default class Collection {
56
56
  * console.log( collection.get( 'George' ) ); // -> { name: 'George' }
57
57
  * console.log( collection.get( 'John' ) ); // -> { name: 'John' }
58
58
  *
59
- * @param {Iterable.<Object>|Object} initialItemsOrOptions The initial items of the collection or
59
+ * @param {Iterable.<Object>|Object} [initialItemsOrOptions] The initial items of the collection or
60
60
  * the options object.
61
61
  * @param {Object} [options={}] The options object, when the first argument is an array of initial items.
62
62
  * @param {String} [options.idProperty='id'] The name of the property which is used to identify an item.
@@ -13,6 +13,8 @@ import getPositionedAncestor from './getpositionedancestor';
13
13
  import getBorderWidths from './getborderwidths';
14
14
  import { isFunction } from 'lodash-es';
15
15
 
16
+ // @if CK_DEBUG_POSITION // import { RectDrawer } from '@ckeditor/ckeditor5-minimap/src/utils';
17
+
16
18
  /**
17
19
  * Calculates the `position: absolute` coordinates of a given element so it can be positioned with respect to the
18
20
  * target in the visually most efficient way, taking various restrictions like viewport or limiter geometry
@@ -74,10 +76,10 @@ import { isFunction } from 'lodash-es';
74
76
  * element.style.top = top;
75
77
  * element.style.left = left;
76
78
  *
77
- * @param {module:utils/dom/position~Options} options Positioning options object.
79
+ * @param {module:utils/dom/position~Options} options The input data and configuration of the helper.
78
80
  * @returns {module:utils/dom/position~Position}
79
81
  */
80
- export function getOptimalPosition( { element, target, positions, limiter, fitInViewport } ) {
82
+ export function getOptimalPosition( { element, target, positions, limiter, fitInViewport, viewportOffsetConfig } ) {
81
83
  // If the {@link module:utils/dom/position~Options#target} is a function, use what it returns.
82
84
  // https://github.com/ckeditor/ckeditor5-utils/issues/157
83
85
  if ( isFunction( target ) ) {
@@ -94,52 +96,54 @@ export function getOptimalPosition( { element, target, positions, limiter, fitIn
94
96
  const elementRect = new Rect( element );
95
97
  const targetRect = new Rect( target );
96
98
 
97
- let bestPositionRect;
98
- let bestPositionName;
99
+ let bestPosition;
100
+
101
+ // @if CK_DEBUG_POSITION // RectDrawer.clear();
102
+ // @if CK_DEBUG_POSITION // RectDrawer.draw( targetRect, { outlineWidth: '5px' }, 'Target' );
103
+
104
+ const positionOptions = { targetRect, elementRect, positionedElementAncestor };
99
105
 
100
106
  // If there are no limits, just grab the very first position and be done with that drama.
101
107
  if ( !limiter && !fitInViewport ) {
102
- [ bestPositionName, bestPositionRect ] = getPositionNameAndRect( positions[ 0 ], targetRect, elementRect );
108
+ bestPosition = new Position( positions[ 0 ], positionOptions );
103
109
  } else {
104
110
  const limiterRect = limiter && new Rect( limiter ).getVisible();
105
- const viewportRect = fitInViewport && new Rect( global.window );
106
- const bestPosition = getBestPositionNameAndRect( positions, { targetRect, elementRect, limiterRect, viewportRect } );
111
+ const viewportRect = fitInViewport && getConstrainedViewportRect( viewportOffsetConfig );
107
112
 
108
- // If there's no best position found, i.e. when all intersections have no area because
109
- // rects have no width or height, then just use the first available position.
110
- [ bestPositionName, bestPositionRect ] = bestPosition || getPositionNameAndRect( positions[ 0 ], targetRect, elementRect );
111
- }
113
+ // @if CK_DEBUG_POSITION // if ( viewportRect ) {
114
+ // @if CK_DEBUG_POSITION // RectDrawer.draw( viewportRect, { outlineWidth: '5px' }, 'Viewport' );
115
+ // @if CK_DEBUG_POSITION // }
112
116
 
113
- let absoluteRectCoordinates = getAbsoluteRectCoordinates( bestPositionRect );
117
+ // @if CK_DEBUG_POSITION // if ( limiter ) {
118
+ // @if CK_DEBUG_POSITION // RectDrawer.draw( limiterRect, { outlineWidth: '5px', outlineColor: 'green' }, 'Visible limiter' );
119
+ // @if CK_DEBUG_POSITION // }
114
120
 
115
- if ( positionedElementAncestor ) {
116
- absoluteRectCoordinates = shiftRectCoordinatesDueToPositionedAncestor( absoluteRectCoordinates, positionedElementAncestor );
121
+ Object.assign( positionOptions, { limiterRect, viewportRect } );
122
+
123
+ // If there's no best position found, i.e. when all intersections have no area because
124
+ // rects have no width or height, then just use the first available position.
125
+ bestPosition = getBestPosition( positions, positionOptions ) || new Position( positions[ 0 ], positionOptions );
117
126
  }
118
127
 
119
- return {
120
- left: absoluteRectCoordinates.left,
121
- top: absoluteRectCoordinates.top,
122
- name: bestPositionName
123
- };
128
+ return bestPosition;
124
129
  }
125
130
 
126
- // For given position function, returns a corresponding `Rect` instance.
131
+ // Returns a viewport `Rect` shrunk by the viewport offset config from all sides.
127
132
  //
128
133
  // @private
129
- // @param {Function} position A function returning {@link module:utils/dom/position~Position}.
130
- // @param {utils/dom/rect~Rect} targetRect A rect of the target.
131
- // @param {utils/dom/rect~Rect} elementRect A rect of positioned element.
132
- // @returns {Array|null} An array containing position name and its Rect (or null if position should be ignored).
133
- function getPositionNameAndRect( position, targetRect, elementRect ) {
134
- const positionData = position( targetRect, elementRect );
135
-
136
- if ( !positionData ) {
137
- return null;
138
- }
134
+ // @param {Object} An object containing viewportOffset config.
135
+ // @returns {utils/dom/rect~Rect} A shrunken rect of the viewport.
136
+ function getConstrainedViewportRect( viewportOffsetConfig ) {
137
+ viewportOffsetConfig = Object.assign( { top: 0, bottom: 0, left: 0, right: 0 }, viewportOffsetConfig );
139
138
 
140
- const { left, top, name } = positionData;
139
+ const viewportRect = new Rect( global.window );
141
140
 
142
- return [ name, elementRect.clone().moveTo( left, top ) ];
141
+ viewportRect.top += viewportOffsetConfig.top;
142
+ viewportRect.height -= viewportOffsetConfig.top;
143
+ viewportRect.bottom -= viewportOffsetConfig.bottom;
144
+ viewportRect.height -= viewportOffsetConfig.bottom;
145
+
146
+ return viewportRect;
143
147
  }
144
148
 
145
149
  // For a given array of positioning functions, returns such that provides the best
@@ -148,157 +152,50 @@ function getPositionNameAndRect( position, targetRect, elementRect ) {
148
152
  // @private
149
153
  //
150
154
  // @param {Object} options
151
- // @param {module:utils/dom/position~Options#positions} positions Functions returning {@link module:utils/dom/position~Position}
152
- // to be checked, in the order of preference.
155
+ // @param {module:utils/dom/position~Options#positions} positions Functions returning
156
+ // {@link module:utils/dom/position~Position}to be checked, in the order of preference.
153
157
  // @param {Object} options
154
158
  // @param {utils/dom/rect~Rect} options.targetRect A rect of the {@link module:utils/dom/position~Options#target}.
155
- // @param {utils/dom/rect~Rect} options.elementRect A rect of positioned {@link module:utils/dom/position~Options#element}.
159
+ // @param {utils/dom/rect~Rect} options.elementRect A rect of positioned
160
+ // {@link module:utils/dom/position~Options#element}.
156
161
  // @param {utils/dom/rect~Rect} options.limiterRect A rect of the {@link module:utils/dom/position~Options#limiter}.
157
- // @param {utils/dom/rect~Rect} options.viewportRect A rect of the viewport.
162
+ // @param {utils/dom/rect~Rect} options.viewportRect A rect of the {@link module:utils/dom/position~Options#viewport}.
158
163
  //
159
164
  // @returns {Array} An array containing the name of the position and it's rect.
160
- function getBestPositionNameAndRect( positions, options ) {
161
- const { elementRect, viewportRect } = options;
162
-
163
- // This is when element is fully visible.
164
- const elementRectArea = elementRect.getArea();
165
-
166
- // Let's calculate intersection areas for positions. It will end early if best match is found.
167
- const processedPositions = processPositionsToAreas( positions, options );
168
-
169
- // First let's check all positions that fully fit in the viewport.
170
- if ( viewportRect ) {
171
- const processedPositionsInViewport = processedPositions.filter( ( { viewportIntersectArea } ) => {
172
- return viewportIntersectArea === elementRectArea;
173
- } );
174
-
175
- // Try to find best position from those which fit completely in viewport.
176
- const bestPositionData = getBestOfProcessedPositions( processedPositionsInViewport, elementRectArea );
177
-
178
- if ( bestPositionData ) {
179
- return bestPositionData;
180
- }
181
- }
182
-
183
- // Either there is no viewportRect or there is no position that fits completely in the viewport.
184
- return getBestOfProcessedPositions( processedPositions, elementRectArea );
185
- }
186
-
187
- // For a given array of positioning functions, calculates intersection areas for them.
188
- //
189
- // Note: If some position fully fits into the `limiterRect`, it will be returned early, without further consideration
190
- // of other positions.
191
- //
192
- // @private
193
- //
194
- // @param {module:utils/dom/position~Options#positions} positions Functions returning {@link module:utils/dom/position~Position}
195
- // to be checked, in the order of preference.
196
- // @param {Object} options
197
- // @param {utils/dom/rect~Rect} options.targetRect A rect of the {@link module:utils/dom/position~Options#target}.
198
- // @param {utils/dom/rect~Rect} options.elementRect A rect of positioned {@link module:utils/dom/position~Options#element}.
199
- // @param {utils/dom/rect~Rect} options.limiterRect A rect of the {@link module:utils/dom/position~Options#limiter}.
200
- // @param {utils/dom/rect~Rect} options.viewportRect A rect of the viewport.
201
- //
202
- // @returns {Array.<Object>} Array of positions with calculated intersection areas. Each item is an object containing:
203
- // * {String} positionName Name of position.
204
- // * {utils/dom/rect~Rect} positionRect Rect of position.
205
- // * {Number} limiterIntersectArea Area of intersection of the position with limiter part that is in the viewport.
206
- // * {Number} viewportIntersectArea Area of intersection of the position with viewport.
207
- function processPositionsToAreas( positions, { targetRect, elementRect, limiterRect, viewportRect } ) {
208
- const processedPositions = [];
165
+ function getBestPosition( positions, options ) {
166
+ const { elementRect } = options;
209
167
 
210
168
  // This is when element is fully visible.
211
169
  const elementRectArea = elementRect.getArea();
212
170
 
213
- for ( const position of positions ) {
214
- const positionData = getPositionNameAndRect( position, targetRect, elementRect );
215
-
216
- if ( !positionData ) {
217
- continue;
218
- }
219
-
220
- const [ positionName, positionRect ] = positionData;
221
- let limiterIntersectArea = 0;
222
- let viewportIntersectArea = 0;
223
-
224
- if ( limiterRect ) {
225
- if ( viewportRect ) {
226
- // Consider only the part of the limiter which is visible in the viewport. So the limiter is getting limited.
227
- const limiterViewportIntersectRect = limiterRect.getIntersection( viewportRect );
228
-
229
- if ( limiterViewportIntersectRect ) {
230
- // If the limiter is within the viewport, then check the intersection between that part of the
231
- // limiter and actual position.
232
- limiterIntersectArea = limiterViewportIntersectRect.getIntersectionArea( positionRect );
233
- }
234
- } else {
235
- limiterIntersectArea = limiterRect.getIntersectionArea( positionRect );
236
- }
237
- }
171
+ const positionInstances = positions
172
+ .map( positioningFunction => new Position( positioningFunction, options ) )
173
+ // Some positioning functions may return `null` if they don't want to participate.
174
+ .filter( position => !!position.name );
238
175
 
239
- if ( viewportRect ) {
240
- viewportIntersectArea = viewportRect.getIntersectionArea( positionRect );
241
- }
176
+ let maxFitFactor = 0;
177
+ let bestPosition = null;
242
178
 
243
- const processedPosition = {
244
- positionName,
245
- positionRect,
246
- limiterIntersectArea,
247
- viewportIntersectArea
248
- };
179
+ for ( const position of positionInstances ) {
180
+ const { _limiterIntersectionArea, _viewportIntersectionArea } = position;
249
181
 
250
182
  // If a such position is found that element is fully contained by the limiter then, obviously,
251
183
  // there will be no better one, so finishing.
252
- if ( limiterIntersectArea === elementRectArea ) {
253
- return [ processedPosition ];
254
- }
255
-
256
- processedPositions.push( processedPosition );
257
- }
258
-
259
- return processedPositions;
260
- }
261
-
262
- // For a given array of processed position data (with calculated Rects for positions and intersection areas)
263
- // returns such that provides the best fit of the `elementRect` into the `limiterRect` and `viewportRect` at the same time.
264
- //
265
- // **Note**: It will return early if some position fully fits into the `limiterRect`.
266
- //
267
- // @private
268
- // @param {Array.<Object>} Array of positions with calculated intersection areas (in order of preference).
269
- // Each item is an object containing:
270
- //
271
- // * {String} positionName Name of position.
272
- // * {utils/dom/rect~Rect} positionRect Rect of position.
273
- // * {Number} limiterIntersectArea Area of intersection of the position with limiter part that is in the viewport.
274
- // * {Number} viewportIntersectArea Area of intersection of the position with viewport.
275
- //
276
- // @param {Number} elementRectArea Area of positioned {@link module:utils/dom/position~Options#element}.
277
- // @returns {Array|null} An array containing the name of the position and it's rect, or null if not found.
278
- function getBestOfProcessedPositions( processedPositions, elementRectArea ) {
279
- let maxFitFactor = 0;
280
- let bestPositionRect;
281
- let bestPositionName;
282
-
283
- for ( const { positionName, positionRect, limiterIntersectArea, viewportIntersectArea } of processedPositions ) {
284
- // If a such position is found that element is fully container by the limiter then, obviously,
285
- // there will be no better one, so finishing.
286
- if ( limiterIntersectArea === elementRectArea ) {
287
- return [ positionName, positionRect ];
184
+ if ( _limiterIntersectionArea === elementRectArea ) {
185
+ return position;
288
186
  }
289
187
 
290
- // To maximize both viewport and limiter intersection areas we use distance on viewportIntersectArea
291
- // and limiterIntersectArea plane (without sqrt because we are looking for max value).
292
- const fitFactor = viewportIntersectArea ** 2 + limiterIntersectArea ** 2;
188
+ // To maximize both viewport and limiter intersection areas we use distance on _viewportIntersectionArea
189
+ // and _limiterIntersectionArea plane (without sqrt because we are looking for max value).
190
+ const fitFactor = _viewportIntersectionArea ** 2 + _limiterIntersectionArea ** 2;
293
191
 
294
192
  if ( fitFactor > maxFitFactor ) {
295
193
  maxFitFactor = fitFactor;
296
- bestPositionRect = positionRect;
297
- bestPositionName = positionName;
194
+ bestPosition = position;
298
195
  }
299
196
  }
300
197
 
301
- return bestPositionRect ? [ bestPositionName, bestPositionRect ] : null;
198
+ return bestPosition;
302
199
  }
303
200
 
304
201
  // For a given absolute Rect coordinates object and a positioned element ancestor, it returns an object with
@@ -310,41 +207,44 @@ function getBestOfProcessedPositions( processedPositions, elementRectArea ) {
310
207
  //
311
208
  // @private
312
209
  //
313
- // @param {Object} absoluteRectCoordinates An object with absolute rect coordinates.
314
- // @param {Object} absoluteRectCoordinates.top
315
- // @param {Object} absoluteRectCoordinates.left
210
+ // @param {utils/dom/rect~Rect} rect A rect with absolute rect coordinates.
211
+ // @param {Number} rect.top
212
+ // @param {Number} rect.left
316
213
  // @param {HTMLElement} positionedElementAncestor An ancestor element that should be considered.
317
214
  //
318
- // @returns {Object} An object corresponding to `absoluteRectCoordinates` input but with values shifted
215
+ // @returns {utils/dom/rect~Rect} A rect corresponding to `absoluteRect` input but with values shifted
319
216
  // to make up for the positioned element ancestor.
320
- function shiftRectCoordinatesDueToPositionedAncestor( { left, top }, positionedElementAncestor ) {
321
- const ancestorPosition = getAbsoluteRectCoordinates( new Rect( positionedElementAncestor ) );
217
+ function shiftRectToCompensatePositionedAncestor( rect, positionedElementAncestor ) {
218
+ const ancestorPosition = getRectForAbsolutePositioning( new Rect( positionedElementAncestor ) );
322
219
  const ancestorBorderWidths = getBorderWidths( positionedElementAncestor );
323
220
 
221
+ let moveX = 0;
222
+ let moveY = 0;
223
+
324
224
  // (https://github.com/ckeditor/ckeditor5-ui-default/issues/126)
325
225
  // If there's some positioned ancestor of the panel, then its `Rect` must be taken into
326
226
  // consideration. `Rect` is always relative to the viewport while `position: absolute` works
327
227
  // with respect to that positioned ancestor.
328
- left -= ancestorPosition.left;
329
- top -= ancestorPosition.top;
228
+ moveX -= ancestorPosition.left;
229
+ moveY -= ancestorPosition.top;
330
230
 
331
231
  // (https://github.com/ckeditor/ckeditor5-utils/issues/139)
332
232
  // If there's some positioned ancestor of the panel, not only its position must be taken into
333
233
  // consideration (see above) but also its internal scrolls. Scroll have an impact here because `Rect`
334
234
  // is relative to the viewport (it doesn't care about scrolling), while `position: absolute`
335
235
  // must compensate that scrolling.
336
- left += positionedElementAncestor.scrollLeft;
337
- top += positionedElementAncestor.scrollTop;
236
+ moveX += positionedElementAncestor.scrollLeft;
237
+ moveY += positionedElementAncestor.scrollTop;
338
238
 
339
239
  // (https://github.com/ckeditor/ckeditor5-utils/issues/139)
340
240
  // If there's some positioned ancestor of the panel, then its `Rect` includes its CSS `borderWidth`
341
241
  // while `position: absolute` positioning does not consider it.
342
242
  // E.g. `{ position: absolute, top: 0, left: 0 }` means upper left corner of the element,
343
243
  // not upper-left corner of its border.
344
- left -= ancestorBorderWidths.left;
345
- top -= ancestorBorderWidths.top;
244
+ moveX -= ancestorBorderWidths.left;
245
+ moveY -= ancestorBorderWidths.top;
346
246
 
347
- return { left, top };
247
+ rect.moveBy( moveX, moveY );
348
248
  }
349
249
 
350
250
  // DOMRect (also Rect) works in a scroll–independent geometry but `position: absolute` doesn't.
@@ -353,13 +253,172 @@ function shiftRectCoordinatesDueToPositionedAncestor( { left, top }, positionedE
353
253
  // @private
354
254
  // @param {utils/dom/rect~Rect} rect A rect to be converted.
355
255
  // @returns {Object} Object containing `left` and `top` properties, in absolute coordinates.
356
- function getAbsoluteRectCoordinates( { left, top } ) {
256
+ function getRectForAbsolutePositioning( rect ) {
357
257
  const { scrollX, scrollY } = global.window;
358
258
 
359
- return {
360
- left: left + scrollX,
361
- top: top + scrollY
362
- };
259
+ return rect.clone().moveBy( scrollX, scrollY );
260
+ }
261
+
262
+ /**
263
+ * A position class which instances are created and used by the {@link module:utils/dom/position~getOptimalPosition} helper.
264
+ *
265
+ * {@link module:utils/dom/position~Position#top} and {@link module:utils/dom/position~Position#left} properties of the position instance
266
+ * translate directly to the `top` and `left` properties in CSS "`position: absolute` coordinate system". If set on the positioned element
267
+ * in DOM, they will make it display it in the right place in the viewport.
268
+ */
269
+ export class Position {
270
+ /**
271
+ * Creates an instance of the {@link module:utils/dom/position~Position} class.
272
+ *
273
+ * @param {module:utils/dom/position~positioningFunction} [positioningFunction] function The function that defines the expected
274
+ * coordinates the positioned element should move to.
275
+ * @param {Object} [options] options object.
276
+ * @param {module:utils/dom/rect~Rect} options.elementRect The positioned element rect.
277
+ * @param {module:utils/dom/rect~Rect} options.targetRect The target element rect.
278
+ * @param {module:utils/dom/rect~Rect} options.viewportRect The viewport rect.
279
+ * @param {HTMLElement|null} [options.positionedElementAncestor] Nearest element ancestor element which CSS position is not "static".
280
+ */
281
+ constructor( positioningFunction, options ) {
282
+ const positioningFunctionOutput = positioningFunction( options.targetRect, options.elementRect, options.viewportRect );
283
+
284
+ // Nameless position for a function that didn't participate.
285
+ if ( !positioningFunctionOutput ) {
286
+ return;
287
+ }
288
+
289
+ const { left, top, name, config } = positioningFunctionOutput;
290
+
291
+ Object.assign( this, { name, config } );
292
+
293
+ this._positioningFunctionCorrdinates = { left, top };
294
+ this._options = options;
295
+
296
+ /**
297
+ * Position name.
298
+ *
299
+ * @readonly
300
+ * @member {String} #name
301
+ */
302
+
303
+ /**
304
+ * Additional position configuration, as passed from the {@link module:utils/dom/position~positioningFunction positioning function}.
305
+ *
306
+ * This object can be use, for instance, to pass through presentation options used by the consumer of the
307
+ * {@link module:utils/dom/position~getOptimalPosition} helper.
308
+ *
309
+ * @readonly
310
+ * @member {Object} #config
311
+ */
312
+ }
313
+
314
+ /**
315
+ * The left value in pixels in the CSS `position: absolute` coordinate system.
316
+ * Set it on the positioned element in DOM to move it to the position.
317
+ *
318
+ * @readonly
319
+ * @type {Number}
320
+ */
321
+ get left() {
322
+ return this._absoluteRect.left;
323
+ }
324
+
325
+ /**
326
+ * The top value in pixels in the CSS `position: absolute` coordinate system.
327
+ * Set it on the positioned element in DOM to move it to the position.
328
+ *
329
+ * @readonly
330
+ * @type {Number}
331
+ */
332
+ get top() {
333
+ return this._absoluteRect.top;
334
+ }
335
+
336
+ /**
337
+ * An intersection area between positioned element and limiter within viewport constraints.
338
+ *
339
+ * @readonly
340
+ * @private
341
+ * @type {Number}
342
+ */
343
+ get _limiterIntersectionArea() {
344
+ const limiterRect = this._options.limiterRect;
345
+
346
+ if ( limiterRect ) {
347
+ const viewportRect = this._options.viewportRect;
348
+
349
+ if ( viewportRect ) {
350
+ // Consider only the part of the limiter which is visible in the viewport. So the limiter is getting limited.
351
+ const limiterViewportIntersectRect = limiterRect.getIntersection( viewportRect );
352
+
353
+ if ( limiterViewportIntersectRect ) {
354
+ // If the limiter is within the viewport, then check the intersection between that part of the
355
+ // limiter and actual position.
356
+ return limiterViewportIntersectRect.getIntersectionArea( this._rect );
357
+ }
358
+ } else {
359
+ return limiterRect.getIntersectionArea( this._rect );
360
+ }
361
+ }
362
+
363
+ return 0;
364
+ }
365
+
366
+ /**
367
+ * An intersection area between positioned element and viewport.
368
+ *
369
+ * @readonly
370
+ * @private
371
+ * @type {Number}
372
+ */
373
+ get _viewportIntersectionArea() {
374
+ const viewportRect = this._options.viewportRect;
375
+
376
+ if ( viewportRect ) {
377
+ return viewportRect.getIntersectionArea( this._rect );
378
+ }
379
+
380
+ return 0;
381
+ }
382
+
383
+ /**
384
+ * An already positioned element rect. A clone of the element rect passed to the constructor
385
+ * but placed in the viewport according to the positioning function.
386
+ *
387
+ * @private
388
+ * @type {module:utils/dom/rect~Rect}
389
+ */
390
+ get _rect() {
391
+ if ( this._cachedRect ) {
392
+ return this._cachedRect;
393
+ }
394
+
395
+ this._cachedRect = this._options.elementRect.clone().moveTo(
396
+ this._positioningFunctionCorrdinates.left,
397
+ this._positioningFunctionCorrdinates.top
398
+ );
399
+
400
+ return this._cachedRect;
401
+ }
402
+
403
+ /**
404
+ * An already absolutely positioned element rect. See ({@link #_rect}).
405
+ *
406
+ * @private
407
+ * @type {module:utils/dom/rect~Rect}
408
+ */
409
+ get _absoluteRect() {
410
+ if ( this._cachedAbsoluteRect ) {
411
+ return this._cachedAbsoluteRect;
412
+ }
413
+
414
+ this._cachedAbsoluteRect = getRectForAbsolutePositioning( this._rect );
415
+
416
+ if ( this._options.positionedElementAncestor ) {
417
+ shiftRectToCompensatePositionedAncestor( this._cachedAbsoluteRect, this._options.positionedElementAncestor );
418
+ }
419
+
420
+ return this._cachedAbsoluteRect;
421
+ }
363
422
  }
364
423
 
365
424
  /**
@@ -381,12 +440,15 @@ function getAbsoluteRectCoordinates( { left, top } ) {
381
440
  */
382
441
 
383
442
  /**
384
- * An array of functions which return {@link module:utils/dom/position~Position} relative
385
- * to the `target`, in the order of preference.
443
+ * An array of positioning functions.
444
+ *
445
+ * **Note**: Positioning functions are processed in the order of preference. The first function that works
446
+ * in the current environment (e.g. offers the complete fit in the viewport geometry) will be picked by
447
+ * `getOptimalPosition()`.
386
448
  *
387
- * **Note**: If a function returns `null`, it is ignored by the `getOptimalPosition()`.
449
+ * **Note**: Any positioning function returning `null` is ignored.
388
450
  *
389
- * @member {Array.<Function>} #positions
451
+ * @member {Array.<module:utils/dom/position~positioningFunction>} #positions
390
452
  */
391
453
 
392
454
  /**
@@ -404,12 +466,53 @@ function getAbsoluteRectCoordinates( { left, top } ) {
404
466
  */
405
467
 
406
468
  /**
407
- * An object describing a position in `position: absolute` coordinate
408
- * system, along with position name.
469
+ * Viewport offset config object. It restricts the visible viewport available to the `getOptimalPosition()` from each side.
409
470
  *
410
- * @typedef {Object} module:utils/dom/position~Position
471
+ * {
472
+ * top: 50,
473
+ * right: 50,
474
+ * bottom: 50,
475
+ * left: 50
476
+ * }
477
+ *
478
+ * @member {Object} #viewportOffsetConfig
479
+ */
480
+
481
+ /**
482
+ * A positioning function which, based on positioned element and target {@link module:utils/dom/rect~Rect Rects}, returns rect coordinates
483
+ * representing the geometrical relation between them. Used by the {@link module:utils/dom/position~getOptimalPosition} helper.
484
+ *
485
+ * // This simple position will place the element directly under the target, in the middle:
486
+ * //
487
+ * // [ Target ]
488
+ * // +-----------------+
489
+ * // | Element |
490
+ * // +-----------------+
491
+ * //
492
+ * const position = ( targetRect, elementRect, [ viewportRect ] ) => ( {
493
+ * top: targetRect.bottom,
494
+ * left: targetRect.left + targetRect.width / 2 - elementRect.width / 2,
495
+ * name: 'bottomMiddle',
496
+ *
497
+ * // Note: The config is optional.
498
+ * config: {
499
+ * zIndex: '999'
500
+ * }
501
+ * } );
411
502
  *
412
- * @property {Number} top Top position offset.
413
- * @property {Number} left Left position offset.
414
- * @property {String} name Name of the position.
503
+ * @callback module:utils/dom/position~positioningFunction
504
+ * @param {module:utils/dom/rect~Rect} elementRect The rect of the element to be positioned.
505
+ * @param {module:utils/dom/rect~Rect} targetRect The rect of the target the element (its rect) is relatively positioned to.
506
+ * @param {module:utils/dom/rect~Rect} viewportRect The rect of the visual browser viewport.
507
+ * @returns {Object|null} return When the function returns `null`, it will not be considered by
508
+ * {@link module:utils/dom/position~getOptimalPosition}.
509
+ * @returns {Number} return.top The `top` value of the element rect that would represent the position.
510
+ * @returns {Number} return.left The `left` value of the element rect that would represent the position.
511
+ * @returns {Number} return.name The name of the position. It helps the user of the {@link module:utils/dom/position~getOptimalPosition}
512
+ * helper to recognize different positioning function results. It will pass through to the {@link module:utils/dom/position~Position}
513
+ * returned by the helper.
514
+ * @returns {Number} [return.config] An optional configuration that will pass-through the
515
+ * {@link module:utils/dom/position~getOptimalPosition} helper to the {@link module:utils/dom/position~Position} returned by this helper.
516
+ * This configuration may, for instance, let the user of {@link module:utils/dom/position~getOptimalPosition} know that this particular
517
+ * position comes with a certain presentation.
415
518
  */
package/src/keyboard.js CHANGED
@@ -33,6 +33,7 @@ const modifiersToGlyphsNonMac = {
33
33
  * * `a-z`,
34
34
  * * `0-9`,
35
35
  * * `f1-f12`,
36
+ * * `` ` ``, `-`, `=`, `[`, `]`, `;`, `'`, `,`, `.`, `/`, `\`,
36
37
  * * `arrow(left|up|right|bottom)`,
37
38
  * * `backspace`, `delete`, `enter`, `esc`, `tab`,
38
39
  * * `ctrl`, `cmd`, `shift`, `alt`.
@@ -251,6 +252,11 @@ function generateKnownKeyCodes() {
251
252
  keyCodes[ 'f' + ( code - 111 ) ] = code;
252
253
  }
253
254
 
255
+ // other characters
256
+ for ( const char of '`-=[];\',./\\' ) {
257
+ keyCodes[ char ] = char.charCodeAt( 0 );
258
+ }
259
+
254
260
  return keyCodes;
255
261
  }
256
262
 
@@ -131,7 +131,7 @@ export function add( language, translations, getPluralForm ) {
131
131
  *
132
132
  * @protected
133
133
  * @param {String} language Target language.
134
- * @param {module:utils/translation-service~Message|String} message A message that will be translated.
134
+ * @param {module:utils/translation-service~Message} message A message that will be translated.
135
135
  * @param {Number} [quantity] The number of elements for which a plural form should be picked from the target language dictionary.
136
136
  * @returns {String} Translated sentence.
137
137
  */
package/src/version.js CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  import CKEditorError from './ckeditorerror';
13
13
 
14
- const version = '29.2.0';
14
+ const version = '30.0.0';
15
15
 
16
16
  export default version;
17
17
 
package/CHANGELOG.md DELETED
@@ -1,324 +0,0 @@
1
- Changelog
2
- =========
3
-
4
- All changes in the package are documented in the main repository. See: https://github.com/ckeditor/ckeditor5/blob/master/CHANGELOG.md.
5
-
6
- Changes for the past releases are available below.
7
-
8
- ## [19.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v18.0.0...v19.0.0) (2020-04-29)
9
-
10
- ### MINOR BREAKING CHANGES
11
-
12
- * The `translate` function from the `translation-service` was marked as protected. See [#334](https://github.com/ckeditor/ckeditor5-utils/issues/334).
13
- * The format of stored editor translations has been changed. If you use `window.CKEDITOR_TRANSLATIONS` please see [#334](https://github.com/ckeditor/ckeditor5-utils/issues/334).
14
- * The `getPositionedAncestor()` helper will no longer return the passed element when it is positioned.
15
-
16
- ### MAJOR BREAKING CHANGES
17
-
18
- * `env.isEdge` is no longer available. See [ckeditor/ckeditor5#6202](https://github.com/ckeditor/ckeditor5/issues/6202).
19
-
20
- ### Features
21
-
22
- * Added the support for initializing `Collection` items via the `constructor()`. Closes [ckeditor/ckeditor5#6319](https://github.com/ckeditor/ckeditor5/issues/6319). ([8846e66](https://github.com/ckeditor/ckeditor5-utils/commit/8846e66))
23
- * Provided support for plural forms internalization. Part of [ckeditor/ckeditor5#6526](https://github.com/ckeditor/ckeditor5/issues/6526). ([5f6ea75](https://github.com/ckeditor/ckeditor5-utils/commit/5f6ea75))
24
-
25
- ### Bug fixes
26
-
27
- * Do not execute `ResizeObserver` callbacks when the resized element is invisible (but still in DOM) (see [ckeditor/ckeditor5#6570](https://github.com/ckeditor/ckeditor5/issues/6570)). ([fb13d9d](https://github.com/ckeditor/ckeditor5-utils/commit/fb13d9d))
28
- * Editor will now load correctly in environment with `Symbol` polyfill. Closes [ckeditor/ckeditor5#6489](https://github.com/ckeditor/ckeditor5/issues/6489). ([7cd1f48](https://github.com/ckeditor/ckeditor5-utils/commit/7cd1f48))
29
- * Fixed various cases with typing multi-byte unicode sequences (e.g. emojis). Closes [ckeditor/ckeditor5#3147](https://github.com/ckeditor/ckeditor5/issues/3147). Closes [ckeditor/ckeditor5#6495](https://github.com/ckeditor/ckeditor5/issues/6495). ([6dc1ba6](https://github.com/ckeditor/ckeditor5-utils/commit/6dc1ba6))
30
- * The `getOptimalPosition()` helper should prefer positions that fit inside the viewport even though there are some others that fit better into the limiter. Closes [ckeditor/ckeditor5#6181](https://github.com/ckeditor/ckeditor5/issues/6181). ([7cd1238](https://github.com/ckeditor/ckeditor5-utils/commit/7cd1238))
31
-
32
- ### Other changes
33
-
34
- * Removed `env.isEdge` as Edge is now detected and treated as Chrome. Closes [ckeditor/ckeditor5#6202](https://github.com/ckeditor/ckeditor5/issues/6202). ([2902b30](https://github.com/ckeditor/ckeditor5-utils/commit/2902b30))
35
- * The `getPositionedAncestor()` helper should use `offsetParent` instead of `getComputedStyle()` for performance reasons. Closes [ckeditor/ckeditor5#6573](https://github.com/ckeditor/ckeditor5/issues/6573). ([7939756](https://github.com/ckeditor/ckeditor5-utils/commit/7939756))
36
-
37
-
38
- ## [18.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v17.0.0...v18.0.0) (2020-03-19)
39
-
40
- Internal changes only (updated dependencies, documentation, etc.).
41
-
42
-
43
- ## [17.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v16.0.0...v17.0.0) (2020-02-19)
44
-
45
- ### MINOR BREAKING CHANGES
46
-
47
- * The `getResizeObserver()` helper is no longer available. We recommend using the [`ResizeObserver`](http://ckeditor.com/docs/ckeditor5/latest/api/module_utils_dom_resizeobserver-ResizeObserver.html) class instead.
48
-
49
- ### Features
50
-
51
- * Added iterator interface to the `Config` class. ([1fdf2f1](https://github.com/ckeditor/ckeditor5-utils/commit/1fdf2f1))
52
-
53
- ### Other changes
54
-
55
- * Improved `toMap()` method performance. This results in improved editor data processing speed. Closes [ckeditor/ckeditor5#5854](https://github.com/ckeditor/ckeditor5/issues/5854). ([fef816e](https://github.com/ckeditor/ckeditor5-utils/commit/fef816e))
56
- * Replaced the `getResizeObserver()` helper with the `ResizeObserver` class for performance reasons. See [ckeditor/ckeditor5#6145](https://github.com/ckeditor/ckeditor5/issues/6145). ([05c97f8](https://github.com/ckeditor/ckeditor5-utils/commit/05c97f8))
57
- * The `uid()` helper should be a lot faster. Closes [ckeditor/ckeditor5#6188](https://github.com/ckeditor/ckeditor5/issues/6188). ([b57fc3f](https://github.com/ckeditor/ckeditor5-utils/commit/b57fc3f))
58
-
59
-
60
- ## [16.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v15.0.0...v16.0.0) (2019-12-04)
61
-
62
- ### Bug fixes
63
-
64
- * Improved error rethrowing by replacing the error stack. Closes [ckeditor/ckeditor5#5595](https://github.com/ckeditor/ckeditor5/issues/5595). ([7685c0d](https://github.com/ckeditor/ckeditor5-utils/commit/7685c0d))
65
-
66
-
67
- ## [15.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v14.0.0...v15.0.0) (2019-10-23)
68
-
69
- ### Features
70
-
71
- * Implemented the `getResizeObserver()` helper that offers an entry to the native `ResizeObserver` API (see [ckeditor/ckeditor5#416](https://github.com/ckeditor/ckeditor5/issues/416)). ([875d5a4](https://github.com/ckeditor/ckeditor5-utils/commit/875d5a4))
72
- * Introduced `assertEqualMarkup()` test util method. Closes [ckeditor/ckeditor5-paste-from-office#14](https://github.com/ckeditor/ckeditor5-paste-from-office/issues/14). ([ee1655f](https://github.com/ckeditor/ckeditor5-utils/commit/ee1655f))
73
- * Introduced support for creating elements in other XML namespaces. See [ckeditor/ckeditor5#1842](https://github.com/ckeditor/ckeditor5/issues/1842). ([37fbcb9](https://github.com/ckeditor/ckeditor5-utils/commit/37fbcb9))
74
-
75
- Thanks [@Sebobo](https://github.com/Sebobo)!
76
-
77
- ### Bug fixes
78
-
79
- * `Rect#excludeScrollbarsAndBorders` should support RTL environments. Fixed incorrect output of the method. Closes [#297](https://github.com/ckeditor/ckeditor5-utils/issues/297). ([35f34fc](https://github.com/ckeditor/ckeditor5-utils/commit/35f34fc))
80
-
81
- ### Other changes
82
-
83
- * Introduced the `CKEditorError.rethrowUnexpectedError()` helper. Added custom error handling for the `Emitter#fire()` function. Part of [ckeditor/ckeditor5#1304](https://github.com/ckeditor/ckeditor5/issues/1304). ([1d84705](https://github.com/ckeditor/ckeditor5-utils/commit/1d84705))
84
-
85
-
86
- ## [14.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v13.0.1...v14.0.0) (2019-08-26)
87
-
88
- ### Features
89
-
90
- * Add feature detection of Unicode properties entities' support. ([21c0f6b](https://github.com/ckeditor/ckeditor5-utils/commit/21c0f6b))
91
- * Allowed specifying editor content language in `Locale`. Implemented the (UI and content) language direction discovery in `Locale`. Implemented `Locale#uiLanguage`, `Locale#uiLanguageDirection`, `Locale#contentLanguage`, and `Locale#contentLanguageDirection` properties. See [ckeditor/ckeditor5#1151](https://github.com/ckeditor/ckeditor5/issues/1151). ([91c95f3](https://github.com/ckeditor/ckeditor5-utils/commit/91c95f3))
92
-
93
- ### Other changes
94
-
95
- * The issue tracker for this package was moved to https://github.com/ckeditor/ckeditor5/issues. See [ckeditor/ckeditor5#1988](https://github.com/ckeditor/ckeditor5/issues/1988). ([71469ac](https://github.com/ckeditor/ckeditor5-utils/commit/71469ac))
96
- * Removed the CKEditor 5 logger and its usage. Part of [ckeditor/ckeditor5#383](https://github.com/ckeditor/ckeditor5/issues/383). ([584ef1d](https://github.com/ckeditor/ckeditor5-utils/commit/584ef1d))
97
-
98
- ### BREAKING CHANGES
99
-
100
- * The`Locale()` constructor arguments syntax has changed. Please refer to the API documentation to learn more.
101
- * The `Locale#language` property has been deprecated by `Locale#uiLanguage`. Please refer to the API documentation to learn more.
102
- * Removed the CKEditor 5 logger utility.
103
-
104
-
105
- ## [13.0.1](https://github.com/ckeditor/ckeditor5-utils/compare/v13.0.0...v13.0.1) (2019-07-10)
106
-
107
- Internal changes only (updated dependencies, documentation, etc.).
108
-
109
-
110
- ## [13.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v12.1.1...v13.0.0) (2019-07-04)
111
-
112
- ### Features
113
-
114
- * Added `env.isAndroid`. ([591f641](https://github.com/ckeditor/ckeditor5-utils/commit/591f641))
115
-
116
- ### Other changes
117
-
118
- * Added context as second required argument to the `CKEditorError`'s constructor, changed `isCKEditorError()` method to `is()`. Introduced the `areConnectedThroughProperties()` utility. See [ckeditor/ckeditor5-watchdog#1](https://github.com/ckeditor/ckeditor5-watchdog/issues/1). ([bacc764](https://github.com/ckeditor/ckeditor5-utils/commit/bacc764))
119
-
120
- ### BREAKING CHANGES
121
-
122
- * The list of `CKEditorError()`'s parameters was changed – now it requires the message, context and then data. The `isCKEditorError()` method was renamed to `is()`.
123
-
124
-
125
- ## [12.1.1](https://github.com/ckeditor/ckeditor5-utils/compare/v12.1.0...v12.1.1) (2019-06-05)
126
-
127
- Internal changes only (updated dependencies, documentation, etc.).
128
-
129
-
130
- ## [12.1.0](https://github.com/ckeditor/ckeditor5-utils/compare/v12.0.0...v12.1.0) (2019-04-10)
131
-
132
- ### Features
133
-
134
- * Added `isSafari` property and `isSafari()` helper to the `env` module. See: [ckeditor/ckeditor5#1463](https://github.com/ckeditor/ckeditor5/issues/1463). ([f1ba6ae](https://github.com/ckeditor/ckeditor5-utils/commit/f1ba6ae))
135
- * Made `FocusTracker#focusedElement` observable to bring support for multi-root editors (see [ckeditor/ckeditor5#1599](https://github.com/ckeditor/ckeditor5/issues/1599)). ([952d440](https://github.com/ckeditor/ckeditor5-utils/commit/952d440))
136
-
137
-
138
- ## [12.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v11.1.0...v12.0.0) (2019-02-28)
139
-
140
- ### Features
141
-
142
- * Introduce `Collection.has()` method. Closes [#266](https://github.com/ckeditor/ckeditor5-utils/issues/266). ([312d55e](https://github.com/ckeditor/ckeditor5-utils/commit/312d55e))
143
-
144
- ### Bug fixes
145
-
146
- * Prevent infinite loops on `.once()`. Closes [#272](https://github.com/ckeditor/ckeditor5-utils/issues/272). Closes [#204](https://github.com/ckeditor/ckeditor5-utils/issues/204). ([54b8108](https://github.com/ckeditor/ckeditor5-utils/commit/54b8108))
147
- * Fixed memory leaks during editor initialization and destruction (see [ckeditor/ckeditor5#1341](https://github.com/ckeditor/ckeditor5/issues/1341)). ([94bc59e](https://github.com/ckeditor/ckeditor5-utils/commit/94bc59e))
148
-
149
- ### Other changes
150
-
151
- * Configuration options should be cloned to prevent features from altering the original values. Closes [#257](https://github.com/ckeditor/ckeditor5-utils/issues/257). ([7981d4e](https://github.com/ckeditor/ckeditor5-utils/commit/7981d4e))
152
- * DOM Elements will not be cloned when returned from config.get. Closes [#264](https://github.com/ckeditor/ckeditor5-utils/issues/264). ([4ad23b1](https://github.com/ckeditor/ckeditor5-utils/commit/4ad23b1))
153
- * Optimized `diff()` function to use `fastDiff()` function internally for large data sets. Closes [#269](https://github.com/ckeditor/ckeditor5-utils/issues/269). ([ee9bed0](https://github.com/ckeditor/ckeditor5-utils/commit/ee9bed0))
154
- * Replaced `for..of` statement in `EventEmitter` with `Array.prototype.forEach`. This changes allows building a React application using `create-react-app@2`. Closes [ckeditor/ckeditor5-react#40](https://github.com/ckeditor/ckeditor5-react/issues/40). ([900b54b](https://github.com/ckeditor/ckeditor5-utils/commit/900b54b))
155
-
156
- ### BREAKING CHANGES
157
-
158
- * Upgraded minimal versions of Node to `8.0.0` and npm to `5.7.1`. See: [ckeditor/ckeditor5#1507](https://github.com/ckeditor/ckeditor5/issues/1507). ([612ea3c](https://github.com/ckeditor/ckeditor5-cloud-services/commit/612ea3c))
159
-
160
-
161
- ## [11.1.0](https://github.com/ckeditor/ckeditor5-utils/compare/v11.0.0...v11.1.0) (2018-12-05)
162
-
163
- ### Features
164
-
165
- * Implemented `env#isGecko()`. See [ckeditor/ckeditor5-engine#1439](https://github.com/ckeditor/ckeditor5-engine/issues/1439). ([53b7c94](https://github.com/ckeditor/ckeditor5-utils/commit/53b7c94))
166
-
167
- ### Other changes
168
-
169
- * Vairous fixes in the API docs. Thanks to [@denisname](https://github.com/denisname)!
170
-
171
-
172
- ## [11.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v10.2.1...v11.0.0) (2018-10-08)
173
-
174
- ### Other changes
175
-
176
- * Removed the `lodash` library from this package (a modular `lodash` build has been kept under `src/lib/lodash/`). We now recommend using `lodash-es` directly. Closes [#251](https://github.com/ckeditor/ckeditor5-utils/issues/251). ([637c9e3](https://github.com/ckeditor/ckeditor5-utils/commit/637c9e3))
177
-
178
- ### BREAKING CHANGES
179
-
180
- * Removed the `lodash` library from this package (a modular `lodash` build has been kept under `src/lib/lodash/`). We now recommend using `lodash-es` directly.
181
-
182
-
183
- ## [10.2.1](https://github.com/ckeditor/ckeditor5-utils/compare/v10.2.0...v10.2.1) (2018-07-18)
184
-
185
- Internal changes only (updated dependencies, documentation, etc.).
186
-
187
-
188
- ## [10.2.0](https://github.com/ckeditor/ckeditor5-utils/compare/v10.1.0...v10.2.0) (2018-07-18)
189
-
190
- ### Features
191
-
192
- * Implemented a module exposing the `CKEDIOR_VERSION` to the global scope. Closes [ckeditor/ckeditor5#1005](https://github.com/ckeditor/ckeditor5/issues/1005). ([3546ac4](https://github.com/ckeditor/ckeditor5-utils/commit/3546ac4))
193
- * Introduced `env.isEdge`. ([13d4af4](https://github.com/ckeditor/ckeditor5-utils/commit/13d4af4))
194
-
195
- ### Bug fixes
196
-
197
- * The `isWindow()` helper should work in the Electron environment. Closes [ckeditor/ckeditor5#879](https://github.com/ckeditor/ckeditor5/issues/879). ([d561151](https://github.com/ckeditor/ckeditor5-utils/commit/d561151))
198
-
199
-
200
- ## [10.1.0](https://github.com/ckeditor/ckeditor5-utils/compare/v10.0.0...v10.1.0) (2018-06-21)
201
-
202
- ### Features
203
-
204
- * Introduced `set:{property}` event in `ObservableMixin`. Closes [#171](https://github.com/ckeditor/ckeditor5-utils/issues/171). ([6ef1246](https://github.com/ckeditor/ckeditor5-utils/commit/6ef1246))
205
- * Introduced `fastDiff()` function. Closes [#235](https://github.com/ckeditor/ckeditor5-utils/issues/235). ([81fefc9](https://github.com/ckeditor/ckeditor5-utils/commit/81fefc9))
206
-
207
- ### Bug fixes
208
-
209
- * Error should not be thrown when scrolling the viewport from within an iframe in a different domain. Closes [ckeditor/ckeditor5#930](https://github.com/ckeditor/ckeditor5/issues/930). ([ad4656e](https://github.com/ckeditor/ckeditor5-utils/commit/ad4656e))
210
-
211
-
212
- ## [10.0.0](https://github.com/ckeditor/ckeditor5-utils/compare/v1.0.0-beta.4...v10.0.0) (2018-04-25)
213
-
214
- ### Other changes
215
-
216
- * Changed the license to GPL2+ only. See [ckeditor/ckeditor5#991](https://github.com/ckeditor/ckeditor5/issues/991). ([3177252](https://github.com/ckeditor/ckeditor5-utils/commit/3177252))
217
-
218
- ### BREAKING CHANGES
219
-
220
- * The license under which CKEditor 5 is released has been changed from a triple GPL, LGPL and MPL license to a GPL2+ only. See [ckeditor/ckeditor5#991](https://github.com/ckeditor/ckeditor5/issues/991) for more information.
221
-
222
-
223
- ## [1.0.0-beta.4](https://github.com/ckeditor/ckeditor5-utils/compare/v1.0.0-beta.2...v1.0.0-beta.4) (2018-04-19)
224
-
225
- Internal changes only (updated dependencies, documentation, etc.).
226
-
227
-
228
- ## [1.0.0-beta.2](https://github.com/ckeditor/ckeditor5-utils/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2018-04-10)
229
-
230
- Internal changes only (updated dependencies, documentation, etc.).
231
-
232
-
233
- ## [1.0.0-beta.1](https://github.com/ckeditor/ckeditor5-utils/compare/v1.0.0-alpha.2...v1.0.0-beta.1) (2018-03-15)
234
-
235
- ### Features
236
-
237
- * Introduce `bind().toMany()` binding chain in `ObservableMixin`. Closes [#224](https://github.com/ckeditor/ckeditor5-utils/issues/224). ([cfa7d0e](https://github.com/ckeditor/ckeditor5-utils/commit/cfa7d0e))
238
- * Introduced skipping items when binding collections. Closes [#215](https://github.com/ckeditor/ckeditor5-utils/issues/215). Closes https://github.com/ckeditor/ckeditor5-ui/issues/92. ([6e0d063](https://github.com/ckeditor/ckeditor5-utils/commit/6e0d063))
239
-
240
- ### Bug fixes
241
-
242
- * `Rect.getDomRangeRects()` should not throw if the provided DOM range starts in a text node. Closes [ckeditor/ckeditor5-ui#317](https://github.com/ckeditor/ckeditor5-ui/issues/317). ([bfa55e9](https://github.com/ckeditor/ckeditor5-utils/commit/bfa55e9))
243
- * Bulletproofed `isDomNode()` helper when used in iframes. Removed `isWindow()` logic from the helper. Closes [#201](https://github.com/ckeditor/ckeditor5-utils/issues/201). ([84ccda2](https://github.com/ckeditor/ckeditor5-utils/commit/84ccda2))
244
- * Long keystrokes should be handled properly by getEnvKeystrokeText on Mac. Added support for ⇧ and ⌥ modifiers. Closes [#206](https://github.com/ckeditor/ckeditor5-utils/issues/206). ([d8443e2](https://github.com/ckeditor/ckeditor5-utils/commit/d8443e2))
245
-
246
- ### Other changes
247
-
248
- * `ObservableMixin#unbind()` should not throw if used for an attribute which is not bound. Closes [#5](https://github.com/ckeditor/ckeditor5-utils/issues/5). ([848a818](https://github.com/ckeditor/ckeditor5-utils/commit/848a818))
249
- * Aligned behaviors of `EmitterMixin` methods responsible for adding end removing listeners. Closes [#144](https://github.com/ckeditor/ckeditor5-utils/issues/144). ([460d7f4](https://github.com/ckeditor/ckeditor5-utils/commit/460d7f4))
250
-
251
- The `emitter.on()` now has the same behavior as `emitter.listenTo( emitter )` as well as `emitter.off()` is the same as `emitter.stopListening( emitter )`. This made `emitter.stopListening()` correctly remove all listeners added in any way to it which prevents memory leaks.
252
- * Aligned code to the new Translation Service ([ckeditor/ckeditor5#624](https://github.com/ckeditor/ckeditor5/issues/624)). ([a51767a](https://github.com/ckeditor/ckeditor5-utils/commit/a51767a))
253
- * Introduced the `isText()` helper. Closes [#214](https://github.com/ckeditor/ckeditor5-utils/issues/214). ([a9a6bec](https://github.com/ckeditor/ckeditor5-utils/commit/a9a6bec))
254
- * Renamed `env.mac` to `env.isMac`. Closes [#222](https://github.com/ckeditor/ckeditor5-utils/issues/222). ([dc6b226](https://github.com/ckeditor/ckeditor5-utils/commit/dc6b226))
255
- * Renamed `isDomNode()` to `isNode()`. Closes [#219](https://github.com/ckeditor/ckeditor5-utils/issues/219). ([1823196](https://github.com/ckeditor/ckeditor5-utils/commit/1823196))
256
-
257
- ### BREAKING CHANGES
258
-
259
- * Renamed `env.mac` to `env.isMac`.
260
- * `isDomNode()` was renamed to `isNode()`.
261
-
262
-
263
- ## [1.0.0-alpha.2](https://github.com/ckeditor/ckeditor5-utils/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2017-11-14)
264
-
265
- ### Bug fixes
266
-
267
- * Removed a period at the end of an error message because some browsers included the period in links to errors. Closes [#193](https://github.com/ckeditor/ckeditor5-utils/issues/193). ([fdebc2f](https://github.com/ckeditor/ckeditor5-utils/commit/fdebc2f))
268
-
269
-
270
- ## [1.0.0-alpha.1](https://github.com/ckeditor/ckeditor5-utils/compare/v0.10.0...v1.0.0-alpha.1) (2017-10-03)
271
-
272
- ### Features
273
-
274
- * Scrolling DOM utilities should support multi-window scenarios. Closes [#175](https://github.com/ckeditor/ckeditor5-utils/issues/175). ([a5c27ea](https://github.com/ckeditor/ckeditor5-utils/commit/a5c27ea))
275
-
276
- ### Other changes
277
-
278
- * `CKEditorError#message`, `log.error()` and `log.warn()` will contain a link to the error documentation. Closes [#185](https://github.com/ckeditor/ckeditor5-utils/issues/185). ([b7a00c9](https://github.com/ckeditor/ckeditor5-utils/commit/b7a00c9))
279
-
280
-
281
- ## [0.10.0](https://github.com/ckeditor/ckeditor5-utils/compare/v0.9.1...v0.10.0) (2017-09-03)
282
-
283
- ### Bug fixes
284
-
285
- * `FocusTracker` should remain in sync when multiple `blur` events are followed by the `focus` event. Closes [#159](https://github.com/ckeditor/ckeditor5-utils/issues/159). ([0ff1b34](https://github.com/ckeditor/ckeditor5-utils/commit/0ff1b34))
286
-
287
- ### Features
288
-
289
- * `KeystrokeHandler` should support priorities and proper keystroke cancelling. Closes [#180](https://github.com/ckeditor/ckeditor5-utils/issues/180). ([14af24c](https://github.com/ckeditor/ckeditor5-utils/commit/14af24c))
290
- * Added support for `'space'` key code in the `parseKeystroke()` helper. Closes [#169](https://github.com/ckeditor/ckeditor5-utils/issues/169). ([f86b1ad](https://github.com/ckeditor/ckeditor5-utils/commit/f86b1ad))
291
- * Introduced `ObservableMixin#decorate()` and support for setting `EmitterMixin#fire()`'s return value by listeners. Closes [#162](https://github.com/ckeditor/ckeditor5-utils/issues/162). ([377c875](https://github.com/ckeditor/ckeditor5-utils/commit/377c875))
292
- * Introduced a static `Rect.getDomRangeRects()` method for external usage. Closes [#168](https://github.com/ckeditor/ckeditor5-utils/issues/168). ([f67aea1](https://github.com/ckeditor/ckeditor5-utils/commit/f67aea1))
293
-
294
- ### Other changes
295
-
296
- * The `getOptimalPosition()` utility should accept the target option defined as a function. Closes [#157](https://github.com/ckeditor/ckeditor5-utils/issues/157). ([d63abae](https://github.com/ckeditor/ckeditor5-utils/commit/d63abae))
297
-
298
-
299
- ## [0.9.1](https://github.com/ckeditor/ckeditor5-utils/compare/v0.9.0...v0.9.1) (2017-05-07)
300
-
301
- ### Bug fixes
302
-
303
- * The `Rect` utility should work for collapsed DOM Ranges. Closes [#153](https://github.com/ckeditor/ckeditor5-utils/issues/153). ([92aff35](https://github.com/ckeditor/ckeditor5-utils/commit/92aff35))
304
- * The `getOptimalPosition()` utility should consider limiter ancestors with CSS overflow. Closes [#148](https://github.com/ckeditor/ckeditor5-utils/issues/148). ([6bf1741](https://github.com/ckeditor/ckeditor5-utils/commit/6bf1741))
305
-
306
-
307
- ## [0.9.0](https://github.com/ckeditor/ckeditor5-utils/compare/v0.8.0...v0.9.0) (2017-04-05)
308
-
309
- ### Bug fixes
310
-
311
- * The `getOptimalPosition()` utility should work fine when the parent element has a scroll. Closes [#139](https://github.com/ckeditor/ckeditor5-utils/issues/139). ([b878949](https://github.com/ckeditor/ckeditor5-utils/commit/b878949))
312
-
313
- ### Features
314
-
315
- * `Collection.bindTo()` method now is not only available in the `ViewCollection` but in all `Collection`s. Closes [#125](https://github.com/ckeditor/ckeditor5-utils/issues/125). ([4e299be](https://github.com/ckeditor/ckeditor5-utils/commit/4e299be))
316
- * Added the `first()` function. Closes [#130](https://github.com/ckeditor/ckeditor5-utils/issues/130). ([8ab07d2](https://github.com/ckeditor/ckeditor5-utils/commit/8ab07d2))
317
- * Two–way data binding between `Collection` instances. Closes [#132](https://github.com/ckeditor/ckeditor5-utils/issues/132). ([6b79624](https://github.com/ckeditor/ckeditor5-utils/commit/6b79624))
318
-
319
-
320
- ## [0.8.0](https://github.com/ckeditor/ckeditor5-utils/compare/v0.7.0...v0.8.0) (2017-03-06)
321
-
322
- ### Features
323
-
324
- * Added ability to provide default configurations to `Config` constructor. Closes [#126](https://github.com/ckeditor/ckeditor5/issues/126). ([16a2a31](https://github.com/ckeditor/ckeditor5-utils/commit/16a2a31))