PageRenderTime 48ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 1ms

/src/com/cf/view/component/list/ListBase.as

https://github.com/isaacueca/copacino.com
ActionScript | 839 lines | 560 code | 150 blank | 129 comment | 105 complexity | c2cadf630fb1dcae8de93fb7d4223475 MD5 | raw file
  1. package com.cf.view.component.list
  2. {
  3. import com.cf.model.vo.ListItem;
  4. import com.cf.util.AssetManager;
  5. import com.cf.util.Component;
  6. import com.cf.util.Settings;
  7. import com.cf.util.TextFactory;
  8. import com.cf.util.Utility;
  9. import com.cf.view.component.OpacityLines;
  10. import com.cf.view.component.scrollbar.Scrollbar;
  11. import com.cf.view.component.shape.ShapeBase;
  12. import com.cf.view.event.UIEvent;
  13. import com.greensock.TweenLite;
  14. import com.greensock.TweenMax;
  15. import com.greensock.easing.Expo;
  16. import com.greensock.easing.Strong;
  17. import com.greensock.events.TweenEvent;
  18. import flash.display.Sprite;
  19. import flash.events.Event;
  20. import flash.events.KeyboardEvent;
  21. import flash.events.MouseEvent;
  22. import flash.geom.Point;
  23. import flash.text.TextField;
  24. import flash.ui.Keyboard;
  25. import flash.utils.Dictionary;
  26. import nl.demonsters.debugger.MonsterDebugger;
  27. public class ListBase extends Component
  28. {
  29. public static const STATE_HIDDEN:String = "list/state/hidden";
  30. public static const STATE_CLOUD_DISPLAY:String = "list/state/cloud_display";
  31. public static const STATE_REVEALED:String = "list/state/revealed";
  32. private static const SCROLL_VERTICAL_MARGIN:int = 15;
  33. // DATA
  34. private var _data:Array;
  35. private var _listHeight:Number;
  36. protected var _url:String;
  37. protected var _listTilesByPostSlug:Dictionary;
  38. protected var _listSectionsBySlug:Dictionary;
  39. protected var _listTiles:Array;
  40. private var _lastSectionY:Number;
  41. // VISUAL
  42. private var _shape:ShapeBase;
  43. private var _opacityLines:OpacityLines;
  44. private var _screen:Sprite;
  45. private var _bg:Sprite;
  46. protected var _shapeSmall:Sprite;
  47. private var _shapeSmallMask:Sprite;
  48. private var _closeButton:Sprite;
  49. private var _closeButtonBg:Sprite;
  50. private var _closeButtonMask:Sprite;
  51. private var _maskShape:Sprite;
  52. private var _scrollbar:Scrollbar;
  53. private var _strokeLines:Sprite = new Sprite();
  54. private var _strokeLeft:Sprite = new Sprite();
  55. private var _strokeRight:Sprite = new Sprite();
  56. // STATE
  57. private var _currentListTileMagnified:ListTile;
  58. private var _currentListTileMaximized:ListTile;
  59. private var _lastOpenListTile:ListTile;
  60. private var _tilesTransitioningCount:int = 0;
  61. private var _isScrolling:Boolean = false;
  62. private var _isDragging:Boolean = false;
  63. private var _isScrollVisible:Boolean = true;
  64. private var _isScrollbarHidden:Boolean = false;
  65. // CONTENT LAYERS
  66. protected var _listTilesContainer:Sprite;
  67. protected var _modalTint:Sprite = new Sprite();
  68. protected var _modalContent:Sprite = new Sprite();
  69. // TWEENS
  70. private var _tweenVertical:TweenMax;
  71. public function ListBase( data:Array, shape:ShapeBase, url:String )
  72. {
  73. super();
  74. this._data = data;
  75. this._shape = shape;
  76. this._url = url;
  77. this.state = STATE_HIDDEN;
  78. }
  79. //
  80. // OVERRIDES
  81. //
  82. override protected function init():void
  83. {
  84. super.init();
  85. this.cacheAsBitmap = true;
  86. // BG
  87. _bg = new Sprite();
  88. _bg.graphics.beginFill( 0x00FF00, 0 );
  89. _bg.graphics.drawRect( 0,0, stage.stageWidth, stage.stageHeight );
  90. _bg.graphics.endFill();
  91. _bg.mouseEnabled = true;
  92. _bg.addEventListener( MouseEvent.MOUSE_DOWN, bg_mouse_down );
  93. _bg.visible = false;
  94. addChild( _bg );
  95. // SCREEN
  96. _screen = new Sprite();
  97. _screen.graphics.beginBitmapFill( AssetManager.InitLoader.getBitmapData( Settings.ASSET_SCREEN_BG ) );
  98. _screen.graphics.drawRect( 0, 0, stage.stageWidth * Settings.LIST_WIDTH_PERCENT, stage.stageHeight );
  99. _screen.graphics.endFill();
  100. _screen.visible = false;
  101. _screen.alpha = 0;
  102. addChild( _screen );
  103. // SCROLLBAR
  104. _scrollbar = new Scrollbar( Settings.TILE_HEIGHT, stage.stageHeight - Settings.FIRST_LINE_HEIGHT - Settings.TILE_HEIGHT );
  105. _scrollbar.y = Settings.FIRST_LINE_HEIGHT + Settings.TILE_HEIGHT;
  106. addChild( _scrollbar );
  107. _scrollbar.alpha = 0;
  108. _scrollbar.visible = false;
  109. _scrollbar.addEventListener( Scrollbar.SCROLLBAR_START, scrollbar_start );
  110. _scrollbar.addEventListener( Scrollbar.SCROLLBAR_STOP, scrollbar_stop );
  111. _scrollbar.addEventListener( Scrollbar.SCROLLBAR_UPDATE, scrollbar_update );
  112. // TICK LINES
  113. addChild( _strokeLines );
  114. ([ _strokeLeft, _strokeRight ] as Array).forEach( function( tick:Sprite, index:int, arr:Array):void {
  115. tick.graphics.beginFill( Settings.LINE_COLOR, 1 );
  116. var h:Number = stage.stageHeight;
  117. tick.graphics.drawRect( 0, 0, 1, stage.stageHeight );
  118. });
  119. _strokeLines.addChild( _strokeLeft );
  120. _strokeLines.addChild( _strokeRight );
  121. _strokeLines.visible = false;
  122. _strokeLines.alpha = 0;
  123. // CREATE LIST TILES using pre-arranged _data Array
  124. _listTilesByPostSlug = new Dictionary();
  125. _listSectionsBySlug = new Dictionary();
  126. _listTiles = new Array();
  127. _listTilesContainer = new Sprite();
  128. // OPACITY lines
  129. _opacityLines = new OpacityLines();
  130. addChild( _opacityLines );
  131. _opacityLines.alpha = 0;
  132. // TILES container LAYER
  133. addChild( _listTilesContainer );
  134. _listTilesContainer.y = Settings.LIST_MARGIN_TOP;
  135. var currY:Number = -(Settings.TILE_HEIGHT);
  136. var currDegrees:Number = 0;
  137. var degreesIncrements:Number = 360 / _data.length;
  138. for each (var listItem:ListItem in _data)
  139. {
  140. // EXTRA MARGIN for SECTION HEAD
  141. if ( listItem.type == ListItem.LIST_ITEM_TYPE_SECTION )
  142. currY += (Settings.TILE_HEIGHT + Settings.TILE_MARGIN);
  143. // BUILD listTile
  144. var listTile:ListTile;
  145. var color:uint = (listItem.type == ListItem.LIST_ITEM_TYPE_SECTION) ? Settings.LIST_DEFAULT_COLOR : Utility.getColorForAngle(currDegrees); //Utility.getRandomPositiveColor();
  146. // STORE colors for media and r+d
  147. if ( listItem.type == ListItem.LIST_ITEM_TYPE_POST )
  148. {
  149. if ( listItem.postData.postTitle.toLowerCase() == "media" ) AssetManager.mediaColor = color;
  150. if ( listItem.postData.postTitle.toLowerCase() == "r+d" ) AssetManager.rdColor = color;
  151. }
  152. // URL
  153. var listTileUrl:String;
  154. if ( listItem.type == ListItem.LIST_ITEM_TYPE_POST) listTileUrl = _url + "/" + Utility.formatAsSlug( listItem.postData.postTitle.toLocaleLowerCase() );
  155. else listTileUrl = _url + "/" + Utility.formatAsSlug( listItem.sectionTitle );
  156. listTile = new ListTile( listItem, color, listTileUrl );
  157. _listTilesContainer.addChild( listTile );
  158. // WIRE EVENT LISTENERS
  159. listTile.addEventListener( MouseEvent.MOUSE_DOWN, listTile_mouse_down );
  160. listTile.addEventListener( MouseEvent.ROLL_OVER, listTile_roll_over );
  161. // POSITION
  162. listTile.y = listTile.originalY = currY;
  163. currY += listTile.tileHeight + Settings.TILE_MARGIN;
  164. // SAVE a reference for posts
  165. if (listItem.type == ListItem.LIST_ITEM_TYPE_POST)
  166. _listTilesByPostSlug[ Utility.formatAsSlug( listItem.postData.postTitle.toLocaleLowerCase() ) ] = listTile;
  167. else
  168. {
  169. _listSectionsBySlug[ Utility.formatAsSlug( listItem.sectionTitle )] = listTile;
  170. // EXTRA increments for sections
  171. currDegrees += ( degreesIncrements * 4 );
  172. // SAVE LAST SECTION Y - (after the full loop it'll be last)
  173. _lastSectionY = listTile.y;
  174. }
  175. // SAVE a reference for correct sort order
  176. _listTiles.push( listTile );
  177. // SAVE the index so we can maintain display list order
  178. listTile.displayIndex = _listTiles.length - 1;
  179. // INCREMENT DEGREES for color
  180. currDegrees += degreesIncrements;
  181. }
  182. // MASKING
  183. _maskShape = new Sprite();
  184. _maskShape.addChild( Utility.getMaskShape( stage.stageWidth, _listHeight ) );
  185. _maskShape.y = Settings.LIST_MARGIN_TOP - Settings.TILE_HEIGHT; // + Settings.TILE_MARGIN);
  186. addChild( _maskShape );
  187. _maskShape.mouseEnabled = false;
  188. _listTilesContainer.mask = _maskShape;
  189. // MODAL TINT
  190. _modalTint.graphics.beginFill( 0x000000, Settings.MODAL_TINT_ALPHA );
  191. _modalTint.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
  192. _modalTint.alpha = 0;
  193. _modalTint.visible = false;
  194. _modalTint.mouseEnabled = _modalTint.mouseChildren = false;
  195. _modalTint.addEventListener( MouseEvent.MOUSE_DOWN, model_mouse_down );
  196. addChild( _modalTint );
  197. // MODAL CONTENT (top layer)
  198. addChild( _modalContent );
  199. // SMALL SHAPE
  200. _shapeSmall = _shape.shapeSmall;
  201. _shapeSmall.mouseChildren = _shapeSmall.mouseEnabled = false;
  202. _shapeSmall.x = -(Settings.TILE_HEIGHT >> 1);
  203. _modalContent.addChild( _shapeSmall );
  204. // SMALL SHAPE MASK
  205. _shapeSmallMask = new Sprite();
  206. _shapeSmallMask.addChild( Utility.getMaskShape( _shapeSmall.width, _shapeSmall.height ) );
  207. _shapeSmallMask.width = 0;
  208. _shapeSmallMask.x = _shapeSmall.width >> 1;
  209. _shapeSmallMask.y = - _shapeSmall.width >> 1;
  210. _shapeSmall.addChild( _shapeSmallMask );
  211. _shapeSmall.mask = _shapeSmallMask;
  212. // CLOSE BUTTON
  213. _closeButton = new Sprite();
  214. // BG
  215. _closeButtonBg = new Sprite();
  216. _closeButton.addChild( _closeButtonBg );
  217. _closeButtonBg.graphics.beginFill( Settings.WE_ARE_CROSS_BG );
  218. _closeButtonBg.graphics.drawRect( 0,0, Settings.TILE_HEIGHT / .8, Settings.TILE_HEIGHT );
  219. _closeButtonBg.graphics.endFill();
  220. // TEXT
  221. var x:TextField = TextFactory.TagText( "x" );
  222. x.mouseEnabled = false;
  223. _closeButton.addChild( x );
  224. x.x = (_closeButton.width >> 1) - (x.width >> 1);
  225. x.y = (_closeButton.height >> 1) - (x.height >> 1);
  226. _modalContent.addChild( _closeButton );
  227. _closeButton.buttonMode = _closeButton.useHandCursor = true;
  228. _closeButton.addEventListener( MouseEvent.MOUSE_DOWN, _closeButton_mouse_down );
  229. // CLOSE BUTTON mask
  230. _closeButtonMask = new Sprite();
  231. _closeButtonMask.addChild( Utility.getMaskShape( _closeButton.width, _closeButton.height ) );
  232. _closeButton.mask = _closeButtonMask;
  233. _closeButtonMask.width = 0;
  234. _closeButton.addChild( _closeButtonMask );
  235. // WIRE EVENTS
  236. stage.addEventListener( KeyboardEvent.KEY_DOWN, key_down );
  237. this.addEventListener( Event.ENTER_FRAME, enter_frame );
  238. this.addEventListener( MouseEvent.MOUSE_WHEEL, mouse_wheel );
  239. position();
  240. }
  241. override protected function position():void
  242. {
  243. // CALCULATE proper width and X instead of relying on listTilescontainer since there could be a delay in sizing
  244. var contentWidth:int = int(stage.stageWidth * Settings.LIST_WIDTH_PERCENT);
  245. var contentX:Number = (stage.stageWidth >> 1) - (contentWidth >> 1);
  246. // CENTER list
  247. _listTilesContainer.x = contentX;
  248. // SIZE opacity lines
  249. _opacityLines.setMinHeight( _listTilesContainer.height );
  250. _opacityLines.width = contentWidth;
  251. // POSITION center screen + opacity lines
  252. _screen.x = _opacityLines.x = contentX;
  253. // MASK
  254. _maskShape.width = stage.stageWidth;
  255. // SCREEN
  256. _screen.graphics.clear();
  257. _screen.graphics.beginBitmapFill( AssetManager.InitLoader.getBitmapData( Settings.ASSET_SCREEN_BG ) );
  258. _screen.graphics.drawRect( 0, 0, stage.stageWidth * Settings.LIST_WIDTH_PERCENT, stage.stageHeight );
  259. _screen.graphics.endFill();
  260. // SCROLLBAR
  261. if ( _isScrollbarHidden )
  262. _scrollbar.x = stage.stageWidth;
  263. else
  264. _scrollbar.x = stage.stageWidth - Settings.TILE_HEIGHT;
  265. _scrollbar.height = stage.stageHeight - Settings.FIRST_LINE_HEIGHT - Settings.TILE_HEIGHT;
  266. // _scrollbarGutter.height = (maxScrollbarY - minScrollbarY) + _scrollbarSlider.height;
  267. // TINT
  268. _modalTint.width = stage.stageWidth;
  269. _modalTint.height = stage.stageHeight;
  270. // MODAL content
  271. if ( _currentListTileMaximized != null && _currentListTileMaximized.state == ListTile.STATE_LARGE )
  272. _modalContent.x = 0;
  273. else if ( _currentListTileMaximized != null && _currentListTileMaximized.state == ListTile.STATE_MAXIMIZED )
  274. {
  275. // CENTER VERTICALLY in maximized view
  276. if ( _currentListTileMaximized )
  277. {
  278. // SCROLL to vertically center the maximized tile
  279. var vertMultiple:int = Math.min( 8, Math.max(1, int( (( stage.stageHeight >> 1 ) - (Settings.CONTENT_AREA_HEIGHT >> 1)) / (Settings.TILE_HEIGHT + Settings.TILE_MARGIN) ) )); // 4
  280. var toVerticalScroll:Number = -_currentListTileMaximized.originalY + (vertMultiple * Settings.TILE_ROW_HEIGHT) + Settings.FIRST_LINE_HEIGHT;
  281. // TweenMax.to( this, 1, { verticalScroll: toVerticalScroll, ease: Expo.easeOut });
  282. verticalScroll = toVerticalScroll;
  283. // SMALL SHAPE Y
  284. _shapeSmall.y = _closeButton.y = _currentListTileMaximized.y + (3 * Settings.TILE_HEIGHT);
  285. _closeButton.y -= .5 * Settings.TILE_HEIGHT;
  286. _closeButton.x = contentWidth - 1;
  287. }
  288. _modalContent.x = contentX;
  289. }
  290. else
  291. {
  292. _modalContent.x = contentX;
  293. }
  294. // BG
  295. _bg.width = stage.stageWidth;
  296. _bg.height = stage.stageHeight;
  297. // TICK
  298. listHeight = listLowerBoundary - (Settings.LIST_MARGIN_TOP - (Settings.TILE_HEIGHT + Settings.TILE_MARGIN)); // AFFECTS mask height and ticks vertical position
  299. /*_tickUpper.x = _tickLower.x = contentX - Settings.TILE_HEIGHT;
  300. _tickUpperRight.x = _tickLowerRight.x = contentWidth + Settings.TILE_HEIGHT;
  301. */
  302. _strokeLines.x = contentX - 1;
  303. _strokeLines.height = stage.stageHeight;
  304. _strokeRight.x = contentWidth+ 1;
  305. }
  306. //
  307. // EVENT handlers
  308. //
  309. private function bg_mouse_down( e:MouseEvent ):void
  310. {
  311. _closeButton_mouse_down( null );
  312. }
  313. private function model_mouse_down(e:MouseEvent):void
  314. {
  315. // default close
  316. _closeButton_mouse_down( null );
  317. }
  318. private function scrollbar_start(e:Event):void
  319. {
  320. _isScrolling = true;
  321. }
  322. private function scrollbar_stop(e:Event):void
  323. {
  324. _isScrolling = false;
  325. }
  326. private function scrollbar_update(e:Event):void
  327. {
  328. updateFromScrollbar();
  329. }
  330. private function key_down(e:KeyboardEvent):void
  331. {
  332. }
  333. private function mouse_wheel(e:MouseEvent):void
  334. {
  335. // verticalScroll = Math.min( 0, e.delta + verticalScroll );
  336. if ( _currentListTileMaximized != null ) return;
  337. _scrollbar.scrollByDelta( e.delta );
  338. }
  339. private var _scrollwheelTweenCount:int = 0;
  340. private function monitorScrollwheelTween( t:TweenMax ):void
  341. {
  342. _scrollwheelTweenCount++;
  343. t.addEventListener( TweenEvent.COMPLETE, scrollwheel_tween_complete );
  344. }
  345. private function scrollwheel_tween_complete( e:TweenEvent ):void
  346. {
  347. _scrollwheelTweenCount--;
  348. if ( _scrollwheelTweenCount == 0 ) _isScrolling = false;
  349. }
  350. private function _modalTint_click(e:MouseEvent):void
  351. {
  352. // _closeButton_mouse_down( null );
  353. }
  354. private function _closeButton_mouse_down(e:MouseEvent):void
  355. {
  356. if ( (state == STATE_REVEALED && _currentListTileMaximized == null) || ( state == STATE_CLOUD_DISPLAY ))
  357. {
  358. // CLOSE LIST
  359. dispatchEvent( new UIEvent( UIEvent.LIST_CLOSE, this.name, "", true, true ) );
  360. }
  361. else if ( state == STATE_REVEALED && _currentListTileMaximized != null )
  362. {
  363. // DYNAMICALLY choose the listTile's parent section
  364. var parentSlug:String = Utility.formatAsSlug( _currentListTileMaximized.listItem.sectionTitle );
  365. var title:String = _currentListTileMaximized.listItem.sectionTitle;
  366. _lastOpenListTile = _currentListTileMaximized;
  367. dispatchEvent( new UIEvent( UIEvent.URL_EVENT, title, this._url + "/" + parentSlug ) );
  368. }
  369. }
  370. private function listTile_mouse_down(e:MouseEvent):void
  371. {
  372. // NAV to tile url
  373. var tile:ListTile = e.currentTarget as ListTile;
  374. if ( tile.listItem.type == ListItem.LIST_ITEM_TYPE_POST && tile != _currentListTileMaximized )
  375. dispatchEvent( new UIEvent( ShapeBase.UIEVENT_TILE_CLICK, tile.listItem.postData.postTitle.toLowerCase(), _url + "/" + Utility.formatAsSlug( tile.listItem.postData.postTitle.toLowerCase() ), true, true ) );
  376. }
  377. private function listTile_roll_over(e:MouseEvent):void
  378. {
  379. // ON ROLL OVER magnify only if it's minimized AND there isn't a current maximized tile
  380. // var tile:ListTile = e.currentTarget as ListTile;
  381. // if ( state == STATE_REVEALED && tile.state == ListTile.STATE_MINIMIZED && _currentListTileMaximized == null ) magnifyTile( tile );
  382. }
  383. private function enter_frame(e:Event):void
  384. {
  385. if ( state == STATE_REVEALED )
  386. {
  387. if ( _isScrolling ) updateFromScrollbar();
  388. // SYNC lines always
  389. _opacityLines.y = _listTilesContainer.y - Settings.LIST_MARGIN_TOP;
  390. }
  391. }
  392. //
  393. // PRIVATE
  394. //
  395. private function updateFromScrollbar():void
  396. {
  397. var contentAreaHeight:Number = _maskShape.height;
  398. var pScrolled:Number = _scrollbar.percentScrolled;
  399. scrollListToPercent( pScrolled );
  400. }
  401. private function get _contentWidth():int { return int(stage.stageWidth * Settings.LIST_WIDTH_PERCENT); }
  402. private function moveNext():void // MOVE to the next tile in the list
  403. {
  404. if ( _currentListTileMaximized )
  405. {
  406. var nextIndex:int = _currentListTileMaximized.displayIndex + 1;
  407. // CHECK IF WE HAVE TO move next further (if we can) if it's a section head
  408. if ( (nextIndex < _listTiles.length - 1) && (_listTiles[ nextIndex ] as ListTile) != null && (_listTiles[ nextIndex ] as ListTile).listItem.type == ListItem.LIST_ITEM_TYPE_SECTION ) nextIndex++;
  409. var nextTile:ListTile = _listTiles[ nextIndex ] as ListTile;
  410. if ( nextTile && nextTile.listItem.type == ListItem.LIST_ITEM_TYPE_POST )
  411. {
  412. minimizeTile( _currentListTileMaximized );
  413. // CHANGE URL
  414. dispatchEvent( new UIEvent( ShapeBase.UIEVENT_TILE_CLICK, nextTile.listItem.postData.postTitle.toLowerCase(), _url + "/" + Utility.formatAsSlug( nextTile.listItem.postData.postTitle.toLowerCase() ), true, true ) );
  415. }
  416. }
  417. }
  418. private function movePrev():void // MOVE to the previous tile in the list
  419. {
  420. if ( _currentListTileMaximized )
  421. {
  422. var prevIndex:int = _currentListTileMaximized.displayIndex - 1;
  423. // CHECK IF WE HAVE TO move back further (if we can) if it's a section head
  424. if ( prevIndex > 0 && (_listTiles[ prevIndex ] as ListTile) != null && (_listTiles[ prevIndex ] as ListTile).listItem.type == ListItem.LIST_ITEM_TYPE_SECTION ) prevIndex--;
  425. var prevTile:ListTile = _listTiles[ prevIndex ] as ListTile;
  426. if ( prevTile && prevTile.listItem.type == ListItem.LIST_ITEM_TYPE_POST )
  427. {
  428. minimizeTile( _currentListTileMaximized );
  429. // CHANGE URL
  430. dispatchEvent( new UIEvent( ShapeBase.UIEVENT_TILE_CLICK, prevTile.listItem.postData.postTitle.toLowerCase(), _url + "/" + Utility.formatAsSlug( prevTile.listItem.postData.postTitle.toLowerCase() ), true, true ) );
  431. }
  432. }
  433. }
  434. private function set listHeight( height:Number ):void
  435. {
  436. _listHeight = height;
  437. _maskShape.height = height + (Settings.TILE_HEIGHT + Settings.TILE_MARGIN);
  438. // _tickLower.y = height + Settings.LIST_MARGIN_TOP;
  439. }
  440. private function get listLowerBoundary():Number
  441. {
  442. var yBoundary:Number = stage.stageHeight - (3 * (Settings.TILE_HEIGHT + Settings.TILE_MARGIN));
  443. yBoundary -= (yBoundary % (Settings.TILE_HEIGHT + Settings.TILE_MARGIN)) - 5;
  444. return yBoundary;
  445. }
  446. private function scrollListToPercent(percent:Number):void
  447. {
  448. var toY:Number = (minListY + (percent * (maxListY - minListY)));
  449. toY = Settings.LIST_MARGIN_TOP - (int( toY / Settings.TILE_ROW_HEIGHT ) * Settings.TILE_ROW_HEIGHT );
  450. // JUST SET IT, don't tween
  451. _listTilesContainer.y = toY;
  452. }
  453. private function tween_complete(e:TweenEvent):void
  454. {
  455. _tilesTransitioningCount--;
  456. }
  457. private function monitorTransitionTween(tween:TweenMax):void
  458. {
  459. _tilesTransitioningCount++;
  460. //Utility.debugColor( this, 0xFFFF00, "monitorTransitionTween", _tilesTransitioningCount );
  461. tween.addEventListener( TweenEvent.COMPLETE, tween_complete );
  462. }
  463. private function minimizeTile( tileToMin:ListTile ):void
  464. {
  465. if ( _currentListTileMaximized.state == ListTile.STATE_LARGE ) delargifyCurrentMaximized( false );
  466. // SHOW SCROLLBARS
  467. showScrollbar();
  468. // PUT Y back
  469. tileToMin.y = tileToMin.originalY;
  470. // FADE OUT MODAL
  471. TweenLite.to( _modalTint, .5, { autoAlpha:0 } );
  472. // if ( tileToMin.state == ListTile.STATE_MAXIMIZED ) _listTilesContainer.addChildAt( _currentListTileMaximized, _currentListTileMaximized.displayIndex );
  473. // PUT IT BACK on the right layer
  474. if ( tileToMin.parent == _modalContent ) _listTilesContainer.addChildAt( _currentListTileMaximized, _currentListTileMaximized.displayIndex );
  475. // MINIMIZE
  476. monitorTransitionTween( tileToMin.minimize() );
  477. // CLEAR REFERENCE
  478. _currentListTileMaximized = null;
  479. // UNWIND SMALL SHAPE
  480. TweenLite.killTweensOf( _shapeSmallMask );
  481. TweenLite.to( _shapeSmallMask, .3, { x: (_shapeSmall.width >> 1), width: 0 } );
  482. // CLOSE BUTTON hide
  483. TweenLite.to( _closeButtonMask, .4, { width:0 } );
  484. }
  485. private function maximizeTile( tileToMax:ListTile ):void
  486. {
  487. TweenMax.to( _closeButtonBg, 1, { tint: tileToMax.color });
  488. if ( _currentListTileMaximized == tileToMax ) return; // DO NOTHING
  489. if ( _currentListTileMaximized != null && _currentListTileMaximized.state == ListTile.STATE_LARGE )
  490. delargifyCurrentMaximized();
  491. // MINIMIZE the current maximized tile
  492. if ( _currentListTileMaximized != null ) minimizeTile( _currentListTileMaximized );
  493. _currentListTileMaximized = tileToMax;
  494. // SQUEEZE scrollbars in
  495. hideScrollbar();
  496. // SCROLL to vertically center the maximized tile
  497. var vertMultiple:int = Math.min( 8, Math.max(1, int( (( stage.stageHeight >> 1 ) - (Settings.CONTENT_AREA_HEIGHT >> 1)) / (Settings.TILE_HEIGHT + Settings.TILE_MARGIN) ) ) ); // 4
  498. var toVerticalScroll:Number = -tileToMax.originalY + (vertMultiple * Settings.TILE_ROW_HEIGHT) + Settings.FIRST_LINE_HEIGHT;
  499. TweenMax.to( this, .5, { verticalScroll: toVerticalScroll, ease: Expo.easeOut });
  500. // ADD content tile to the modalContent layer
  501. _modalContent.addChild( _currentListTileMaximized );
  502. TweenLite.to( _modalTint, .5, { autoAlpha:1 } );
  503. // CHECK delay - needs longer delay when transition into list and opening a post at the same time
  504. var shapeDelay:Number = .5;
  505. if ( tileToMax.mask.width < int(stage.stageWidth * Settings.LIST_WIDTH_PERCENT) ) shapeDelay = 3.5;
  506. // MAXIMIZE
  507. monitorTransitionTween( _currentListTileMaximized.maximize() );
  508. // SMALL SHAPE + CLOSE button - position + show
  509. _shapeSmall.y = _closeButton.y = tileToMax.y + (3 * Settings.TILE_HEIGHT);
  510. _closeButton.x = _contentWidth;
  511. TweenLite.to( _shapeSmallMask, .6, { x: -(_shapeSmall.width >> 1), width: _shapeSmall.width, delay: shapeDelay } );
  512. TweenLite.to( _closeButtonMask, 1, { width: _closeButton.width, delay:shapeDelay + .6 } );
  513. }
  514. private function magnifyTile( tileToMag:ListTile ):void
  515. {
  516. if ( _currentListTileMagnified == tileToMag ) return; // DO NOTHING
  517. if ( _currentListTileMagnified != null ) _currentListTileMagnified.minimize();
  518. _currentListTileMagnified = tileToMag;
  519. monitorTransitionTween( _currentListTileMagnified.magnify() );
  520. }
  521. private function get localShapeCoordinates():Point
  522. {
  523. return this.globalToLocal( _shape.global() );
  524. }
  525. private function hideScrollbar():void
  526. {
  527. // FADE OUT 1px stroke also
  528. TweenMax.to( _strokeLines, 1, { alpha: 0 });
  529. _isScrollbarHidden = true;
  530. TweenMax.to( _scrollbar, 1, { x: stage.stageWidth });
  531. }
  532. private function showScrollbar():void
  533. {
  534. // FADE OUT 1px stroke also
  535. TweenMax.to( _strokeLines, 1, { alpha: 1 });
  536. _isScrollbarHidden = false;
  537. TweenMax.to( _scrollbar, 1, { x: stage.stageWidth - _scrollbar.width });
  538. }
  539. private function get minListY():Number
  540. {
  541. return 0;
  542. }
  543. private function get maxListY():Number
  544. {
  545. // IS "we are not" content higher than viewable
  546. var lastTile:ListTile = _listTiles[ _listTiles.length-1 ] as ListTile;
  547. if ( (lastTile.y - _lastSectionY ) > ( _maskShape.height ))
  548. {
  549. return lastTile.y - _maskShape.height + (2 * (Settings.TILE_HEIGHT + Settings.TILE_MARGIN));
  550. }
  551. return _lastSectionY - Settings.TILE_MARGIN;
  552. }
  553. //
  554. // PUBLIC API
  555. //
  556. public function largifyCurrentMaximized():void
  557. {
  558. _currentListTileMaximized.largify();
  559. // RAISE tile to top of screen
  560. TweenLite.to( this, .8, { delay:1, verticalScroll: -_currentListTileMaximized.originalY, ease: Expo.easeOut });
  561. // TweenLite.to( _currentListTileMaximized, .8, { delay:1, y: _currentListTileMaximized.originalY - Settings.LIST_MARGIN_TOP });
  562. // PULL MODAL to left of screen
  563. TweenLite.to( _modalContent, 1, { x: 0, ease:Strong.easeInOut } );
  564. // MOVE SHAPE to top layer
  565. _modalContent.addChild( _shapeSmall );
  566. // SLIDE SHAPE over
  567. TweenLite.to( _shapeSmall, .8, { x: (Settings.TILE_HEIGHT >> 1) });
  568. // SMALL SHAPE Y
  569. TweenLite.to( _shapeSmall, .8, { y: Settings.LIST_MARGIN_TOP + _currentListTileMaximized.originalY + (3 * Settings.TILE_HEIGHT) });
  570. }
  571. public function delargifyCurrentMaximized( slideTiles:Boolean = true ):void
  572. {
  573. if ( _currentListTileMaximized != null && _currentListTileMaximized.state == ListTile.STATE_LARGE )
  574. {
  575. _currentListTileMaximized.maximize( slideTiles );
  576. // LOWER tile to original position
  577. // TweenLite.to( _currentListTileMaximized, .8, { y: _currentListTileMaximized.originalY });
  578. // SCROLL to vertically center the maximized tile
  579. var vertMultiple:int = Math.min( 8, Math.max(1, int( (( stage.stageHeight >> 1 ) - (Settings.CONTENT_AREA_HEIGHT >> 1)) / (Settings.TILE_HEIGHT + Settings.TILE_MARGIN) ) ) ); // 4
  580. var toVerticalScroll:Number = -_currentListTileMaximized.originalY + (vertMultiple * Settings.TILE_ROW_HEIGHT) + Settings.FIRST_LINE_HEIGHT;
  581. TweenMax.to( this, .5, { verticalScroll: toVerticalScroll, ease: Expo.easeOut });
  582. // RETURN modal content container x position
  583. var contentWidth:int = int(stage.stageWidth * Settings.LIST_WIDTH_PERCENT);
  584. var contentX:Number = (stage.stageWidth >> 1) - (contentWidth >> 1);
  585. TweenLite.to( _modalContent, 1, { x: contentX, ease:Strong.easeInOut } );
  586. // MOVE SHAPE back to the bottom
  587. _modalContent.addChildAt( _shapeSmall, 0 );
  588. // SLIDE SHAPE back over
  589. TweenLite.to( _shapeSmall, .8, { x: -(Settings.TILE_HEIGHT >> 1) });
  590. // SMALL SHAPE Y
  591. TweenLite.to( _shapeSmall, .8, { y: _currentListTileMaximized.y + (3 * Settings.TILE_HEIGHT) });
  592. }
  593. }
  594. public function scrollToSection( sectionSlug:String ):void
  595. {
  596. var isClosing:Boolean = false;
  597. // ENSURE there is no maximized content
  598. if ( _currentListTileMaximized != null )
  599. {
  600. minimizeTile( _currentListTileMaximized );
  601. isClosing = true;
  602. }
  603. var tile:ListTile;
  604. if ( isClosing && _lastOpenListTile && sectionSlug == Utility.formatAsSlug( _lastOpenListTile.listItem.sectionTitle ) ) // USE last open tile to figure out where to scroll to if the sectionSlug is the last open tile's parent
  605. tile = _lastOpenListTile;
  606. else
  607. tile = _listSectionsBySlug[ sectionSlug ] as ListTile;
  608. if ( tile )
  609. {
  610. // 1. TWEEN the list position
  611. var toListY:Number = Settings.LIST_MARGIN_TOP - (tile.y - Settings.TILE_MARGIN);
  612. TweenLite.to( _listTilesContainer, .8, { y: toListY });
  613. // 2. CALCULATE percentage scrolled
  614. var listScrolledY:Number = Math.abs( toListY - Settings.LIST_MARGIN_TOP ) ;
  615. var percent:Number = ( listScrolledY - minListY ) / ( maxListY - minListY );
  616. // 3. TWEEN the scrollbar position
  617. _scrollbar.percentScrolled = percent;
  618. }
  619. }
  620. public function get currentListTileMaximized():ListTile { return _currentListTileMaximized; }
  621. public function openPost( slug:String ):void
  622. {
  623. // OPEN POST using the slug from the url
  624. MonsterDebugger.trace(this, "openPost: " + slug );
  625. var tile:ListTile = _listTilesByPostSlug[ slug ] as ListTile;
  626. if ( tile ) maximizeTile( tile );
  627. }
  628. public function get verticalScroll():Number
  629. {
  630. return _listTilesContainer.y;
  631. }
  632. public function set verticalScroll( y:Number ):void
  633. {
  634. _listTilesContainer.y = _modalContent.y = y;
  635. }
  636. public function set data(data:Array):void
  637. {
  638. this.data = data;
  639. }
  640. public function reveal( initDelay:Number, isCloudDisplay:Boolean ):void
  641. {
  642. _bg.visible = true;
  643. if ( !isCloudDisplay)
  644. {
  645. for (var i:int=0; i < _listTiles.length; i++)
  646. {
  647. var tile:ListTile = _listTiles[i] as ListTile;
  648. tile.reveal( initDelay + (i * .02) );
  649. }
  650. // OPACTIY LINES
  651. TweenLite.to( _opacityLines, 1, { delay:2, alpha: 1 } );
  652. // SCREEN
  653. TweenLite.to( _screen, 2, { delay:2, autoAlpha: .35 } );
  654. // STROKES
  655. TweenLite.to( _strokeLines, 1, { delay:2, autoAlpha:1 } );
  656. // SCROLLBAR
  657. TweenMax.to( _scrollbar, 1.5, { delay:2, autoAlpha:1 } );
  658. }
  659. if ( isCloudDisplay ) state = STATE_CLOUD_DISPLAY;
  660. else state = STATE_REVEALED;
  661. }
  662. public function hide( initDelay:Number ):void
  663. {
  664. if ( _currentListTileMaximized != null ) minimizeTile( _currentListTileMaximized );
  665. _bg.visible = false;
  666. // ENSURE all tiles are hidden
  667. for (var i:int=0; i < _listTiles.length; i++)
  668. {
  669. var tile:ListTile = _listTiles[i] as ListTile;
  670. tile.hide( initDelay + (i * .04) );
  671. }
  672. if ( state != STATE_CLOUD_DISPLAY )
  673. {
  674. // HIDE scrollbar
  675. TweenMax.to( _scrollbar, 1, { delay:1, autoAlpha:0 } );
  676. // OPACTIY LINES
  677. TweenLite.to( _opacityLines, 1, { delay:1, alpha: 0 } );
  678. // SCREEN
  679. TweenLite.to( _screen, 1, { delay:1, autoAlpha: 0 } );
  680. // HIDE ticks
  681. TweenLite.to( _strokeLines, 1, { delay:2, autoAlpha:0 } );
  682. }
  683. // CLOSE BUTTON
  684. TweenLite.killTweensOf( _closeButtonMask );
  685. TweenLite.to( _closeButtonMask, .4, { width:0 } );
  686. state = STATE_HIDDEN;
  687. }
  688. }
  689. }