Calling server side method from jquery dialog - javascript

I'm moving my search functionality into a jquery dialog.
Originally I had
Use the following search box to located by Last Name
Search By:
Search
I've added the following javascript :
var dlgSearch = $("#SearchDialog").dialog({
autoOpen: false,
zIndex: 9999,
bgiframe: true,
resizable: false,
width: 450,
modal: true,
overlay: {
backgroundColor: '#000',
opacity: 0.5
},
buttons: {
'Search':
function() {
<%= Page.ClientScript.GetPostBackEventReference(btnSearch, String.Empty) %>;
},
Cancel: function() {
$(this).dialog('close');
}
}
});
dlgSearch.parent().appendTo($("form:first"));
This works fine. However Now I rendering 2 search buttons to the browser. the original one rendered with the tag, and the button rendered with the jquery dialog instantiation. I'd like to get rid of the one rendered with the server side tag and only use the jquery one.
The problem is, if I remove the tag, I get a compile error at the GetPostBackEventReference call because the control btnSearch no longer exists.
I could alway style the btnSearch with CSS and make it display:none, but that just seems like a dirty way to address the problem.
Isn't there a way to call a server side method without it being tied to a controls event?
Be aware that I don't want an ajax callback approach, I need to actually have a postback.

use this on client: __doPostBack("SearchDialog", ""); and this on server:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack && Request.Form["__EVENTTARGET"] == "SearchDialog")
{
//your code here
}
}

Related

jquery-ui dialog in colorbox results to Maximum call stack size exceeded error

I am using jquery-ui and it's dialog functionality to display modal dialogs in my web app. It works ok.
At one use case, I have a colorbox popup window on a screen, and once user finishes his input I need to display a confirmation dialog.
Also here everything actually works thanks to error handling on all the major browsers I tried, but I worry what problems might some combination of javascript engine&browser could cause.
The error I get is call stack size overflow (Chrome shows it as Uncaught RangeError: Maximum call stack size exceeded.).
The code for the modal dialog is:
function modalDialog(dialogText, dialogTitle, okFunc, okLabel, cancelFunc, cancelLabel) {
var dialogButtons = {};
dialogButtons[okLabel] = function() {
if (typeof(okFunc) == 'function') {
setTimeout(okFunc, 50);
}
$(this).dialog('destroy');
};
dialogButtons[cancelLabel] = function() {
if (typeof(cancelFunc) == 'function') {
setTimeout(cancelFunc, 50);
}
$(this).dialog('destroy');
};
$('<div style="padding: 10px; max-width: 500px; word-wrap: break-word;">' + dialogText + '</div>').dialog({
draggable: true,
modal: true,
resizable: false,
width: 'auto',
title: dialogTitle || 'Confirm',
minHeight: 75,
buttons: dialogButtons
});
}
The colorbox is called in javascript, and it takes embedded div from the actual page as it's content:
$(function() {
$(".colorbox-load").colorbox({
inline: true,
overlayClose: false,
href: "#popupContents",
height: "320",
width: "300"
});
})
In the popup, I have a button which just opens up the confirmation dialog.
I apologize in advance as it's my first time using JSFiddle, and I wasn't able to get colorbox and dialog popup match exactly how it looks on my page (it actually pops up properly on top of the colorbox and not "in the background"). I'm not sure if this is because I had to use different versions of jquery and jquery-ui (I couldn't find same combination I am using from the pulldown) or something else.
A JSFiddle is here. If you click around the colorbox area once the "open dialog" button has been pressed you should get same error (firefox and Chrome seem to react slightly differently when to show the error).
Thank you for any suggestions!
It seems like the Dialog and Colorbox are fighting for the focus. Setting the trapFocus setting to false will resolve this issue. Of course it might have some side effects for your page depending on how you use it. Please consult the official documentation for details.
$(function() {
$(".colorbox-load").colorbox({
inline: true,
overlayClose: false,
href: "#popupContents",
height: "320",
width: "300",
trapFocus: false
});
})

Adding Buttons with Functionality Using JavaScript in Bootstrap

I have created a modal window below to have customized buttons and functionality attached to those buttons using jQuery-UI. However, I want to do the equivalent in Bootstrap using JavaScript and not using data attributes. How would I do this? The Bootstrap website only gives the example of doing something like this using data attributes.
function showWindow(message) {
windowShowing = true;
$("#alertWindow").dialog(
{
height: 120,
modal: true,
buttons:
{
Continue: function(){$(this).dialog("close"); someProcedure();},
Exit: function(){$(this).dialog("close"); exitProcedure();}
},
close: function(){windowShowing = false;}
});
$("#alertWindowMsg").text(message);
}
You can add separate handlers and use the modal methods provided by Bootstrap. Something like
$(".close-button").click(function(){
$('#myModal').modal('hide');
exitProcedure();
});
$(".continue-button").click(function(){
$('#myModal').modal('hide');
continueProcedure();
});

how to display a particular string in color in pop up alert in Javascript

I would like to display a particular text in color in the pop up alert box message in a Java script.
For example:
function redirect()
{
if ERCode == 'TEST'
{
alert("You will be redirected to www.google.com.");
}
}
I want www.google.com to be displayed in Blue color when the pop alert comes.
Is this possible in Java Script?
Is it possible to underline atleast a string?
No, this is not possible with alert.
You cannot do it using the default popup dialog. You'll need to use something like http://jqueryui.com/dialog/
You can't, the alert box uses what ever color the browser developers set it to.
The only way to to get a custom colored alert box is to create your own and write the code for it. An example of a custom html alert that adds no dependencies. I haven't tested that code but it seems like it would work.
Using jQuery and jQuery UI.
var dialogUI = $( '<p>You text here google.com</p>' ).dialog( {
modal: true,
title: 'Alert',
buttons: {
'Okay': function() {
dialogUI.dialog( 'destroy' );
// code going to google here
}
}
} );
Not possible in alert but using jQuery (there are other libraries too) you can achieve this, i.e.
function redirect()
{
if ERCode == 'TEST'
{
$('<div/>', {'html':'You will be redirected to <span style="color:blue">www.google.com.</span>'})
.dialog({
width:400,
height:'auto',
modal:true,
resizable:false,
buttons: {
"Ok":function(){
//$(this).dialog("close");
window.location='www.google.com';
}
}
});
}
}
Example Here. or This One.

Using tinyMCE into modal window

I'm using Grails 1.3.7 and I use tinyMCE via richui. I'm trying to display a modal window which enables users to send a mail. However, if tinyMCE is correctly displayed, I can't use the text editor because of this error :
t.win.document is null
I finally found the reason here, at the end of the article :
http://blog.mirthlab.com/2008/11/13/dynamically-adding-and-removing-tinymce-instances-to-a-page/
It seems that when I call the page with the jquery script building the modal window, DOM isn't refreshed and doesn't create the corresponding textarea.
Anyway I don't know how to resolve this, so here is my code :
Jquery code :
function dialogSendFirstMail(id) {
var monurl = "/myApp/emailTemplate/writeFirstMail.gsp?id_for_mail="+id;
var titre = "Premier email"
//alert(monurl);
$("#dialogSendFirstMail").load(monurl, function() {
$(this).dialog({
height: 'auto',
width:'auto',
modal: true,
position: 'center',
overlay: {
backgroundColor: '#000',
opacity: 0.5
},
title:titre
});
});
}
GSP calling the script for the modal window :
<!-- ... -->
<g:if test="${params.sendFirstMail}" >
<div id="dialogSendFirstMail"></div>
<script>dialogSendFirstMail(${idProfil});</script>
</g:if>
</body>
modal window (only this for the moment) :
<richui:richTextEditor name="firstMail" value="%Email_de_bienvenue%"/>
In summary, if I detect that I have to send a first mail, the page creates a div in which is placed tinyMCE. This is what the user will see.
As you have mentioned, the reason that you the the error "t.win.document is null" is because the DOM isn't refreshed. So you will have to add the tinyMCE control explicitly when you load the modal dialog. You can use something like this in the gsp which renders the richUI editor (writeFirstMail.gsp in your case) :
jQuery(document).ready(function() {
//your tinyMCE settings here
tinyMCE.settings = {
mode : "textareas",
theme : "simple",
editor_selector : "mcesimple",
width: 400
};
tinyMCE.execCommand("mceAddControl", false, "yourTextareaId");
});
Once the dialog is closed, you can remove tinyMCE control from the textarea using this:
tinyMCE.execCommand("mceRemoveControl", false, "yourTextareaId");

jQuery UI Dialog instead of alert() for Rails 3 data-confirm attribute

In Rails 3, passing a :confirm parameter to link_to will populate the data-confirm attribute of the link. This will induce a JS alert() when the link is clicked.
I am using the rails jQuery UJS adapter (https://github.com/rails/jquery-ujs). The relevant code from rails.js is:
$('body').delegate('a[data-confirm], button[data-confirm], input[data-confirm]', 'click.rails', function () {
var el = $(this);
if (el.triggerAndReturn('confirm')) {
if (!confirm(el.attr('data-confirm'))) {
return false;
}
}
});
and
triggerAndReturn: function (name, data) {
var event = new $.Event(name);
this.trigger(event, data);
return event.result !== false;
}
I would like to know how this could be modified to instead yield a jQuery dialog (e.g. the jQuery UI Dialog) allowing the user to confirm or cancel.
My knowledge of JavaScript isn't sufficient to achieve this elegantly. My current approach would be to simply rewrite the $('body').delegate() function to instead instantiate a lightbox. However I imagine that there is a more effective approach than this.
As others have mentioned, you cannot use a jQuery dialog box, as $.rails.confirm needs to block until it returns the users answer.
However, you can overwrite $.rails.allowAction in your application.js file like this:
$.rails.allowAction = function(element) {
var message = element.data('confirm'),
answer = false, callback;
if (!message) { return true; }
if ($.rails.fire(element, 'confirm')) {
myCustomConfirmBox(message, function() {
callback = $.rails.fire(element,
'confirm:complete', [answer]);
if(callback) {
var oldAllowAction = $.rails.allowAction;
$.rails.allowAction = function() { return true; };
element.trigger('click');
$.rails.allowAction = oldAllowAction;
}
});
}
return false;
}
function myCustomConfirmBox(message, callback) {
// implement your own confirm box here
// call callback() if the user says yes
}
It works by returning false immediately, thus effectively canceling the click event. However, your custom function can then call the callback to actually follow the link/submit the form.
I just added an external API to the Rails jquery-ujs for exactly this kind of customization. You can now make rails.js use a custom confirm dialog by plugging into (and re-writing 1 line of) the $.rails.allowAction function.
See my article, Rails jQuery UJS: Now Interactive, for a full explanation with examples.
EDIT: As of this commit, I moved the confirm dialog function to the $.rails object, so that it can be modified or swapped out even more easily now. E.g.
$.rails.confirm = function(message) { return myConfirmDialog(message); };
I liked the answer from #Marc Schütz about overriding $.rails.allowAction the most of anything I found online - but I'm not a big fan of overriding the functionality in allowAction since it's used all throughout the jquery-ujs codebase (what if there are side effects? Or if the source for that method changes in a future update?).
By far, the best approach would be to make $.rails.confirm return a promise... But it doesn't look like that's going to happen anytime soon :(
So... I rolled my own method which I think is worth mentioning because it's lighter weight than the method outlined above. It doesn't hijack allowAction. Here it is:
# Nuke the default confirmation dialog. Always return true
# since we don't want it blocking our custom modal.
$.rails.confirm = (message) -> true
# Hook into any data-confirm elements and pop a custom modal
$(document).on 'confirm', '[data-confirm]', ->
if !$(this).data('confirmed')
myCustomModal 'Are you sure?', $(this).data('confirm'), =>
$(this).data('confirmed', true)
$(this).trigger('click.rails')
false
else
true
# myCustomModal is a function that takes (title, message, confirmCallback)
How does it work? Well, if you look at the source, you'll notice that the allowAction method halts if the confirm event returns a falsy value. So the flow is:
User clicks link or button with data-confirm attribute. There is no data-confirmed present on the link or button, so we fall into the first if block, trigger our custom modal and return false, thereby stopping the action from continuing in the ujs click handler.
User confirms in the custom modal, and the callback is triggered. We store state on the element via data('confirmed', true) and re-trigger the same event that was triggered previously (click.rails).
This time the confirm event will fall into the else block (since data('confirmed') is truthy) and return true, causing the allowAction block to evaluate to true.
I'm sure I'm even missing other ways that might make this even simpler, but I think this is a really flexible approach to get a custom confirm modal without breaking core jquery-ujs functionality.
(Also, because we're using .on() this will bind to any data-confirm elements on the page at load time or in the future, similarly to how .delegate() works, in case you are wondering.)
I don't understand why you need to use the jQuery dialog when the JavaScript confirm() function will still work just fine. I would do something like this:
$('a[data-confirm]').click(funciton() {
confirm($(this).data("confirm"));
});
If you want to use a dialog instead, it's a little different. You can one-off each dialog you want, or you can probably take a uniform approach application wide so that your rails.js or your application.js can handle any dialog instance. For example, you'd need something like this on your page:
<a class="dialogLauncher">The link that creates your dialog</a>
<div class="dialog" title="My confirmation title" style="display:none">
<p>My confirmation message</p>
</div>
Then, in your js:
$('.dialogLauncher').click(function() {
var dialog = $(this).next('.dialog');
dialog.dialog();
})
If you want to customize your dialog a little more, check out this example.
Edit
Now that I think of it, this would be a good opportunity for a custom form builder. You could override one of your Rails link tags to output html similar to what's listed above whenever a certain attribute is present, i.e. :dialog => true. Surely that would be the Railsy way to do it. You could add other options into your tag as well, like the dialog title, etc.
Edit
Better yet, instead of :dialog => true, use :confirm => "my confirm message" just as you would normally, but in your override of link_to, you will use the :confirm option to create the dialog html that jQuery needs, delete that option, and then call super.
This is how I got it to work. Please suggest any corrections / improvements
#
in rails.js
#
// Added new variable
var deleteConfirmed = false;
// Changed function to use jquery dialog instead of confirm
$('body').delegate('a[data-confirm], button[data-confirm], input[data-confirm]', 'click.rails', function () {
var el = $(this);
/*
if (el.triggerAndReturn('confirm')) {
if (!confirm(el.attr('data-confirm'))) {
return false;
}
}
*/
if (el.triggerAndReturn('confirm')) {
if(deleteConfirmed) {
deleteConfirmed = false;
return true;
}
$( "#dialog-confirm" ).dialog("option", "buttons",
{
"Delete": function() {
$( this ).dialog( "close" );
deleteConfirmed = true;
el.trigger('click');
return true;
},
Cancel: function() {
$( this ).dialog( "close" );
return false;
}
}
);
$( "#dialog-confirm" ).dialog("open");
return false;
}
});
#
in application.js
#
//Ensure confirm Dialog is pre-created
jQuery(function () {
$( "#dialog-confirm" ).dialog({
autoOpen: false,
resizable: false,
height:140,
modal: true
});
});
#
in layout.html
Alt you can place this div anywhere in your generated html
#
<div id='dialog-confirm' title='Confirm Delete'>
<p>
<span class='ui-icon-alert' style='float:left; margin:0 7px 20px 0;'>
This item will be permanently deleted. Are you sure?
</span>
</p>
</div>
This is how I solved this problem.
I tried a lot of different ways, but only this one works.
In rails.js
function myCustomConfirmBox(element, callback) {
const modalConfirmDestroy = document.getElementById('modal-confirm');
// wire up cancel
$("#modal-confirm #cancel-delete").click(function (e) {
e.preventDefault();
modalConfirmDestroy.classList.remove('modal--open');
});
// wire up OK button.
$("#modal-confirm #confirm-delete").click(function (e) {
e.preventDefault();
modalConfirmDestroy.classList.remove('modal--open');
callback(element, true);
});
// show the dialog.
modalConfirmDestroy.classList.add('modal--open');
}
In this place I used code of #Mark G. with some changes. Because this $(this).trigger('click.rails') snipped of the code didn't work for me.
$.rails.confirm = function(message) {return true};
$(document).on('confirm', '[data-confirm]', (event)=> {
if (!$(this).data('confirmed'))
{
myCustomConfirmBox($(this), (element, choice)=> {
element.data('confirmed', choice);
let clickedElement = document.getElementById(event.target.id);
clickedElement.click();
});
return false;
}
else
{
return true;
}
});
Then in the html.erb file I have this code for link:
<%= link_to "documents/#{document.id}", method: "delete", data: {confirm: "sure?"}, id: "document_#{document.id}" %>
and this code for modal:
<div id="modal-confirm" class="modal modal-confirm">
<h2 class="modal__ttl">Title</h2>
<div class="modal__inner">
<p>Description</p>
<div class="modal__btns">
<button type="button" name="cancel" id="cancel-delete" class="btn btn-primary">Cancel</button>
<button type="button" name="confirm" id="confirm-delete" class="btn delete_button btn-secondary">Delete</button>
</div>
</div>
</div>
I hope, it will help someone.

Categories