6 `Polymer.CoreResizable` and `Polymer.CoreResizer` are a set of mixins that can be used
7 in Polymer elements to coordinate the flow of resize events between "resizers" (elements
8 that control the size or hidden state of their children) and "resizables" (elements that
9 need to be notified when they are resized or un-hidden by their parents in order to take
10 action on their new measurements).
12 Elements that perform measurement should add the `Core.Resizable` mixin to their
13 Polymer prototype definition and listen for the `core-resize` event on themselves.
14 This event will be fired when they become showing after having been hidden,
15 when they are resized explicitly by a `CoreResizer`, or when the window has been resized.
16 Note, the `core-resize` event is non-bubbling.
18 `CoreResizable`'s must manually call the `resizableAttachedHandler` from the element's
19 `attached` callback and `resizableDetachedHandler` from the element's `detached`
22 @element CoreResizable
27 scope.CoreResizable = {
30 * User must call from `attached` callback
32 * @method resizableAttachedHandler
34 resizableAttachedHandler: function(cb) {
35 cb = cb || this._notifyResizeSelf;
36 this.async(function() {
37 var detail = {callback: cb, hasParentResizer: false};
38 this.fire('core-request-resize', detail);
39 if (!detail.hasParentResizer) {
40 this._boundWindowResizeHandler = cb.bind(this);
41 // log('adding window resize handler', null, this);
42 window.addEventListener('resize', this._boundWindowResizeHandler);
48 * User must call from `detached` callback
50 * @method resizableDetachedHandler
52 resizableDetachedHandler: function() {
53 this.fire('core-request-resize-cancel', null, this, false);
54 if (this._boundWindowResizeHandler) {
55 window.removeEventListener('resize', this._boundWindowResizeHandler);
59 // Private: fire non-bubbling resize event to self; returns whether
60 // preventDefault was called, indicating that children should not
62 _notifyResizeSelf: function() {
63 return this.fire('core-resize', null, this, false).defaultPrevented;
69 `Polymer.CoreResizable` and `Polymer.CoreResizer` are a set of mixins that can be used
70 in Polymer elements to coordinate the flow of resize events between "resizers" (elements
71 that control the size or hidden state of their children) and "resizables" (elements that
72 need to be notified when they are resized or un-hidden by their parents in order to take
73 action on their new measurements).
75 Elements that cause their children to be resized (e.g. a splitter control) or hide/show
76 their children (e.g. overlay) should add the `Core.CoreResizer` mixin to their
77 Polymer prototype definition and then call `this.notifyResize()` any time the element
78 resizes or un-hides its children.
80 `CoreResizer`'s must manually call the `resizerAttachedHandler` from the element's
81 `attached` callback and `resizerDetachedHandler` from the element's `detached`
84 Note: `CoreResizer` extends `CoreResizable`, and can listen for the `core-resize` event
85 on itself if it needs to perform resize work on itself before notifying children.
86 In this case, returning `false` from the `core-resize` event handler (or calling
87 `preventDefault` on the event) will prevent notification of children if required.
90 @extends CoreResizable
95 scope.CoreResizer = Polymer.mixin({
98 * User must call from `attached` callback
100 * @method resizerAttachedHandler
102 resizerAttachedHandler: function() {
103 this.resizableAttachedHandler(this.notifyResize);
104 this._boundResizeRequested = this._boundResizeRequested || this._handleResizeRequested.bind(this);
106 if (this.resizerIsPeer) {
107 listener = this.parentElement || (this.parentNode && this.parentNode.host);
108 listener._resizerPeers = listener._resizerPeers || [];
109 listener._resizerPeers.push(this);
113 listener.addEventListener('core-request-resize', this._boundResizeRequested);
114 this._resizerListener = listener;
118 * User must call from `detached` callback
120 * @method resizerDetachedHandler
122 resizerDetachedHandler: function() {
123 this.resizableDetachedHandler();
124 this._resizerListener.removeEventListener('core-request-resize', this._boundResizeRequested);
128 * User should call when resizing or un-hiding children
130 * @method notifyResize
132 notifyResize: function() {
134 if (!this._notifyResizeSelf()) {
135 // Notify requestors if default was not prevented
136 var r = this.resizeRequestors;
138 for (var i=0; i<r.length; i++) {
140 if (!this.resizerShouldNotify || this.resizerShouldNotify(ri.target)) {
141 // log('notifying resize', null, ri.target, true);
142 ri.callback.apply(ri.target);
151 * User should implement to introduce filtering when notifying children.
152 * Generally, children that are hidden by the CoreResizer (e.g. non-active
153 * pages) need not be notified during resize, since they will be notified
154 * again when becoming un-hidden.
156 * Return `true` if CoreResizable passed as argument should be notified of
159 * @method resizeerShouldNotify
160 * @param {Element} el
162 // resizeerShouldNotify: function(el) { } // User to implement if needed
165 * Set to `true` if the resizer is actually a peer to the elements it
166 * resizes (e.g. splitter); in this case it will listen for resize requests
167 * events from its peers on its parent.
169 * @property resizerIsPeer
174 // Private: Handle requests for resize
175 _handleResizeRequested: function(e) {
176 var target = e.path[0];
177 if ((target == this) ||
178 (target == this._resizerListener) ||
179 (this._resizerPeers && this._resizerPeers.indexOf(target) < 0)) {
182 // log('resize requested', target, this);
183 if (!this.resizeRequestors) {
184 this.resizeRequestors = [];
186 this.resizeRequestors.push({target: target, callback: e.detail.callback});
187 target.addEventListener('core-request-resize-cancel', this._cancelResizeRequested.bind(this));
188 e.detail.hasParentResizer = true;
192 // Private: Handle cancellation requests for resize
193 _cancelResizeRequested: function(e) {
194 // Exit early if we're already out of the DOM (resizeRequestors will already be null)
195 if (this.resizeRequestors) {
196 for (var i=0; i<this.resizeRequestors.length; i++) {
197 if (this.resizeRequestors[i].target == e.target) {
198 // log('resizeCanceled', e.target, this);
199 this.resizeRequestors.splice(i, 1);
206 }, Polymer.CoreResizable);
208 // function prettyName(el) {
209 // return el.localName + (el.id ? '#' : '') + el.id;
212 // function log(what, from, to, group) {
213 // var args = [what];
215 // args.push('from ' + prettyName(from));
218 // args.push('to ' + prettyName(to));
221 // console.group.apply(console, args);
223 // console.log.apply(console, args);
227 // function logEnd() {
228 // console.groupEnd();