@@ -94,6 +94,8 @@ angular
94
94
* [$sce service](https://docs.angularjs.org/api/ng/service/$sce).
95
95
* - `templateUrl` - `{string=}`: The URL that will be used as the content of
96
96
* the panel.
97
+ * - `contentElement` - `{(string|!angular.JQLite|!Element)=}`: Pre-compiled
98
+ * element to be used as the panel's content.
97
99
* - `controller` - `{(function|string)=}`: The controller to associate with
98
100
* the panel. The controller can inject a reference to the returned
99
101
* panelRef, which allows the panel to be closed, hidden, and shown. Any
@@ -1034,6 +1036,24 @@ MdPanelService.prototype._wrapTemplate = function(origTemplate) {
1034
1036
} ;
1035
1037
1036
1038
1039
+ /**
1040
+ * Wraps a content element in a md-panel-outer wrapper and
1041
+ * positions it off-screen. Allows for proper control over positoning
1042
+ * and animations.
1043
+ * @param {!angular.JQLite } contentElement Element to be wrapped.
1044
+ * @return {!angular.JQLite } Wrapper element.
1045
+ * @private
1046
+ */
1047
+ MdPanelService . prototype . _wrapContentElement = function ( contentElement ) {
1048
+ var wrapper = angular . element ( '<div class="md-panel-outer-wrapper">' ) ;
1049
+
1050
+ contentElement . addClass ( 'md-panel' ) . css ( 'left' , '-9999px' ) ;
1051
+ wrapper . append ( contentElement ) ;
1052
+
1053
+ return wrapper ;
1054
+ } ;
1055
+
1056
+
1037
1057
/*****************************************************************************
1038
1058
* MdPanelRef *
1039
1059
*****************************************************************************/
@@ -1123,6 +1143,23 @@ function MdPanelRef(config, $injector) {
1123
1143
* @private {!Object}
1124
1144
*/
1125
1145
this . _interceptors = Object . create ( null ) ;
1146
+
1147
+ /**
1148
+ * Cleanup function, provided by `$mdCompiler` and assigned after the element
1149
+ * has been compiled. When `contentElement` is used, the function is used to
1150
+ * restore the element to it's proper place in the DOM.
1151
+ * @private {!Function}
1152
+ */
1153
+ this . _compilerCleanup = null ;
1154
+
1155
+ /**
1156
+ * Cache for saving and restoring element inline styles, CSS classes etc.
1157
+ * @type {{styles: string, classes: string} }
1158
+ */
1159
+ this . _restoreCache = {
1160
+ styles : '' ,
1161
+ classes : ''
1162
+ } ;
1126
1163
}
1127
1164
1128
1165
@@ -1241,6 +1278,14 @@ MdPanelRef.prototype.detach = function() {
1241
1278
self . _bottomFocusTrap . parentNode . removeChild ( self . _bottomFocusTrap ) ;
1242
1279
}
1243
1280
1281
+ if ( self . _restoreCache . classes ) {
1282
+ self . panelEl [ 0 ] . className = self . _restoreCache . classes ;
1283
+ }
1284
+
1285
+ // Either restore the saved styles or clear the ones set by mdPanel.
1286
+ self . panelEl [ 0 ] . style . cssText = self . _restoreCache . styles || '' ;
1287
+
1288
+ self . _compilerCleanup ( ) ;
1244
1289
self . panelContainer . remove ( ) ;
1245
1290
self . isAttached = false ;
1246
1291
return self . _$q . when ( self ) ;
@@ -1473,6 +1518,51 @@ MdPanelRef.prototype.toggleClass = function(toggleClass, onElement) {
1473
1518
} ;
1474
1519
1475
1520
1521
+ /**
1522
+ * Compiles the panel, according to the passed in config and appends it to
1523
+ * the DOM. Helps normalize differences in the compilation process between
1524
+ * using a string template and a content element.
1525
+ * @returns {!angular.$q.Promise<!MdPanelRef> } Promise that is resolved when
1526
+ * the element has been compiled and added to the DOM.
1527
+ * @private
1528
+ */
1529
+ MdPanelRef . prototype . _compile = function ( ) {
1530
+ var self = this ;
1531
+
1532
+ // Compile the element via $mdCompiler. Note that when using a
1533
+ // contentElement, the element isn't actually being compiled, rather the
1534
+ // compiler saves it's place in the DOM and provides a way of restoring it.
1535
+ return self . _$mdCompiler . compile ( self . config ) . then ( function ( compileData ) {
1536
+ var config = self . config ;
1537
+
1538
+ if ( config . contentElement ) {
1539
+ var panelEl = compileData . element ;
1540
+
1541
+ // Since mdPanel modifies the inline styles and CSS classes, we need
1542
+ // to save them in order to be able to restore on close.
1543
+ self . _restoreCache . styles = panelEl [ 0 ] . style . cssText ;
1544
+ self . _restoreCache . classes = panelEl [ 0 ] . className ;
1545
+
1546
+ self . panelContainer = self . _$mdPanel . _wrapContentElement ( panelEl ) ;
1547
+ self . panelEl = panelEl ;
1548
+ } else {
1549
+ self . panelContainer = compileData . link ( config [ 'scope' ] ) ;
1550
+ self . panelEl = angular . element (
1551
+ self . panelContainer [ 0 ] . querySelector ( '.md-panel' )
1552
+ ) ;
1553
+ }
1554
+
1555
+ // Save a reference to the cleanup function from the compiler.
1556
+ self . _compilerCleanup = compileData . cleanup ;
1557
+
1558
+ // Attach the panel to the proper place in the DOM.
1559
+ getElement ( self . config [ 'attachTo' ] ) . append ( self . panelContainer ) ;
1560
+
1561
+ return self ;
1562
+ } ) ;
1563
+ } ;
1564
+
1565
+
1476
1566
/**
1477
1567
* Creates a panel and adds it to the dom.
1478
1568
* @returns {!angular.$q.Promise } A promise that is resolved when the panel is
@@ -1488,44 +1578,41 @@ MdPanelRef.prototype._createPanel = function() {
1488
1578
}
1489
1579
1490
1580
self . config . locals . mdPanelRef = self ;
1491
- self . _$mdCompiler . compile ( self . config )
1492
- . then ( function ( compileData ) {
1493
- self . panelContainer = compileData . link ( self . config [ 'scope' ] ) ;
1494
- getElement ( self . config [ 'attachTo' ] ) . append ( self . panelContainer ) ;
1495
-
1496
- if ( self . config [ 'disableParentScroll' ] ) {
1497
- self . _restoreScroll = self . _$mdUtil . disableScrollAround (
1498
- null ,
1499
- self . panelContainer ,
1500
- { disableScrollMask : true }
1501
- ) ;
1502
- }
1503
1581
1504
- self . panelEl = angular . element (
1505
- self . panelContainer [ 0 ] . querySelector ( '.md-panel' ) ) ;
1582
+ self . _compile ( ) . then ( function ( ) {
1583
+ if ( self . config [ 'disableParentScroll' ] ) {
1584
+ self . _restoreScroll = self . _$mdUtil . disableScrollAround (
1585
+ null ,
1586
+ self . panelContainer ,
1587
+ { disableScrollMask : true }
1588
+ ) ;
1589
+ }
1506
1590
1507
- // Add a custom CSS class to the panel element.
1508
- if ( self . config [ 'panelClass' ] ) {
1509
- self . panelEl . addClass ( self . config [ 'panelClass' ] ) ;
1510
- }
1591
+ // Add a custom CSS class to the panel element.
1592
+ if ( self . config [ 'panelClass' ] ) {
1593
+ self . panelEl . addClass ( self . config [ 'panelClass' ] ) ;
1594
+ }
1511
1595
1512
- // Handle click and touch events for the panel container.
1513
- if ( self . config [ 'propagateContainerEvents' ] ) {
1514
- self . panelContainer . css ( 'pointer-events' , 'none' ) ;
1515
- }
1596
+ // Handle click and touch events for the panel container.
1597
+ if ( self . config [ 'propagateContainerEvents' ] ) {
1598
+ self . panelContainer . css ( 'pointer-events' , 'none' ) ;
1599
+ }
1516
1600
1517
- // Panel may be outside the $rootElement, tell ngAnimate to animate
1518
- // regardless.
1519
- if ( self . _$animate . pin ) {
1520
- self . _$animate . pin ( self . panelContainer ,
1521
- getElement ( self . config [ 'attachTo' ] ) ) ;
1522
- }
1601
+ // Panel may be outside the $rootElement, tell ngAnimate to animate
1602
+ // regardless.
1603
+ if ( self . _$animate . pin ) {
1604
+ self . _$animate . pin (
1605
+ self . panelContainer ,
1606
+ getElement ( self . config [ 'attachTo' ] )
1607
+ ) ;
1608
+ }
1609
+
1610
+ self . _configureTrapFocus ( ) ;
1611
+ self . _addStyles ( ) . then ( function ( ) {
1612
+ resolve ( self ) ;
1613
+ } , reject ) ;
1614
+ } , reject ) ;
1523
1615
1524
- self . _configureTrapFocus ( ) ;
1525
- self . _addStyles ( ) . then ( function ( ) {
1526
- resolve ( self ) ;
1527
- } , reject ) ;
1528
- } , reject ) ;
1529
1616
} ) ;
1530
1617
} ;
1531
1618
0 commit comments