Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 59 additions & 7 deletions src/components/panel/panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ angular
* - `attachTo` - `{(string|!angular.JQLite|!Element)=}`: The element to
* attach the panel to. Defaults to appending to the root element of the
* application.
* - `propagateContainerEvents` - `{boolean=}`: Whether pointer or touch
* events should be allowed to propagate 'go through' the container, aka the
* wrapper, of the panel. Defaults to false.
* - `panelClass` - `{string=}`: A css class to apply to the panel element.
* This class should define any borders, box-shadow, etc. for the panel.
* - `zIndex` - `{number=}`: The z-index to place the panel at.
Expand Down Expand Up @@ -308,6 +311,8 @@ angular
* Adds a class to the panel. DO NOT use this to hide/show the panel.
*
* @param {string} newClass Class to be added.
* @param {boolean} toElement Whether or not to add the class to the panel
* element instead of the container.
*/

/**
Expand All @@ -317,6 +322,8 @@ angular
* Removes a class from the panel. DO NOT use this to hide/show the panel.
*
* @param {string} oldClass Class to be removed.
* @param {boolean} fromElement Whether or not to remove the class from the
* panel element instead of the container.
*/

/**
Expand All @@ -326,6 +333,17 @@ angular
* Toggles a class on the panel. DO NOT use this to hide/show the panel.
*
* @param {string} toggleClass Class to be toggled.
* @param {boolean} onElement Whether or not to remove the class from the panel
* element instead of the container.
*/

/**
* @ngdoc method
* @name MdPanelRef#updatePosition
* @description
* Updates the position configuration of a panel. Use this to update the
* position of a panel that is open, without having to close and re-open the
* panel.
*/

/**
Expand Down Expand Up @@ -628,6 +646,7 @@ function MdPanelService($rootElement, $rootScope, $injector, $window) {
focusOnOpen: true,
fullscreen: false,
hasBackdrop: false,
propagateContainerEvents: false,
transformTemplate: angular.bind(this, this._wrapTemplate),
trapFocus: false,
zIndex: defaultZIndex
Expand Down Expand Up @@ -1057,14 +1076,18 @@ MdPanelRef.prototype.hide = function() {
* Add a class to the panel. DO NOT use this to hide/show the panel.
*
* @param {string} newClass Class to be added.
* @param {boolean} toElement Whether or not to add the class to the panel
* element instead of the container.
*/
MdPanelRef.prototype.addClass = function(newClass) {
MdPanelRef.prototype.addClass = function(newClass, toElement) {
if (!this._panelContainer) {
throw new Error('Panel does not exist yet. Call open() or attach().');
}

if (!this._panelContainer.hasClass(newClass)) {
if (!toElement && !this._panelContainer.hasClass(newClass)) {
this._panelContainer.addClass(newClass);
} else if (toElement && !this._panelEl.hasClass(newClass)) {
this._panelEl.addClass(newClass);
}
};

Expand All @@ -1073,14 +1096,18 @@ MdPanelRef.prototype.addClass = function(newClass) {
* Remove a class from the panel. DO NOT use this to hide/show the panel.
*
* @param {string} oldClass Class to be removed.
* @param {boolean} fromElement Whether or not to remove the class from the
* panel element instead of the container.
*/
MdPanelRef.prototype.removeClass = function(oldClass) {
MdPanelRef.prototype.removeClass = function(oldClass, fromElement) {
if (!this._panelContainer) {
throw new Error('Panel does not exist yet. Call open() or attach().');
}

if (this._panelContainer.hasClass(oldClass)) {
if (!fromElement && this._panelContainer.hasClass(oldClass)) {
this._panelContainer.removeClass(oldClass);
} else if (fromElement && this._panelEl.hasClass(oldClass)) {
this._panelEl.removeClass(oldClass);
}
};

Expand All @@ -1089,13 +1116,19 @@ MdPanelRef.prototype.removeClass = function(oldClass) {
* Toggle a class on the panel. DO NOT use this to hide/show the panel.
*
* @param {string} toggleClass The class to toggle.
* @param {boolean} onElement Whether or not to toggle the class on the panel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New params need to be added to the public documentation at the top of this file. (For add, remove, and toggle)

* element instead of the container.
*/
MdPanelRef.prototype.toggleClass = function(toggleClass) {
MdPanelRef.prototype.toggleClass = function(toggleClass, onElement) {
if (!this._panelContainer) {
throw new Error('Panel does not exist yet. Call open() or attach().');
}

this._panelContainer.toggleClass(toggleClass);
if (!onElement) {
this._panelContainer.toggleClass(toggleClass);
} else {
this._panelEl.toggleClass(toggleClass);
}
};


Expand Down Expand Up @@ -1131,11 +1164,16 @@ MdPanelRef.prototype._createPanel = function() {
self._panelEl = angular.element(
self._panelContainer[0].querySelector('.md-panel'));

// Add a custom CSS class.
// Add a custom CSS class to the panel element.
if (self._config['panelClass']) {
self._panelEl.addClass(self._config['panelClass']);
}

// Handle click and touch events for the panel container.
if (self._config['propagateContainerEvents']) {
self._panelContainer.css('pointer-events', 'none');
}

// Panel may be outside the $rootElement, tell ngAnimate to animate
// regardless.
if (self._$animate.pin) {
Expand Down Expand Up @@ -1193,6 +1231,20 @@ MdPanelRef.prototype._addStyles = function() {
};


/**
* Updates the position configuration of a panel
* @param {MdPanelPosition} position
*/
MdPanelRef.prototype.updatePosition = function(position) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add this documentation also to the public documentation above, probably with a description of why you someone would use this. (~line 330)

if (!this._panelContainer) {
throw new Error('Panel does not exist yet. Call open() or attach().');
}

this._config['position'] = position;
this._updatePosition();
};


/**
* Calculates and updates the position of the panel.
* @param {boolean=} opt_init
Expand Down
210 changes: 209 additions & 1 deletion src/components/panel/panel.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,34 @@ describe('$mdPanel', function() {
});
});

describe('should cause the propagation of events', function() {
var config, wrapper;

it('to be stopped when propagateContainerEvents=false', function() {
config = {
propagateContainerEvents: false,
template: DEFAULT_TEMPLATE
};

openPanel(config);

wrapper = angular.element(document.querySelector(PANEL_WRAPPER_CLASS));
expect(wrapper.css('pointer-events')).not.toEqual('none');
});

it('to NOT be stopped when propagateContainerEvents=true', function() {
config = {
propagateContainerEvents: true,
template: DEFAULT_TEMPLATE
};

openPanel(config);

wrapper = angular.element(document.querySelector(PANEL_WRAPPER_CLASS));
expect(wrapper.css('pointer-events')).toEqual('none');
});
});

it('should apply a custom css class to the panel', function() {
var customClass = 'custom-class';

Expand Down Expand Up @@ -815,7 +843,6 @@ describe('$mdPanel', function() {
expect(onRemovingCalled).toBe(true);
});


it('should call onDomRemoved if provided when removing the panel from ' +
'the DOM', function() {
var onDomRemovedCalled = false;
Expand Down Expand Up @@ -868,6 +895,87 @@ describe('$mdPanel', function() {
});
});

describe('CSS class logic:', function() {
it('should add a class to the container/wrapper when toElement=false',
function() {
openPanel(DEFAULT_CONFIG);

panelRef.addClass('my-class');

expect(PANEL_WRAPPER_CLASS).toHaveClass('my-class');
expect(PANEL_EL).not.toHaveClass('my-class');
});

it('should add a class to the element when toElement=true', function() {
openPanel(DEFAULT_CONFIG);

panelRef.addClass('my-class', true);

expect(PANEL_WRAPPER_CLASS).not.toHaveClass('my-class');
expect(PANEL_EL).toHaveClass('my-class');
});

it('should remove a class from the container/wrapper when fromElement=false',
function() {
openPanel(DEFAULT_CONFIG);

panelRef.addClass('my-class');

expect(PANEL_WRAPPER_CLASS).toHaveClass('my-class');
expect(PANEL_EL).not.toHaveClass('my-class');

panelRef.removeClass('my-class');

expect(PANEL_WRAPPER_CLASS).not.toHaveClass('my-class');
expect(PANEL_EL).not.toHaveClass('my-class');
});

it('should remove a class from the element when fromElement=true',
function() {
openPanel(DEFAULT_CONFIG);

panelRef.addClass('my-class', true);

expect(PANEL_WRAPPER_CLASS).not.toHaveClass('my-class');
expect(PANEL_EL).toHaveClass('my-class');

panelRef.removeClass('my-class', true);

expect(PANEL_WRAPPER_CLASS).not.toHaveClass('my-class');
expect(PANEL_EL).not.toHaveClass('my-class');
});

it('should toggle a class on the container/wrapper when onElement=false',
function() {
openPanel(DEFAULT_CONFIG);

panelRef.toggleClass('my-class');

expect(PANEL_WRAPPER_CLASS).toHaveClass('my-class');
expect(PANEL_EL).not.toHaveClass('my-class');

panelRef.toggleClass('my-class');

expect(PANEL_WRAPPER_CLASS).not.toHaveClass('my-class');
expect(PANEL_EL).not.toHaveClass('my-class');
});

it('should toggle a class on the element when onElement=true',
function() {
openPanel(DEFAULT_CONFIG);

panelRef.toggleClass('my-class', true);

expect(PANEL_WRAPPER_CLASS).not.toHaveClass('my-class');
expect(PANEL_EL).toHaveClass('my-class');

panelRef.toggleClass('my-class', true);

expect(PANEL_WRAPPER_CLASS).not.toHaveClass('my-class');
expect(PANEL_EL).not.toHaveClass('n-class');
});
});

describe('should focus on the origin element on', function() {
var myButton;
var detachFocusConfig;
Expand Down Expand Up @@ -1115,6 +1223,106 @@ describe('$mdPanel', function() {
mdPanelPosition = $mdPanel.newPanelPosition();
});

describe('should update the position of an open panel', function() {
var xPosition, yPosition, myButton, myButtonRect;

beforeEach(function() {
xPosition = $mdPanel.xPosition;
yPosition = $mdPanel.yPosition;

myButton = '<button>myButton</button>';
attachToBody(myButton);
myButton = angular.element(document.querySelector('button'));
myButtonRect = myButton[0].getBoundingClientRect();
});

it('between two absolute positions', function() {
var top = '50px';
var left = '30px';
var position = $mdPanel.newPanelPosition()
.absolute()
.top(top)
.left(left);

config['position'] = position;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: new line before this one


openPanel(config);

var panelRect = document.querySelector(PANEL_EL)
.getBoundingClientRect();
expect(panelRect.top).toBeApproximately(parseInt(top));
expect(panelRect.left).toBeApproximately(parseInt(left));

var newTop = '500px';
var newLeft = '300px';
var newPosition = $mdPanel.newPanelPosition()
.absolute()
.top(newTop)
.left(newLeft);

panelRef.updatePosition(newPosition);

var newPanelRect = document.querySelector(PANEL_EL)
.getBoundingClientRect();
expect(newPanelRect.top).toBeApproximately(parseInt(newTop));
expect(newPanelRect.left).toBeApproximately(parseInt(newLeft));
});

it('between two relative positions', function() {
var position = $mdPanel.newPanelPosition()
.relativeTo(myButton[0])
.addPanelPosition(xPosition.ALIGN_START, yPosition.ALIGN_TOPS);

config['position'] = position;

openPanel(config);

var panelRect = document.querySelector(PANEL_EL)
.getBoundingClientRect();
expect(panelRect.top).toBeApproximately(myButtonRect.top);
expect(panelRect.left).toBeApproximately(myButtonRect.left);

var newPosition = $mdPanel.newPanelPosition()
.relativeTo(myButton)
.addPanelPosition(null, yPosition.ABOVE);

panelRef.updatePosition(newPosition);

var newPanelRect = document.querySelector(PANEL_EL)
.getBoundingClientRect();
expect(newPanelRect.bottom).toBeApproximately(myButtonRect.top);
});

it('from an absolute to a relative position', function() {
var top = '250px';
var left = '400px';
var position = $mdPanel.newPanelPosition()
.absolute()
.top(top)
.left(left);

config['position'] = position;

openPanel(config);

var panelRect = document.querySelector(PANEL_EL)
.getBoundingClientRect();
expect(panelRect.top).toBeApproximately(parseInt(top));
expect(panelRect.left).toBeApproximately(parseInt(left));

var newPosition = $mdPanel.newPanelPosition()
.relativeTo(myButton[0])
.addPanelPosition(xPosition.ALIGN_START, yPosition.ALIGN_TOPS);

panelRef.updatePosition(newPosition);

var newPanelRect = document.querySelector(PANEL_EL)
.getBoundingClientRect();
expect(newPanelRect.top).toBeApproximately(myButtonRect.top);
expect(newPanelRect.left).toBeApproximately(myButtonRect.left);
});
});

describe('should offset the panel', function() {
it('horizontally', function() {
var left = '50px';
Expand Down