trigger an jQuery UI Dialog if user not authorized - javascript

On my website I have two ways to login. The first is used then an user is pushing the Logon button, which trigger an jQuery UI Dialog to open. The second is an normal view, which is used, if an user isn't Authorized, which redirect to an normal login view. But what i liked to do instead, is if an user is not Authorized, it opens the Login jquery ui dialog instead of redirection to the view the user is intended.
This is how i currently are opening the dialog,
$(".openLoginDialog").on("click", function (e) {
e.preventDefault();
$("<div></div>")
.addClass("dialog")
.attr("id", $(this).attr("data-dialog-id"))
.appendTo("body")
.dialog({
title: $(this).attr("data-dialog-title"),
create: function (event, ui) {},
close: function () { $(this).remove() },
open: function (event, ui) {},
modal: true,
position: ['center', 130],
minWidth: 510,
resizable: true,
zIndex: 20000
})
.load(this.href);
});
Because the content in the dialog is an partialView it's called like this:
<div class="items iconlogin highligth-br"><a class="openLoginDialog" data-dialog-id="LoginDialog" data-dialog-title="Login" href="#Url.Action("LogOn", "Authentication", new { returnUrl = Request.Url.ToString() })">Login</a></div>
Also to help me controlling the not Authorized, i have overriden this calls.
public override void OnAuthorization(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new { controller = "Authentication", action = "AccessDenied" }));
}
Last resort would be to redirect to an access denied page, with just an white background, which opens on load, a dialog.

I have a MVC intranet solution that employs functionality similar to what you describing, however it is using windows auth not forms.
Basically I have something like this in the Index...
var userExists = "#ViewBag.User";
// require the user to register if they are not found
if (userExists == "") {
$.get('Home/Register/', function (data) {
$("#Register").html(data);
$("#Register").dialog({
resizable: false,
closeOnEscape: false,
dialogClass: 'no-close',
typeDelay: 250
});
});
}
And then in the controller I just set 'ViewBag.User' to the username if they exist.

Have a look at this example:
http://jqueryui.com/dialog/#modal-form
Notice the autoOpen: false

I'm not familiar with asp.net so I wont be able to help with actual implementation. One approach would be to check where the request came from and if the user is not authorized redirect them back to that page and hit them with a dialog.
Another approach would be to know if the user is authenticated on the page load and override links that require authentication
$(".authRequired").on("click", function (e) {
e.preventDefault();
//fancy logic here to load form and dialog
});

Related

How can I use document.referrer with two different modals?

I have two different modals on my website, one with specific domains to target, the other to target all pages with domain website.com. Both modals are targeting the document.referrer and each modal has a different id (#closureModal and #parkModal).
My issue is that the #parkModal is firing on all pages (rather than specific pages: website.com/parks/park1, website.com/acitivies/park1, etc) since it starts with the domain website.com.
How can I allow two different modals target the document.referrer without one appearing where it's not meant to? How can I use document.referrer with two different modals?
here is #closureModal's code:
const tsp = ["website.com"];
const closureReferrer = document.referrer;
const referrer_hostname = closureReferrer !== "" ? new URL(closureReferrer).hostname : "";
if (tsp.includes(referrer_hostname)) {
console.log("Don't Show Modal", closureReferrer);
} else {
console.log("Show Modal", closureReferrer);
$( window ).on('load', function() {
console.log("closure modal firing");
$('#closureModal .closure').modal({
backdrop: 'static',
keyboard: false,
show: true
});
});
}
the #parkModal is similar code:
const domains = ["https://website.com/parks/park1", "https://website.com/parks/events/park1", "https://website.com/parks/events/park1", "https://website.com/parks/promotions/park1", "https://website.com/parks/go-green/park1", "https://website.com/parks/info/park1", "https://website.com/parks/activities/park1", "https://website.com/parks/events/park1/#/?park=park1"];
const parkReferrer = document.referrer;
if (domains.includes(parkReferrer)) {
console.log("Don't Show Modal - from Cummins page", parkReferrer);
} else {
console.log("Show Modal - From other Page", parkReferrer);
$( window ).on('load', function() {
console.log("park modal firing");
$('#parkModal').modal({
backdrop: 'static',
keyboard: false,
show: true
});
});
}
I don't immediately see the issue but I do have some advice on what may help you move closer to both better code and something that is easier to diagnose.
I see a lot of code duplication. Is it necessary to have two different window onload events that both look at the referrer and then decide which modal to display? My recommendation is do it all in one onload handler that looks at document.referrer only once, then determines what modal to display (if any).
Something kinda like:
$( window ).on('load', function() {
console.log("park modal firing");
// define your parkReferrers and closureReferrers here
const referrer = document.referrer;
const displayParkReferrerModal = parkReferrers.includes(referrer);
const displayClosureModal = closureReferrers.includes(referrer);
let modalToDisplay;
if (displayParkReferrerModal) {
modalToDisplay = '#parkModal';
} else if (displayClosureModal) {
modalToDisplay = '#closureModal .closure';
}
if (modalToDisplay) {
console.log(modalToDisplay);
$(modalToDisplay).modal({
backdrop: 'static',
keyboard: false,
show: true
});
return;
}
console.log('no matching modal to display');
return;
});
Hope this is helpful. You could also abstract this to a handleReferrerModal function that you then invoke in the load event handler. That might be cleaner if you have multiple different things happening on load.

jQuery Validate not working with Ajax and jQuery dialog

On my website I have a navigation and a main content area. When you click on a navigation link, the content inside the main content area always gets loaded via ajax. If you click the link "Contact", a text gets loaded which contains a link for a jQuery dialog which contains the contact form.
The problem: When you load the website and navigate to the contact form area, the validation works perfectly fine. However, if you navgiate away to another content area (= another content gets loaded via ajax) and then go back to the contact form area and click the submit button (WITHOUT reloading the page in between), validation fails, gets ignored and the form action gets executed. If you reload the page and then navigate to the contact form area, everything works again.
I cannot make sense of this behaviour. What is weird: Validating another form in the content area which is NOT opened in a jQuery dialog always works, no matter what you had clicked before. So it must be because of the jQuery dialog popup and Ajax. Who can make sense of this problem?
Here comes my code:
HTML:
open form test popup
<div id="popup-form-test">
<form id="form-test" action="somelink">
<input type="text" placeholder="testtext eingeben" name="testText"></input>
<input type="submit" value="submit">
</form>
</div>
JS:
var dialogTest = $("#popup-form-test").dialog({
autoOpen: false,
modal: true,
close: function () {
console.log('closed');
}
});
$("#open-popup-form-test").on("click", function () {
dialogTest.dialog("open");
});
$('#form-test').validate({
debug: true,
rules : {
testText: {
required: true
}
},
submitHandler: function(form) {
alert('submitted');
}
});
you must use the open callback of .dialog() and insert there the validator:
var dialogTest = $("#popup-form-test").dialog({
autoOpen: false,
modal: true,
open : function (event, ui) {
$('#form-test').validate({
debug: true,
rules : {
testText: {
required: true
}
},
submitHandler: function(form) {
alert('submitted');
}
});
},
close: function () {
console.log('closed');
}
});
i can't test without a valid example but it should work.

$.when(ajaxCall) Versus success

I have the following code inside my asp.net MVC view:-
$('body').on("click", "#transferserver,#transfersd,#transferfirewall,#transferrouter,#transferswitch", function () {
$("#showoptions").dialog({
title: "Assign Selected Records To New Rack",
width: 'auto', // overcomes width:'auto' and maxWidth bug
maxWidth: 600,
height: 'auto',
modal: true,
fluid: true, //new option
resizable: false
});
var ajaxCall = $.ajax({
url: '#Url.Content("~/Rack/ShowTransferSelectedDialog")',
data: {
rackfrom: "#Model.Rack.ITsysRackID",
assettype: $(this).attr('id')//get the id for the clciked link, so that the submit button will call the associted action method.
},
type: 'get',
success: function (html) {
$('#showoptions').html(html);
$("#showoptions").dialog("show"); //This could also be dialog("open") depending on the version of jquery ui.
}
});
$.when(ajaxCall)
.then(function (data) { showDialog(data); });
});
I have the following questions:
What are the differences between the $when(ajaxcall) and on success ?
In my above code if I remove the $.when(ajaxCall) the dialog box will still be displayed . so is there any need to have it?
Thanks
EDIT
But one benefit i find for using $.when(ajaxCall) is that i have defined a custom authorization attribute as follow:-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CheckUserPermissionsAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
var viewResult = new JsonResult();
viewResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
viewResult.Data = (new { IsSuccess = "Unauthorized", description = "Sorry, you do not have the required permission to perform this action." });
filterContext.Result = viewResult;
}
}
}
currently if the user clicks on the link to display the dialog box and he is not authorize to do so , he will receive a jAlert containing the unauthorized message as follow:-
![enter image description here][1]
but if i remove the $.when(ajaxCall), then the user will not receive the unauthorization message , and instead the dialog will be blank .. so can anyone advice ?
1) This is the definition of jQuery when
Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events.
It make no sense to use it for a single ajax call, you want to use it for 2 or more so you wait for them to finish before executing some code.
2) I don't know what showDialog does but your dialog already shows because in your success handler you have $("#showoptions").dialog("show");. Again, no need at all to use when here

Javascript redirect only seems to work when chrome debugger is open

I have written a Jquery-Ui Dialog to popup as a confirmation on particular links. This however does not redirect to my Delete page correctly. However if I open the debugger in chrome to debug, then the code works as expected.
I have found the same question, however the solution does not seem to work for me. It is exactly the same scenario though. Question here JavaScript redirect not working and works only in Chrome if debugger is turned on
So I have my link
<div id="confirm-dialog">
<div class="dialog-inner">
<p id="confirm-dialog-message"></p>
</div>
</div>
Delete
And I have my javascript
$('.confirmLink').click(function (e) {
BodyScrolling(false);
var theHref = $(this).attr("href");
var theTitle = $(this).attr("title") == null ? "Confirm..." : $(this).attr("title");
var theText = $(this).attr("data-confirm-message") == null ? "Are you sure?" : $(this).attr("data-confirm-message");
$("#confirm-dialog-message").html(theText);
$("#confirm-dialog").parent().css({ position: "fixed" }).end().dialog("open");
$("#confirm-dialog").dialog({
title: theTitle,
close: function() {
BodyScrolling(true);
},
buttons: [
{
text: "Yes",
class: "mws-button red",
click: function () {
$("#confirm-dialog").dialog("close");
window.location.href = theHref;
return false;
}
},
{
text: "No",
class: "mws-button black",
click: function () {
$("#confirm-dialog").dialog("close");
}
}]
});
return false;
});
So when I click my Delete link, I am indeed presented with my confirm dialog with Yes and No buttons, css styled correctly, and has captured the link href and bound it to the Yes button. If I click "No", I am kicked back and nothing further happens - Correct!
If I click Yes, it should take send me on to the original href that it captured. I have thrown alert(theHref) on the Yes Button click just before the redirect and it does show me the correct address (/Customer/Delete/73865878346587), but the redirect does not happen.
When I open the chrome debugger to debug the javascript or see if any errors occurred, then everything works as expected and redirects me correctly!
In IE, it does not work either.
I have tried...
window.location.href = theHref
window.location = theHref
location.href = theHref
$(location).attr('href', theHref)
I have also tried adding return false; after my redirect. Nothing works.
The link I added above to the same question said to make sure that the Yes button is being rendered on the page as a ... which mine is.
Can anyone shed any light?
Instead of window.location.href = theHref;
have you tried window.location.replace(theHref);?
Back to basics, try: window.location = theHref;
Well I have found the answer. Javascript was a red herring!
I did try to remove the confirmLink jQuery class so that the link was just a standard link that went straight to my controller to perofm my delete. When I did this test, the link worked perfectly. Therefore I denoted the problem be with my javascript. However, it seems that this was not quite the case and had only worked again if the Debugger in Chrome had been or was open at the time aswell.
When I revisited the non confirm link option again, I found this not to work properly, therefore denoting the problem not with the javascript.
It appears that you cannot perform a Delete action from a HTML Link in MVC. This is obviously because of security risks involved as anyone could perform a Delete on an Id. I had thought of this in my implementation and had added code to check where the Request had come from and if it wasn't from my List page, then it threw back an error and wouldn't perform the Delete. It didn't matter what I named my controller either, eg Test, the link performing my HTTP GET request would never hit this. There must be some algorithm that determines what the action is doing and stops you from performing the action on a HttpGet request. For more information about Delete Actions, check out this post http://stephenwalther.com/archive/2009/01/21/asp-net-mvc-tip-46-ndash-donrsquot-use-delete-links-because
It seems that you can only perform this by a HTTP Post, which means either using a Ajax.ActionLink or by using a Form and a submit button. Then your Action must be specified for HttpPost.
If, like me, you wish to keep your Link as a HTML Link, then you can do the following which is what I did, code below. I kept my HTML Link, set it up to point to my HttpPost Delete Action. Added my confirmLink class for jquery to bind my dialog box to. I pick up the link href and set the Yes button in the jquery dialog to dynamically create a Form and set the method to post and the action to the links href. Then I can call submit on the new dynamically created form to perform my Post to my Delete action.
My Delete Link
Html.ActionLink("Delete", "Delete", "Caterer", new { id = caterer.Id }, new { #class = "mws-ic-16 ic-delete imageButton confirmLink", #data_confirm_title = "Delete " + caterer.Name, #data_confirm_message = "Are you sure you want to delete this caterer, " + caterer.Name + "?" })
My Javascript
function LoadConfirm() {
$('.confirmLink').click(function (e) {
e.preventDefault();
BodyScrolling(false);
var actionHref = $(this).attr("href");
var confirmTitle = $(this).attr("data-confirm-title");
confirmTitle = confirmTitle == null ? "Confirm..." : confirmTitle;
var confirmMessage = $(this).attr("data-confirm-message");
confirmMessage = confirmMessage == null ? "Are you sure?" : confirmMessage;
$("#confirm-dialog").dialog({
autoOpen: false,
modal: true,
width: 400,
closeOnEscape: true,
close: function () { BodyScrolling(true); },
title: confirmTitle,
resizable: false,
buttons: [
{
text: "Yes",
class: "mws-button red",
click: function () {
StartLoading();
$(this).dialog("close");
var form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", actionHref);
form.submit();
}
},
{
text: "No",
class: "mws-button black",
click: function () {
$("#confirm-dialog").dialog("close");
return false;
}
}
]
});
$("#confirm-dialog #confirm-dialog-message").html(confirmMessage);
$("#confirm-dialog").parent().css({ position: "fixed" });
$("#confirm-dialog").dialog("open");
});
}
My Action
[HttpPost]
[Authorize(Roles = "User")]
public ActionResult Delete(long id)
{
//Perform my delete
return RedirectToActionPermanent("List");
}

Custom confirm dialog with JavaScript

I would like to create a JavaScript function similar to confirm() that shows a dialog (a div with a question and 2 buttons) and returns true if the user clicks "Ok" or false otherwise.
Is it possible to do that using JavaScript/jQuery but without plugins (e.g. jQuery UI or Dialog)? Because I'm trying to reduce size and round trip times...
I tried to write this code, but I don't know how to make the function "wait" for the user click.
I would like to use my function in this way:
answer=myConfirm("Are you sure?")
In this way I could use the same function in several contexts, simply changing the question passed as a parameter. This is the same behavior of confirm()
Rather than waiting for the user's input and then returning from the function, it is more common in JavaScript to provide a callback function that will be called when the action you're waiting for is complete. For example:
myCustomConfirm("Are you sure?", function (confirmed) {
if (confirmed) {
// Whatever you need to do if they clicked confirm
} else {
// Whatever you need to do if they clicked cancel
}
});
This could be implemented along the lines of:
function myCustomConfirm(message, callback) {
var confirmButton, cancelButton;
// Create user interface, display message, etc.
confirmButton.onclick = function() { callback(true); };
cancelButton.onclick = function() { callback(false); };
}
If using jQuery, why not implement jQueryUI? And use the Dialog function as follows:
as a 2 part:
HTML
<div id="dialog-confirm" title="ALERT">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>Are you sure?</p>
</div>
Script
$( "#dialog-confirm" ).dialog({
resizable: false,
modal: true,
buttons: {
"OK": function() {
$( this ).dialog( "close" );
},
Cancel: function() {
$( this ).dialog( "close" );
}
}
});
All in Script:
$(function() {
$("<div />").attr("id", "dialog-confirm").append(
$("<p />").text('Are you sure?').css("text-align", "center").prepend(
$("<span />").addClass("ui-icon ui-icon-alert").css({
float: 'left',
margin: '0 7px 20px 0'
})
)
).dialog({
resizable: false,
modal: true,
title: "ALERT",
buttons: {
"OK": function() {
answer=1;
$(this).dialog("close");
},
"Cancel": function() {
answer=0;
$(this).dialog("close");
}
}
});
});
jsFiddle
This really should be done with a callback. The closest thing to what you're after would be to use a publish and subscribe model with some custom events.
To do so:
When a user clicks the yes button, trigger a custom event called clickedYes. Do the same for "no"
$('#yesbtn').click(function(){
$(document).trigger('clickedYes');
});
$('#nobtn').click(function(){
$(document).trigger('clickedNo');
});
Now we need to "listen" or subscribe for those events and execute the appropriate action in context.
Lets create a hypothetical situation: Your user clicks delete and you want to confirm that choice.
First setup what you want to happen if they click yes:
$(document).unbind('clickedYes'); //Unbind any old actions
$(document).bind('clickedYes',function(){
//Code to delete the item
//Hide the popup
});
then what you want to happen if they click no:
$(document).unbind('clickedNo'); //Unbind any old actions
$(document).bind('clickedNo',function(){
//Hide the popup and don't delete
});
So we've setup actions that are listening for clickedYes or clickedNo. Now we just need to show the user the popup so that they have to click yes or no. When they do, they'll trigger the events above.
so your myConfirm() function will just do the following:
function myConfirm(msg){
//change the message to 'msg'
//Show the popup
}
So the order would be:
Bind triggers for the custom events to the yes and no buttons
Before prompting - unbind any old actions and attach your new ones
Present the user with a popup that'll cause them to trigger on of your actions.
This will allow you to call the function like this myConfirm('Are you sure'); It's not quite what you're after...but I don't think it's possible to do exactly what you want.

Categories