11import React , { Component , PropTypes } from 'react' ;
22import cloudinary , { Util } from 'cloudinary-core' ;
33import CloudinaryComponent from '../CloudinaryComponent' ;
4-
5- function firstDefined ( ...values ) {
6- for ( let value of values ) {
7- if ( value !== undefined ) return value ;
8- }
9- return undefined ;
10- }
11-
12- function defaultBreakpoints ( width , steps = 100 ) {
13- return steps * Math . ceil ( width / steps ) ;
14- }
15-
16- function closestAbove ( list , value ) {
17- var i ;
18- i = list . length - 2 ;
19- while ( i >= 0 && list [ i ] >= value ) {
20- i -- ;
21- }
22- return list [ i + 1 ] ;
23- }
4+ import debounce from '../../util/debounce' ;
5+ import firstDefined from '../../util/firstDefined' ;
246
257export default class Image extends CloudinaryComponent {
268 constructor ( props , context ) {
279 super ( props , context ) ;
28- console . log ( "Image constructor" ) ;
2910 let options = CloudinaryComponent . normalizeOptions ( context , props ) ;
30- let url = this . getUrl ( options ) ;
3111 this . handleResize = this . handleResize . bind ( this ) ;
3212
3313 let state = { responsive : false , url : "" , breakpoints : defaultBreakpoints } ;
3414 this . state = Object . assign ( state , this . prepareState ( props , context ) ) ;
3515 this . state = state ;
36- console . log ( this ) ;
3716 }
3817
3918 get window ( ) {
4019 return ( this . element && this . element . ownerDocument ) ? ( this . element . ownerDocument . defaultView || window ) : window ;
4120 }
4221
4322 componentWillReceiveProps ( nextProps , nextContext ) {
44- console . log ( "componentWillReceiveProps" , nextProps , nextContext ) ;
4523 let state = this . prepareState ( nextProps , nextContext ) ;
4624 this . setState ( state ) ;
4725 }
@@ -50,80 +28,80 @@ export default class Image extends CloudinaryComponent {
5028 let options = CloudinaryComponent . normalizeOptions ( context , props ) ;
5129 let url = this . getUrl ( options ) ;
5230 let state = { } ;
53- console . log ( "prepareState options " , options ) ;
5431 if ( options . breakpoints !== undefined ) {
5532 state . breakpoints = options . breakpoints ;
5633 }
5734 if ( options . responsive ) {
58- console . log ( "prepareState - responsive" ) ;
5935 state . responsive = true ;
6036 url = this . cloudinary_update ( url , state ) ;
6137 }
6238
6339 let currentState = this . state || { } ;
6440 if ( /* FIXME probably not needed */ Util . isEmpty ( currentState . url ) || url !== currentState . url ) {
65- console . log ( "prepareState setting url " , url ) ;
6641 state . url = url ;
6742 }
6843 return state ;
6944 }
7045
7146 componentWillMount ( ) {
72- console . log ( "componentWillMount" ) ;
7347 super . componentWillMount ( ) ;
7448 }
7549
7650 componentDidMount ( ) {
77- console . log ( "componentDidMount" ) ;
7851 super . componentDidMount ( ) ;
7952 // now that we have a this.element, we need to calculate the URL
8053 let state = this . prepareState ( ) ;
81- if ( state . url !== undefined ) {
82- console . log ( "componentDidMount setting state" ) ;
54+ if ( state . url !== undefined ) {
8355 this . setState ( state ) ;
8456 }
8557 }
8658
8759 componentWillUnmount ( ) {
88- console . log ( "componentWillUnmount" ) ;
89- this . window . removeEventListener ( 'resize' , this . handleResize ) ;
60+ this . element = undefined ;
61+ if ( this . listener ) {
62+ this . listener . cancel ( ) ;
63+ this . window . removeEventListener ( 'resize' , this . listener ) ;
64+ }
65+ this . listener = undefined ;
9066 }
9167
9268 componentWillUpdate ( nextProps , nextState , nextContext ) {
9369 // TODO check responsive. also check for responsive state change.
94- console . log ( "componentWillUpdate" , nextState ) ;
95- if ( nextState . responsive ) {
96- console . log ( "componentWillUpdate - setting listener" ) ;
97- this . window . addEventListener ( 'resize' , this . handleResize ) ;
70+ if ( nextState . responsive ) {
71+ const wait = firstDefined ( nextProps . responsiveDebounce , nextContext . responsiveDebounce , 100 ) ;
72+ if ( this . listener ) {
73+ this . window . removeEventListener ( 'resize' , this . listener ) ;
74+ }
75+ this . listener = debounce ( this . handleResize , wait ) ;
76+ this . window . addEventListener ( 'resize' , this . listener ) ;
9877 }
99-
10078 }
10179
10280 componentDidUpdate ( prevProps , prevState , prevContext ) {
103- console . log ( "componentDidUpdate" ) ;
10481 }
10582
10683 shouldComponentUpdate ( nextProps , nextState , nextContext ) {
107- console . log ( "shouldComponentUpdate" ) ;
10884 return true ;
10985 }
11086
111- handleResize ( e ) {
87+ handleResize ( e ) {
11288 let options = CloudinaryComponent . normalizeOptions ( this . context , this . props ) ;
11389 let url = this . getUrl ( options ) ;
114- if ( this . state . responsive ) {
90+ if ( this . state . responsive ) {
11591 url = this . cloudinary_update ( url ) ;
11692 let partialState = { url : url } ;
117- this . setState ( partialState ) ;
93+ if ( this . element ) {
94+ this . setState ( partialState ) ;
95+ }
11896 }
11997 }
12098
12199 render ( ) {
122- var { public_id, responsive, children, ...options } = CloudinaryComponent . normalizeOptions ( this . props , this . context ) ;
123- console . log ( "render image" , this . _reactInternalInstance . _debugID , this . state . url , this . state . width ) ;
100+ var { public_id, responsive, responsive_debounce , children, ...options } = CloudinaryComponent . normalizeOptions ( this . props ,
101+ this . context ) ;
124102 var attributes = cloudinary . Transformation . new ( options ) . toHtmlAttributes ( ) ;
125103 return (
126- < img { ...attributes } src = { this . state . url } ref = { ( e ) => { this . element = e ; } } />
104+ < img { ...attributes } src = { this . state . url } ref = { ( e ) => { this . element = e ; } } />
127105 ) ;
128106 }
129107
@@ -139,13 +117,11 @@ export default class Image extends CloudinaryComponent {
139117 containerWidth = Util . width ( element ) ;
140118 }
141119 }
142- console . log ( "findContainerWidth returning " , containerWidth ) ;
143120 return containerWidth ;
144121 } ;
145122
146123 applyBreakpoints ( tag , width , steps , options ) {
147- console . log ( "applyBreakpoints" ) ;
148- var ref , ref1 , ref2 , responsive_use_breakpoints ;
124+ var responsive_use_breakpoints ;
149125 options = CloudinaryComponent . normalizeOptions ( this . context , this . props , options ) ;
150126 responsive_use_breakpoints = options . responsiveUseBreakpoints ;
151127 if ( ( ! responsive_use_breakpoints ) || ( responsive_use_breakpoints === 'resize' && ! options . resizing ) ) {
@@ -156,14 +132,13 @@ export default class Image extends CloudinaryComponent {
156132 } ;
157133
158134 calc_breakpoint ( element , width , steps ) {
159- console . log ( "calc_breakpoint" ) ;
160135 var breakpoints , point ;
161136 breakpoints = this . state . breakpoints || defaultBreakpoints ;
162137 if ( Util . isFunction ( breakpoints ) ) {
163138 return breakpoints ( width , steps ) ;
164139 } else {
165140 if ( Util . isString ( breakpoints ) ) {
166- breakpoints = ( ( function ( ) {
141+ breakpoints = ( ( function ( ) {
167142 var j , len , ref , results ;
168143 ref = breakpoints . split ( ',' ) ;
169144 results = [ ] ;
@@ -172,7 +147,7 @@ export default class Image extends CloudinaryComponent {
172147 results . push ( parseInt ( point ) ) ;
173148 }
174149 return results ;
175- } ) ( ) ) . sort ( function ( a , b ) {
150+ } ) ( ) ) . sort ( function ( a , b ) {
176151 return a - b ;
177152 } ) ;
178153 }
@@ -195,8 +170,8 @@ export default class Image extends CloudinaryComponent {
195170 }
196171 return dprString ;
197172 } ;
173+
198174 updateDpr ( dataSrc , roundDpr ) {
199- console . log ( "updateDpr" ) ;
200175 return dataSrc . replace ( / \b d p r _ ( 1 \. 0 | a u t o ) \b / g, 'dpr_' + this . device_pixel_ratio ( roundDpr ) ) ;
201176 } ;
202177
@@ -205,7 +180,7 @@ export default class Image extends CloudinaryComponent {
205180 imageWidth = this . state . width || 0 ;
206181 if ( requiredWidth > imageWidth ) {
207182 imageWidth = requiredWidth ;
208- this . setState ( { width : requiredWidth } ) ;
183+ this . setState ( { width : requiredWidth } ) ;
209184 }
210185 return imageWidth ;
211186 } ;
@@ -214,35 +189,40 @@ export default class Image extends CloudinaryComponent {
214189 var requiredWidth ;
215190 var match ;
216191 let resultUrl = this . updateDpr ( url , options . roundDpr ) ;
217- console . group ( "cloudinary_update" , resultUrl ) ;
218- console . log ( "state" , this . state ) ;
219- if ( options . responsive || this . state && this . state . responsive ) {
220- console . log ( "responsive" ) ;
192+ if ( options . responsive || this . state && this . state . responsive ) {
221193 let containerWidth = this . findContainerWidth ( ) ;
222194 if ( containerWidth !== 0 ) {
223195 if ( / w _ a u t o : b r e a k p o i n t s / . test ( resultUrl ) ) {
224- requiredWidth = this . maxWidth ( containerWidth , this . element ) ;
225- resultUrl = resultUrl . replace ( / w _ a u t o : b r e a k p o i n t s ( [ _ 0 - 9 ] * ) ( : [ 0 - 9 ] + ) ? / , "w_auto:breakpoints$1:" + requiredWidth ) ;
196+ requiredWidth = this . maxWidth ( containerWidth , this . element ) ;
197+ resultUrl = resultUrl . replace ( / w _ a u t o : b r e a k p o i n t s ( [ _ 0 - 9 ] * ) ( : [ 0 - 9 ] + ) ? / ,
198+ "w_auto:breakpoints$1:" + requiredWidth ) ;
226199 } else if ( match = / w _ a u t o ( : ( \d + ) ) ? / . exec ( resultUrl ) ) {
227- requiredWidth = this . applyBreakpoints ( this . element , containerWidth , match [ 2 ] , options ) ;
228- requiredWidth = this . maxWidth ( requiredWidth , this . element ) ;
229- resultUrl = resultUrl . replace ( / w _ a u t o [ ^ , \/ ] * / g, "w_" + requiredWidth ) ;
200+ requiredWidth = this . applyBreakpoints ( this . element , containerWidth , match [ 2 ] , options ) ;
201+ requiredWidth = this . maxWidth ( requiredWidth , this . element ) ;
202+ resultUrl = resultUrl . replace ( / w _ a u t o [ ^ , \/ ] * / g, "w_" + requiredWidth ) ;
230203 }
231- // Util.removeAttribute(this.element, 'width');
232- // if (!options.responsive_preserve_height) {
233- // Util.removeAttribute(this.element, 'height');
234- // }
235204 } else {
236205 resultUrl = "" ;
237206 }
238-
239207 }
240- console . log ( "cloudinary_update returning" , resultUrl ) ;
241- console . groupEnd ( ) ;
242208 return resultUrl ;
243209 }
244210}
245211
246212Image . defaultProps = { } ;
247213Image . contextTypes = CloudinaryComponent . contextTypes ;
248- Image . propTypes = CloudinaryComponent . propTypes ;
214+ Image . propTypes = CloudinaryComponent . propTypes ;
215+
216+
217+ function defaultBreakpoints ( width , steps = 100 ) {
218+ return steps * Math . ceil ( width / steps ) ;
219+ }
220+
221+ function closestAbove ( list , value ) {
222+ var i ;
223+ i = list . length - 2 ;
224+ while ( i >= 0 && list [ i ] >= value ) {
225+ i -- ;
226+ }
227+ return list [ i + 1 ] ;
228+ }
0 commit comments