Skip to content

Commit ea092d6

Browse files
committed
Firefly-91: fixed dropdown opening in visible area, when too far right
1 parent 2295512 commit ea092d6

File tree

6 files changed

+72
-28
lines changed

6 files changed

+72
-28
lines changed

src/firefly/js/ui/DialogRootContainer.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function computeZIndex(element ) {
153153
/**
154154
* @param {string} dialogId
155155
* @param {object} dialog
156-
* @param {Element} overElement
156+
* @param {Element} [overElement]
157157
*/
158158
function defineDialog(dialogId, dialog, overElement) {
159159
if (!divElement) init();

src/firefly/js/ui/DropDownMenu.css

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
border-radius: 0 0 5px 5px;
55
background-color: rgba(245,245,245,.97);
66
box-shadow: 0 5px 10px rgba(0,0,0,0.3);
7-
min-width: 180px;
7+
min-width: 100px;
88
}
99

1010

@@ -29,7 +29,8 @@
2929
.dropdown-menu__right {
3030
position: absolute;
3131
top: -10px;
32-
left: 8px;
32+
/*left: 8px;*/
33+
left: 13px;
3334
}
3435

3536

src/firefly/js/ui/DropDownMenu.jsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const DROP_DOWN_WRAPPER_CLASSNAME= 'ff-dropdown-menu';
1313

1414
const computePosition= (tgtX,tgtY) => ({x:tgtX,y:tgtY+18});
1515

16-
function placeDropDown(e,x,y) {
16+
function placeDropDown(e,x,y, beforeVisible) {
1717
var pos= computePosition(x,y);
1818

1919
var left= pos.x - 10;
@@ -22,6 +22,7 @@ function placeDropDown(e,x,y) {
2222
}
2323
e.style.left= left +'px';
2424
e.style.top= (pos.y + 10)+'px';
25+
if (isFunction(beforeVisible)) beforeVisible(e);
2526
e.style.visibility='visible';
2627
}
2728

@@ -42,12 +43,12 @@ export class DropDownMenuWrapper extends PureComponent {
4243
}
4344

4445
componentDidMount() {
45-
var {x,y}= this.props;
46-
placeDropDown(ReactDOM.findDOMNode(this),x,y);
46+
const {x,y,beforeVisible}= this.props;
47+
placeDropDown(ReactDOM.findDOMNode(this),x,y, beforeVisible );
4748
}
4849
componentDidUpdate() {
49-
var {x,y}= this.props;
50-
placeDropDown(ReactDOM.findDOMNode(this),x,y);
50+
const {x,y,beforeVisible}= this.props;
51+
placeDropDown(ReactDOM.findDOMNode(this),x,y, beforeVisible);
5152
}
5253

5354
render() {
@@ -74,14 +75,15 @@ DropDownMenuWrapper.propTypes= {
7475
x : PropTypes.number.isRequired,
7576
y : PropTypes.number.isRequired,
7677
content : PropTypes.object.isRequired,
77-
zIndex : PropTypes.number
78+
zIndex : PropTypes.number,
79+
beforeVisible : PropTypes.func
7880
};
7981

8082

8183

8284
export class DropDownSubMenu extends PureComponent {
8385

84-
constructor(props, context) {
86+
constructor(props) {
8587
super(props);
8688
this.state= {showSubMenu: false};
8789
this.show = this.show.bind(this);
@@ -118,7 +120,8 @@ export class DropDownSubMenu extends PureComponent {
118120
}
119121
</div>
120122

121-
{<div className={'arrow-right'}/>}
123+
{/*{<div style={{marginLeft:5}} className={'arrow-right'}/>}*/}
124+
{<div style={{marginLeft:5}} className={'arrow-right'}/>}
122125

123126
</div>
124127
</div>

src/firefly/js/ui/DropDownToolbarButton.jsx

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,50 @@ import {DropDownDirCTX} from './DropDownDirContext.js';
1616
import {DROP_DOWN_WRAPPER_CLASSNAME} from './DropDownMenu';
1717

1818

19-
function computeDropdownXY(divElement, isIcon) {
19+
/**
20+
* j
21+
* @param {Element} buttonElement
22+
* @param isIcon
23+
* @param {Element} dropdownElement
24+
* @return {{x: number, y: number}}
25+
*/
26+
function computeDropdownXY(buttonElement, isIcon, dropdownElement) {
2027
const bodyRect = document.body.parentElement.getBoundingClientRect();
21-
const off= isIcon ? 0 : 6;
22-
const elemRect = divElement.getBoundingClientRect();
23-
const x = (elemRect.left - bodyRect.left);
24-
const y = elemRect.top - bodyRect.top- off;
28+
const dropdownRect = dropdownElement.getBoundingClientRect();
29+
const elemRect = buttonElement.getBoundingClientRect();
30+
const off= isIcon ? 4 : 10;
31+
let x = elemRect.left - bodyRect.left - 10;
32+
const leftAdjust= (bodyRect.right-20 < x + dropdownRect.width) ? dropdownRect.width-elemRect.width-20 : 0;
33+
x-= leftAdjust;
34+
const y = elemRect.bottom - bodyRect.top- off;
2535
return {x,y};
2636
}
2737

2838

29-
function showDialog(divElement,dropDown,ownerId,offButtonCB, isIcon) {
30-
const {x,y}= computeDropdownXY(divElement, isIcon);
39+
/**
40+
* Compute the drop down position and build the react components to show the dropdown.
41+
* The dropdown position is computed in two phases. The normal position and after the dropdown element exist
42+
* it is check to make sure it is not going off the right side of the screen. Part 2 is done in the beforeVisible
43+
* callback. At that point the element has be created and the visibility is set ot hidden. They way we can do side
44+
* computations.
45+
*
46+
* @param {Object} buttonElement - the div of where the button is
47+
* @param {Object} dropDown - dropdown React component
48+
* @param {String} ownerId
49+
* @param {function} offButtonCB
50+
* @param {boolean} isIcon
51+
*/
52+
function showDialog(buttonElement,dropDown,ownerId,offButtonCB, isIcon) {
53+
54+
const beforeVisible= (e) =>{
55+
if (!e) return;
56+
const {x,y}= computeDropdownXY(buttonElement,isIcon, e);
57+
e.style.left= x+'px';
58+
e.style.top= y+'px';
59+
};
3160

32-
const dropDownClone= React.cloneElement(dropDown, { toolbarElement:divElement });
33-
const dd= <DropDownMenuWrapper x={x} y={y} content={dropDownClone}/>;
61+
const dropDownClone= React.cloneElement(dropDown, { toolbarElement:buttonElement});
62+
const dd= <DropDownMenuWrapper x={0} y={0} content={dropDownClone} beforeVisible={beforeVisible}/>;
3463
DialogRootContainer.defineDialog(DROP_DOWN_KEY,dd);
3564
document.removeEventListener('mousedown', offButtonCB);
3665
dispatchShowDialog(DROP_DOWN_KEY,ownerId);
@@ -52,6 +81,7 @@ export class DropDownToolbarButton extends PureComponent {
5281
this.state= {dropDownVisible:false, dropDownOwnerId:null };
5382
this.ownerId= uniqueId(OWNER_ROOT);
5483
this.mounted= true;
84+
this.divElement= undefined;
5585
}
5686

5787
componentWillUnmount() {
@@ -76,12 +106,11 @@ export class DropDownToolbarButton extends PureComponent {
76106
}
77107

78108
offButtonCallback(ev) {
79-
document.removeEventListener('mousedown', this.docMouseDownCallback);
80109
delay( () => {
110+
document.removeEventListener('mousedown', this.docMouseDownCallback);
81111
const {dropDownVisible, dropDownOwnerId}= this.state;
82-
if (!dropDownVisible) {
83-
return;
84-
}
112+
if (!dropDownVisible) return;
113+
85114
let e= document.activeElement;
86115
let focusIsDropwdownInput= false;
87116
if (e && e.tagName==='INPUT') {
@@ -92,9 +121,17 @@ export class DropDownToolbarButton extends PureComponent {
92121
}
93122
}
94123
}
124+
e= ev.target;
125+
const maxBack= 10;
126+
let clickOnButton= false;
127+
for(let i=0;(e&&i<maxBack);e= e.parentElement,i++) {
128+
if (this.divElement===e) {
129+
clickOnButton= true;
130+
break;
131+
}
132+
}
95133
const onDropDownInput= focusIsDropwdownInput && ev && ev.target.tagName==='INPUT';
96-
console.log(ev);
97-
if (!onDropDownInput&& dropDownVisible && dropDownOwnerId===this.ownerId) {
134+
if (!clickOnButton && !onDropDownInput && dropDownOwnerId===this.ownerId) {
98135
dispatchHideDialog(DROP_DOWN_KEY);
99136
}
100137
else {
@@ -106,11 +143,13 @@ export class DropDownToolbarButton extends PureComponent {
106143

107144
handleDropDown(divElement,dropDown) {
108145
if (divElement) {
146+
this.divElement= divElement;
109147
const isIcon= Boolean(this.props.icon);
110148
const {dropDownVisible, dropDownOwnerId}= this.state;
111149

150+
const dropdownDirection= calcDropDownDir(divElement, this.props.menuMaxWidth);
112151
const dropDownWithContext= (
113-
<DropDownDirCTX.Provider value={{dropdownDirection: calcDropDownDir(divElement, this.props.menuMaxWidth)}}>
152+
<DropDownDirCTX.Provider value={{dropdownDirection}}>
114153
{dropDown}
115154
</DropDownDirCTX.Provider>
116155
);

src/firefly/js/ui/ToolbarButton.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
justify-content: space-between;
1414
width: 100%;
1515
align-items: center;
16+
min-width: 180px;
1617
}
1718

1819
.ff-MenuItem-dark:HOVER {

src/firefly/js/ui/ToolbarButton.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export function makeBadge(cnt) {
2020

2121
export function makeDropDownIndicator(cnt) {
2222
// return (<img className={'ff-dropDownIndicator'} src={DROP_DOWN_ICON}/>);
23-
return (<img src={DROP_DOWN_ICON}/>);
23+
return (<img src={DROP_DOWN_ICON} style={{width:11, height:6, alignSelf: 'center'}}/>);
2424
}
2525

2626

0 commit comments

Comments
 (0)