|
|
|||||||||||||||||||||||||||||
|
Модальные диалоговые окна на AJAXИсточник: max404
Код доступен для загрузки по адресу: CuttingEdge2008_Launch.exe (419 KB) Диалоговые окна используются в Windows® уже давно, и у них есть свои премущества. Но если вам нужны диалоговые окна в веб-приложении, обычно приходится использовать всплывающие окна, а пользователи, как известно, обычно блокируют их с помощью специальных программ. Что же делать, если нужно всплывающее диалоговое окно? // Code excerpted from modalpopupbehavior.js. // Method initialize() // // Download the source code of the AJAX Control Toolkit from // http://www.codeplex.com/atlascontroltoolkit. // // The panel defined as the popup is saved as the foreground element. this._foregroundElement = this._popupElement; // A new DIV tag is created as the background element for the panel. // The panel is invisible and placed at 0,0 coordinates (fixed position). // In addition, the background element is given a high z-index so that it // sits above everything else. this._backgroundElement = document.createElement('div'); this._backgroundElement.id = this.get_id() + '_backgroundElement'; this._backgroundElement.style.display = 'none'; this._backgroundElement.style.position = 'fixed'; this._backgroundElement.style.left = '0px'; this._backgroundElement.style.top = '0px'; this._backgroundElement.style.zIndex = 10000; // The background element is styled as specified. if (this._BackgroundCssClass) { this._backgroundElement.className = this._BackgroundCssClass; } // The background element is appended to the parent of the foreground // element. this._foregroundElement.parentNode.appendChild(this._backgroundElement); // The foreground element is programmatically hidden from view. In // addition, it is given absolute positioning and an higher z-index than // the background element. this._foregroundElement.style.display = 'none'; this._foregroundElement.style.position = 'fixed'; this._foregroundElement.style.zIndex = $common.getCurrentStyle( this._backgroundElement, 'zIndex', this._backgroundElement.style.zIndex) + 1; // A click handler is added to the target element of the extender. In // this case, It is the DOM element whose ID is passed on as the // TargetControlID property. this._showHandler = Function.createDelegate(this, this._onShow); $addHandler(this.get_element(), 'click', this._showHandler); Код представляет собой выдержку из сценария, используемого для запуска расширения ModalPopup на клиенте. Заметьте, что расширение AJAX для ASP.NET обычно состоит из серверного элемента управления, расширения и класса поведения клиента, написанного на JavaScript. Код на рис. 1 - из класса поведения клиента расширения ModalPopup. Если вы загрузили исходный код набора AJAX Control Toolkit со страницы codeplex.com/atlascontroltoolkit, вышеуказанный код можно найти в файле modalpopupbehavior.js.
Элемент управления ModalPopupExtenderСоздать модальное всплывающее окно с помощью библиотеки AJAX Control Toolkit достаточно просто. Сначала нужно определить панель, обеспечивающую пользовательский интерфейс, а затем добавить кнопку, запускающую отображение диалогового окна: <asp:Button runat="server" ID="btnEditCustomer" Text="Edit text" /> <asp:Panel runat="server" ID="pnlEditCustomer"> ... </asp:Panel> Затем нужно настроить расширение и указать идентификаторы целевого элемента управления и всплывающего окна: <act:ModalPopupExtender ID="ModalPopupExtender1" runat="server" TargetControlID="btnEditCustomer" PopupControlID="pnlEditCustomer" BackgroundCssClass="modalBackground" OkControlID="editBox_OK" OnOkScript="yes()" /> Идентификатор элемента управления цели расширения ModalPopup - идентификатор серверного элемента управления , который вызывает появление диалогового окна при нажатии. Идентификатор элемента управления всплывающего окна - идентификатор того серверного элемента управления, который обеспечивает содержимое диалогового окна.
Можно добавить ряд функций, чтобы расширение ModalPopup выглядело похожим на диалоговое окно Windows. Например, полезно добавить возможность закрыть диалоговое окно нажатием клавиши Esc - обычная функция в Windows, пока не поддерживаемая AJAX Control Toolkit. BackgroundCssClass Класс CSS, связанный с размещающим приложением и применяемый к любому содержимому под отображаемым модальным всплывающим окном. Сигнатура класса элемента управления ModalPopupExtender такова: public class ModalPopupExtender : DynamicPopulateExtenderControlBase Здесь основной класс - расширение, определяемое библиотекой и обеспечивающее поддержку DynamicPopulate для множественных расширений. DynamicPopulate - еще одно расширение AJAX Control Toolkit, заменяющее разметку элемента DOM текстом, возвращенным вызовом к веб-службе. Расширение ModalPopup зависит от других расширений AJAX Control Toolkit, включая DropShadow и DragPanel.
Закрытие всплывающего окна клавишей EscВ Windows пользователь может закрыть сообщение или диалоговое окно, нажав клавишу Esc. Исходно такая возможность не заложена в поведение модальных всплывающих окон AJAX Control Toolkit. Сейчас вы увидите, что обнаружить и обработать нажатие клавиши Esc нетрудно. Посмотрите на этот код JavaScript, связанный с событием KeyDown в модели DOM страницы: function OnKeyPress(args) { if(args.keyCode == Sys.UI.Key.esc) { $find("ModalPopupExtender1").hide(); } } Код запускается нажатиями клавиш, влияющими на весь документ. Обработчик получает объект Sys.UI.DomEvent через параметр args. Объект описывает состояние мыши и клавиатуры, когда перехватывается событие на уровне модели DOM. В частности, свойство keyCode указывает код ASCII нажатой клавиши. Доступна дополнительная информация о клавишах Ctrl, Shift и Alt, а также информация о положении курсора и состоянии кнопок. Перечисление Sys.UI.Key описывает некоторые предопределенные константы для кода наиболее часто используемых клавиш, в том числе Esc, Enter и Del. С помощью этих средств обнаружить нажатие клавиши Esc проще простого. Посмотрим, как запрограммировать сокрытие всплывающего окна. function pageLoad(sender, args) { $addHandler(document, "keydown", OnKeyPress); } Библиотека Microsoft AJAX вызывает функцию pageLoad, когда закончены все задачи по запуску и инициализировано всё в библиотеке и на странице. Кроме того, библиотека автоматически связывает свою стадию загрузки с любой функцией JavaScript, которую можно найти на странице. Теперь любое модальное всплывающее окно под управлением расширения ModalPopup AJAX Control Toolkit можно убрать клавишей Esc.
Добавление анимации на экранЗакончив с этим, можно перейти к другим вещам. Было бы неплохо использовать что-то вроде эффекта постепенного появления, которые использует Windows Vista® для веб-приложений, не правда ли? Этот эффект встроен в обычные окна под управлением Windows, например те, которые всплывают при вызове метода window.alert. В пользовательских модальных всплывающих окнах, наподобие тех, которыми мы занимаемся, придется делать это самим. <act:AnimationExtender ID="popUpAnimation" runat="server" TargetControlID="btnViewMore"> <Animations> <OnClick> <Parallel AnimationTarget="pnlViewCustomer" Duration=".3" Fps="25"> <FadeIn /> </Parallel> </OnClick> </Animations> </act:AnimationExtender> Анимации можно собирать в последовательность, а некоторые можно даже проигрывать одновременно. Приведенный выше код просто медленно выводит панель, связанную с модальным всплывающим окном, за указанный период времени и количество кадров после нажатия кнопки. Код ниже показывает более сложную анимацию, выполняющую несколько эффектов: <act:AnimationExtender ID="popUpAnimation" runat="server" TargetControlID="btnViewMore"> <Animations> <OnClick> <Parallel AnimationTarget="pnlViewCustomer" Duration=".3" Fps="25"> <Move Horizontal="100" Vertical="100" /> <Resize Width="280" Height="180" /> <Color PropertyKey="backgroundColor" StartValue="#FFFFFF" EndValue="#FFFF00" /> </Parallel> </OnClick> </Animations> </act:AnimationExtender> Здесь модальное всплывающее окно сперва передвигается в новое относительное положение, а затем масштабируется и окрашивается. Несколько примеров можно найти в галерее на странице asp.net/AJAX/AjaxControlToolkit/Samples/Animation/Animation.aspx; большинство из них можно применить к модальному всплывающему окну, только изменив исходный код. Главная проблема заключается в том, что модальное всплывающее окно отображается до запуска анимации. Это может сгодиться для простого эффекта медленного появления, но если вам нужны эффекты взрыва или смывания, придется поднапрячься. function pageLoad(sender, args) { $find("ModalPopupExtender1").add_showing(onModalShowing); } Любой код, связанный с событием отображения, выполняется непосредственно перед отображением всплывающего окна. Это событие можно использовать для выполнения любых задач инициализации на стороне клиента. Другие события клиента, к которым можно привязаться, включают hiding (сокрытие), hidden (скрыто) и shown (отображено). <table> <tr> <td valign="top"> <b>Customers</b><br /> <asp:DropDownList id="ddlCustomers" runat="server" DataSourceID="odsCustomers" DataTextField="CompanyName" DataValueField="ID" AutoPostBack="true" OnSelectedIndexChanged="ddlCustomers_SelectedIndexChanged" ondatabound="ddlCustomers_DataBound" /> <asp:ObjectDataSource ID="odsCustomers" runat="server" TypeName="IntroAjax.CustomerManager" SelectMethod="LoadAll"> </asp:ObjectDataSource> </td> <td valign="top"> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <table> <tr> <td><b>Customer ID:</b></td> <td> <asp:Label runat="server" id="lblCustomerID" /> </td> </tr> <tr> <td><b>Company Name:</b></td> <td> <asp:Label runat="server" id="lblCompanyName" /> </td> </tr> <tr> <td><b>Contact Name:</b></td> <td> <asp:Label runat="server" id="lblContactName" /> </td> </tr> <tr> <td><b>Country:</b></td> <td><asp:Label runat="server" id="lblCountry" /></td> </tr> </table> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="ddlCustomers" EventName="SelectedIndexChanged" /> </Triggers> </asp:UpdatePanel> </td> </tr> </table> Следующий этап - обновить панель на рис. 6, которая представляет содержимое модального всплывающего окна. Панель должна быть синхронизирована с представлением клиента. <asp:Panel ID="pnlEditCustomer" runat="server" CssClass="modalPopup" style="display:none"> <div style="margin:10px"> <asp:UpdatePanel runat="server" ID="ModalPanel1" RenderMode="Inline" UpdateMode="Conditional"> <ContentTemplate> <table> <tr> <td><b>Customer ID:</b></td> <td> <asp:Label runat="server" id="editCustomerID" /> </td> </tr> <tr> <td><b>Company Name:</b></td> <td> <asp:TextBox runat="server" id="editTxtCompanyName" /> </td> </tr> <tr> <td><b>Contact Name:</b></td> <td> <asp:TextBox runat="server" id="editTxtContactName" /> </td> </tr> <tr> <td><b>Country:</b></td> <td> <asp:TextBox runat="server" id="editTxtCountry" /> </td> </tr> </table> <hr /> <asp:Button ID="btnApply" runat="server" Text="Apply" OnClick="btnApply_Click" /> </ContentTemplate> </asp:UpdatePanel> <asp:Button ID="editBox_OK" runat="server" Text="OK" OnClick="editBox_OK_Click" /> <asp:Button ID="editBox_Cancel" runat="server" Text="Cancel" /> </div> </asp:Panel> Панель можно обновлять при появлении нового клиента, когда панель отображается, или прямо перед отображением панели: <act:ModalPopupExtender ID="ModalPopupExtender1" runat="server" TargetControlID="hiddenTargetControlForModalPopup" PopupControlID="pnlEditCustomer" BackgroundCssClass="modalBackground" DropShadow="false" OkControlID="editBox_OK" OnOkScript="ok()" OnCancelScript="cancel()" CancelControlID="editBox_Cancel" /> Если содержимое всплывающего окна обновляется сразу перед отображением (я рекомендую этот подход), код инциализации окна должен выполняться на сервере, зато у вас не будет событий обратной передачи от элементов управления, выводящих модальное окно. Даже если они будут, изменять элементы управления диалогового окна будет поздно. Расширение ModalPopup добавляет к целевому элементу управления обработчик события щелчка со стороны клиента и предотвращает действие по умолчанию - в данном случае обратную передачу. <asp:UpdatePanel runat="server" ID="DialogBoxUpdatePanel" UpdateMode="Conditional"> <ContentTemplate> <asp:Button runat="server" ID="btnEditText" Text="Edit text" OnClick="btnEditText_Click" /> </ContentTemplate> </asp:UpdatePanel> Это имеет два преимущества. Во-первых, страница не обновляется целиком. Во-вторых, код OnClick на сервере можно использовать, чтобы правильно инициализировать всплывающую панель, а затем указать расширению отобразить всплывающее окно: protected void btnEditText_Click(object sender, EventArgs e) { InitDialog(); ModalPanel1.Update(); ModalPopupExtender1.Show(); } Метод InitDialog содержит внутренний код, необходимый для инициализации всех элементов управления в панели на рис. 6. Код достаточен, чтобы изменить состояние элементов управления, но не изменяет их разметки. Так получается потому, что код выполняется над обратной передачей частичной визуализации. Следующим шагом нужно обновить перезагружаемую панель. Наконец, вызвать на расширение ModalPopup метод Show. Этот вызов обеспечивает правильную загрузку в обозреватель сценария, показывающего диалоговое окно при загрузке страницы. На рис. 7 показана действующая страница, созданная по этим рекомендациям.
Так ли нужны на странице все эти области частичной визуализации? Если ваша единственная задача - выяснить, как запускать диалоговые окна серверным кодом, тогда, пожалуй, без некоторых областей можно обойтись. Но если диалоговое окно требует работы по инициализации со стороны сервера, то оно наверняка должно обновлять подлежащую страницу собранными данными. В этом случае придется возвращать данные на сервер.
Возврат данных на серверРасширение ModalPopup позволяет определять элементы управления, служащие кнопками OK и Отмена с помощью специальных свойств OkControlID и CancelControlID. При нажатии на эти кнопки, всплывающее окно закрывается и, при необходимости, выполняется какой-нибудь код JavaScript. С помощью свойств OnOkScript и OnCancelScript можно определить выполнение какой-либо функции JavaScript при нажатии кнопок "OK" и "Отмена". Окно не делает обратной передачи, если нажаты предустановленные кнопки "ОК" и "Отмена". Пояснения - в приведенном фрагменте исходного кода из файла modalpopupbehavior.js. Код принадлежит встроенным обработчикам события нажатия для обеих кнопок, "ОК" и "Отмена": var element = $get(this._OkControlID); if (element && !element.disabled) { if (this.hide() && this._OnOkScript) { window.setTimeout(this._OnOkScript, 0); } e.preventDefault(); return false; } Вот пример обработчика кнопки ОК: function onOK(sender, e) { // refresh the UI // if you need to run server code, you // can invoke a Web service method }
Теперь ваш ходДля выполнения этого примера я не добавлял код в существующие элементы управления или поведение клиента. Я просто использовал существующий набор элементов (и клиента, и сервера), чтобы улучшить инициализацию диалогового окна и обмен данными с главной страницей. Чтобы избежать полной перезагрузки страницы, я использовал частичную визуализацию, где это было уместно. Ссылки по теме
|
|