Stel:
Ik heb een textbox. Als ik daar op klik wil ik een popup. In die popup bied ik de mogelijkheid om te zoeken. Wanneer ik meer dan x resultaten heb wil ik een modal popup die meldt dat er teveel resultaten zijn en dat alleen de eerste 100 getoond worden.
Stel:
Ik heb een textbox. Als ik daar op klik wil ik een popup. In die popup bied ik de mogelijkheid om te zoeken. Wanneer ik meer dan x resultaten heb wil ik een modal popup die meldt dat er teveel resultaten zijn en dat alleen de eerste 100 getoond worden.
Implementatie:
a) textbox, b) panel voor de popup, c) popupextender om van b een popup te maken, d) panel voor de modal popup en e) modalpopupextender om van d) een modal popup te maken.
Wanneer we dit implementeren ziet dat er als volgt uit:

Precies wat we willen, totdat we de modal popup dichtklikken. Het blijkt dat dan ook onze zoekpopup verdwijnt. En als we nog iets verder kijken blijkt ook dat onze zoekpopup verdwijnt als we waar dan ook op het (browser)scherm klikken.
De oorzaak hiervoor is tweeledig.
1) Bij het plaatsen van een popupextender wordt in 'PopupControlBehavior.js' een eventhandler gekoppeld aan het click-event op document.body. In dit click-event (_onBodyClick) wordt gekeken of de popup visible is. Als dit zo is wordt hij ge-hide. Dit is 'by design'. Immers, je wilt dat de popup verschijnt als je op de textbox klikt en verdwijnt als je op een Ok of Annuleer button of iets dergelijks klikt, maar ook als je buiten de popup klikt. Deze functionaliteit mag echter niet uitgevoerd worden als er een element 'over de popup heen' gepositioneerd is.
Dit kunnen we oplossen door de _onBodyClick functie aan te passen.
Code:
_onBodyClick : function() {
/// <summary>
/// Handler for the HTML body tag's click event
/// </summary>
// Hide the popup if something other than our target or popup
// was clicked (since each of these stop the event from bubbling
// up to the body)
if (this._popupVisible) {
this.hidePopup();
}
},
wordt:
Code:
_onBodyClick : function() {
/// <summary>
/// Handler for the HTML body tag's click event
/// </summary>
// Hide the popup if something other than our target or popup
// was clicked (since each of these stop the event from bubbling
// up to the body)
if (this._popupVisible) {
// First determine the zIndex of the popup itself
var selfIndex;
if (this._popupElement.style)
{ selfIndex = this._popupElement.style.zIndex}
else //NS 4
{ selfIndex = this._popupElement.zIndex};
// Now create a variable to hold the highest zIndex of all other div's
highestIndex = 0;
// Loop through all div's and determine their zIndex
elements = document.getElementsByTagName("div");
for (i=0; i < elements.length; i++) {
var index;
var display;
if (elements[i].style)
{
index = elements[i].style.zIndex;
display = elements[i].style.display;
}
else
{
index = elements[i].zIndex;
display = elements[i].display;
};
if (index > highestIndex && display != "none") {highestIndex = index};
}
if (highestIndex <= selfIndex) {
this.hidePopup();
}
}
},
Wat er hier gebeurd is dat we door alle DIV's op de pagina heenlopen en kijken of er ééntje is met een hogere z-index dan de popup en die ook nog zichtbaar is. Als dat zo is mag de popup niet ge-hide worden en anders hiden we hem.
Nu is dat probleem opgelost. Bij verder testen blijkt echter dat het klikken buiten de popups nu wel goed gaat maar dat op het moment dat we binnen de modal popup op Ok of Cancel klikken verdwijnt niet alleen de modal maar ook de gewone popup.
Dit wordt veroorzaakt door het zogenaamde event-bubbling. Er wordt een click-event geraised op het moment dat we op Ok of Cancel klikken. De achterliggende code wordt uitgevoerd en deze laat de modal popup verdwijnen. Vervolgens bubble't het event echter door naar de body. Als gevolg hiervan wordt uiteindelijk de eerdergenoemde _onBodyClick functie uitgevoerd. Aangezien de modal popup al netjes is opgeruimd is er geen element meer dat over de popup heen staat dus wordt deze ook opgeruimd. Er is immers buiten de popup geklikt en die stond 'bovenop'.
Dit lossen we op door in ModalPopupBehavior.js de volgende wijzigingen door te voeren:
Code:
_onOk : function(e) {
/// <summary>
/// Handler for the modal dialog's OK button click
/// </summary>
/// <param name="e" type="Sys.UI.DomEvent">
/// Event info
/// </param>
var element = $get(this._OkControlID);
if (element && !element.disabled) {
this.hide();
e.preventDefault();
if (this._OnOkScript) {
window.setTimeout(this._OnOkScript, 0);
}
return false;
}
},
_onCancel : function(e) {
/// <summary>
/// Handler for the modal dialog's Cancel button click
/// </summary>
/// <param name="e" type="Sys.UI.DomEvent">
/// Event info
/// </param>
var element = $get(this._CancelControlID);
if (element && !element.disabled) {
this.hide();
e.preventDefault();
if (this._OnCancelScript) {
window.setTimeout(this._OnCancelScript, 0);
}
return false;
}
},
wordt uitgebreid door vóór de this.hide() het bubble'n van de events te stoppen. Dit doen we met de code:
Code:
e.cancelBubble = true; //MS IE
if (e.stopPropagation) e.stopPropagation(); //FF
Uiteindelijk ziet deze code er dus als volgt uit:
Code:
_onOk : function(e) {
/// <summary>
/// Handler for the modal dialog's OK button click
/// </summary>
/// <param name="e" type="Sys.UI.DomEvent">
/// Event info
/// </param>
var element = $get(this._OkControlID);
if (element && !element.disabled) {
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
this.hide();
e.preventDefault();
if (this._OnOkScript) {
window.setTimeout(this._OnOkScript, 0);
}
return false;
}
},
_onCancel : function(e) {
/// <summary>
/// Handler for the modal dialog's Cancel button click
/// </summary>
/// <param name="e" type="Sys.UI.DomEvent">
/// Event info
/// </param>
var element = $get(this._CancelControlID);
if (element && !element.disabled) {
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
this.hide();
e.preventDefault();
if (this._OnCancelScript) {
window.setTimeout(this._OnCancelScript, 0);
}
return false;
}
},