UNPKG

13.3 kBJavaScriptView Raw
1/***
2 * A Resizer plugin that can be used to auto-resize a grid and/or resize with fixed dimensions.
3 * When fixed height is defined, it will auto-resize only the width and vice versa with the width defined.
4 * You can also choose to use the flag "enableAutoSizeColumns" if you want to the plugin to
5 * automatically call the grid "autosizeColumns()" method after each resize.
6 *
7 * USAGE:
8 *
9 * Add the "slick.resizer.js" file and register it with the grid.
10 *
11 * You can specify certain options as arguments when instantiating the plugin like so:
12 * var resizer = new Slick.Plugins.Resizer({
13 * container: '#gridContainer',
14 * rightPadding: 15,
15 * bottomPadding: 20,
16 * minHeight: 180,
17 * minWidth: 300,
18 * });
19 * grid.registerPlugin(resizer);
20 *
21 *
22 * The plugin exposes the following events:
23 *
24 * onGridAfterResize: Fired after the grid got resized. You can customize the menu or dismiss it by returning false.
25 * Event args:
26 * grid: Reference to the grid.
27 * dimensions: Resized grid dimensions used
28 *
29 * onGridBeforeResize: Fired before the grid gets resized. You can customize the menu or dismiss it by returning false.
30 * Event args:
31 * grid: Reference to the grid.
32 *
33 *
34 * @param {Object} options available plugin options that can be passed in the constructor:
35 * container: (REQUIRED) DOM element selector of the page container, basically what element in the page will be used to calculate the available space
36 * gridContainer: DOM element selector of the grid container, optional but when provided it will be resized with same size as the grid (typically a container holding the grid and extra custom footer/pagination)
37 * applyResizeToContainer: Defaults to false, do we want to apply the resized dimentions to the grid container as well?
38 * rightPadding: Defaults to 0, right side padding to remove from the total dimension
39 * bottomPadding: Defaults to 20, bottom padding to remove from the total dimension
40 * minHeight: Defaults to 180, minimum height of the grid
41 * minWidth: Defaults to 300, minimum width of the grid
42 * maxHeight: Maximum height of the grid
43 * maxWidth: Maximum width of the grid
44 * calculateAvailableSizeBy: Defaults to "window", which DOM element ("container" or "window") are we using to calculate the available size for the grid?
45 *
46 * @class Slick.Plugins.Resizer
47 * @constructor
48 */
49
50'use strict';
51
52(function ($) {
53 // register namespace
54 $.extend(true, window, {
55 "Slick": {
56 "Plugins": {
57 "Resizer": Resizer
58 }
59 }
60 });
61
62 function Resizer(options, fixedDimensions) {
63 // global variables, height/width are in pixels
64 var DATAGRID_MIN_HEIGHT = 180;
65 var DATAGRID_MIN_WIDTH = 300;
66 var DATAGRID_BOTTOM_PADDING = 20;
67
68 var _self = this;
69 var _fixedHeight;
70 var _fixedWidth;
71 var _grid;
72 var _gridOptions;
73 var _gridUid;
74 var _lastDimensions;
75 var _timer;
76 var _resizePaused = false;
77 var _gridDomElm;
78 var _pageContainerElm;
79 var _gridContainerElm;
80 var _defaults = {
81 bottomPadding: 20,
82 applyResizeToContainer: false,
83 minHeight: 180,
84 minWidth: 300,
85 rightPadding: 0
86 };
87
88 function init(grid) {
89 options = $.extend(true, {}, _defaults, options);
90 _grid = grid;
91 _gridOptions = _grid.getOptions();
92 _gridUid = _grid.getUID();
93 _gridDomElm = $(_grid.getContainerNode());
94 _pageContainerElm = $(options.container);
95 if (options.gridContainer) {
96 _gridContainerElm = $(options.gridContainer);
97 }
98
99 if (fixedDimensions) {
100 _fixedHeight = fixedDimensions.height;
101 _fixedWidth = fixedDimensions.width;
102 }
103
104 if (_gridOptions) {
105 bindAutoResizeDataGrid();
106 }
107 }
108
109 /** Bind an auto resize trigger on the datagrid, if that is enable then it will resize itself to the available space
110 * Options: we could also provide a % factor to resize on each height/width independently
111 */
112 function bindAutoResizeDataGrid(newSizes) {
113 // if we can't find the grid to resize, return without binding anything
114 if (_gridDomElm !== undefined || _gridDomElm.offset() !== undefined) {
115 // -- 1st resize the datagrid size at first load (we need this because the .on event is not triggered on first load)
116 // -- also we add a slight delay (in ms) so that we resize after the grid render is done
117 resizeGrid(0, newSizes, null);
118
119 // -- 2nd bind a trigger on the Window DOM element, so that it happens also when resizing after first load
120 // -- bind auto-resize to Window object only if it exist
121 $(window).on('resize.grid.' + _gridUid, function (event) {
122 _self.onGridBeforeResize.notify({ grid: _grid }, event, _self);
123
124 // unless the resizer is paused, let's go and resize the grid
125 if (!_resizePaused) {
126 // for some yet unknown reason, calling the resize twice removes any stuttering/flickering
127 // when changing the height and makes it much smoother experience
128 resizeGrid(0, newSizes, event);
129 resizeGrid(0, newSizes, event);
130 }
131 });
132 }
133 }
134
135 /**
136 * Calculate the datagrid new height/width from the available space, also consider that a % factor might be applied to calculation
137 */
138 function calculateGridNewDimensions() {
139 if (!window || _pageContainerElm === undefined || _gridDomElm === undefined || _gridDomElm.offset() === undefined) {
140 return null;
141 }
142
143 // calculate bottom padding
144 var bottomPadding = (options && options.bottomPadding !== undefined) ? options.bottomPadding : DATAGRID_BOTTOM_PADDING;
145
146 var gridHeight = 0;
147 var gridOffsetTop = 0;
148
149 // which DOM element are we using to calculate the available size for the grid?
150 // defaults to "window"
151 if (options.calculateAvailableSizeBy === 'container') {
152 // uses the container's height to calculate grid height without any top offset
153 gridHeight = _pageContainerElm.height() || 0;
154 } else {
155 // uses the browser's window height with its top offset to calculate grid height
156 gridHeight = window.innerHeight || 0;
157 var coordOffsetTop = _gridDomElm.offset();
158 gridOffsetTop = (coordOffsetTop !== undefined) ? coordOffsetTop.top : 0;
159 }
160
161 var availableHeight = gridHeight - gridOffsetTop - bottomPadding;
162 var availableWidth = _pageContainerElm.width() || window.innerWidth || 0;
163 var maxHeight = options && options.maxHeight || undefined;
164 var minHeight = (options && options.minHeight !== undefined) ? options.minHeight : DATAGRID_MIN_HEIGHT;
165 var maxWidth = options && options.maxWidth || undefined;
166 var minWidth = (options && options.minWidth !== undefined) ? options.minWidth : DATAGRID_MIN_WIDTH;
167
168 var newHeight = availableHeight;
169 var newWidth = (options && options.rightPadding) ? availableWidth - options.rightPadding : availableWidth;
170
171 // optionally (when defined), make sure that grid height & width are within their thresholds
172 if (newHeight < minHeight) {
173 newHeight = minHeight;
174 }
175 if (maxHeight && newHeight > maxHeight) {
176 newHeight = maxHeight;
177 }
178 if (newWidth < minWidth) {
179 newWidth = minWidth;
180 }
181 if (maxWidth && newWidth > maxWidth) {
182 newWidth = maxWidth;
183 }
184
185 // return the new dimensions unless a fixed height/width was defined
186 return {
187 height: _fixedHeight || newHeight,
188 width: _fixedWidth || newWidth
189 };
190 }
191
192 /** Destroy function when element is destroyed */
193 function destroy() {
194 _self.onGridBeforeResize.unsubscribe();
195 _self.onGridAfterResize.unsubscribe();
196 $(window).off('resize.grid.' + _gridUid);
197 }
198
199 /**
200 * Return the last resize dimensions used by the service
201 * @return {object} last dimensions (height: number, width: number)
202 */
203 function getLastResizeDimensions() {
204 return _lastDimensions;
205 }
206
207 /**
208 * Provide the possibility to pause the resizer for some time, until user decides to re-enabled it later if he wish to.
209 * @param {boolean} isResizePaused are we pausing the resizer?
210 */
211 function pauseResizer(isResizePaused) {
212 _resizePaused = isResizePaused;
213 }
214
215 /**
216 * Resize the datagrid to fit the browser height & width.
217 * @param {number} delay to wait before resizing, defaults to 0 (in milliseconds)
218 * @param {object} newSizes can optionally be passed (height: number, width: number)
219 * @param {object} event that triggered the resize, defaults to null
220 * @return If the browser supports it, we can return a Promise that would resolve with the new dimensions
221 */
222 function resizeGrid(delay, newSizes, event) {
223 // because of the javascript async nature, we might want to delay the resize a little bit
224 delay = delay || 0;
225
226 // return a Promise when supported by the browser
227 if (typeof Promise === 'function') {
228 return new Promise(function (resolve) {
229 if (delay > 0) {
230 clearTimeout(_timer);
231 _timer = setTimeout(function () {
232 resolve(resizeGridCallback(newSizes, event));
233 }, delay);
234 } else {
235 resolve(resizeGridCallback(newSizes, event));
236 }
237 });
238 } else {
239 // OR no return when Promise isn't supported
240 if (delay > 0) {
241 clearTimeout(_timer);
242 _timer = setTimeout(function () {
243 resizeGridCallback(newSizes, event);
244 }, delay);
245 } else {
246 resizeGridCallback(newSizes, event);
247 }
248 }
249 }
250
251 function resizeGridCallback(newSizes, event) {
252 var lastDimensions = resizeGridWithDimensions(newSizes);
253 _self.onGridAfterResize.notify({ grid: _grid, dimensions: lastDimensions }, event, _self);
254 return lastDimensions;
255 }
256
257 function resizeGridWithDimensions(newSizes) {
258 // calculate the available sizes with minimum height defined as a varant
259 var availableDimensions = calculateGridNewDimensions();
260
261 if ((newSizes || availableDimensions) && _gridDomElm && _gridDomElm.length > 0) {
262 try {
263 // get the new sizes, if new sizes are passed (not 0), we will use them else use available space
264 // basically if user passes 1 of the dimension, let say he passes just the height,
265 // we will use the height as a fixed height but the width will be resized by it's available space
266 var newHeight = (newSizes && newSizes.height) ? newSizes.height : availableDimensions.height;
267 var newWidth = (newSizes && newSizes.width) ? newSizes.width : availableDimensions.width;
268
269 // apply these new height/width to the datagrid
270 if (!_gridOptions.autoHeight) {
271 _gridDomElm.height(newHeight);
272 if (options.gridContainer && options.applyResizeToContainer) {
273 _gridContainerElm.height(newHeight);
274 }
275 }
276
277 _gridDomElm.width(newWidth);
278 if (options.gridContainer && options.applyResizeToContainer) {
279 _gridContainerElm.width(newWidth);
280 }
281
282 // resize the slickgrid canvas on all browser except some IE versions
283 // exclude all IE below IE11
284 // IE11 wants to be a better standard (W3C) follower (finally) they even changed their appName output to also have 'Netscape'
285 if (new RegExp('MSIE [6-8]').exec(navigator.userAgent) === null && _grid && _grid.resizeCanvas) {
286 _grid.resizeCanvas();
287 }
288
289 // also call the grid auto-size columns so that it takes available when going bigger
290 if (_gridOptions && _gridOptions.enableAutoSizeColumns && _grid.autosizeColumns) {
291 // make sure that the grid still exist (by looking if the Grid UID is found in the DOM tree) to avoid SlickGrid error "missing stylesheet"
292 if (_gridUid && ($('.' + _gridUid).length > 0 || $(_gridDomElm).length > 0)) {
293 _grid.autosizeColumns();
294 }
295 }
296
297 // keep last resized dimensions & resolve them to the Promise
298 _lastDimensions = {
299 height: newHeight,
300 width: newWidth
301 };
302 } catch (e) {
303 destroy();
304 }
305 }
306
307 return _lastDimensions;
308 }
309
310 $.extend(this, {
311 "init": init,
312 "destroy": destroy,
313 "pluginName": "Resizer",
314 "bindAutoResizeDataGrid": bindAutoResizeDataGrid,
315 "getLastResizeDimensions": getLastResizeDimensions,
316 "pauseResizer": pauseResizer,
317 "resizeGrid": resizeGrid,
318
319 "onGridAfterResize": new Slick.Event(),
320 "onGridBeforeResize": new Slick.Event()
321 });
322 }
323})(jQuery);