Handle errors when loading content into a Kendo UI KendoWindow - javascript

I have a KendoWindow that loads content into an iFrame from a JSP.
I've attached error-handlers at every position yet when the JSP isn't available, none of these error handlers are called.
What is the proper way to handle errors when loading content into a KendoWindow?
win.kendoWindow({
width : "860px",
modal : true,
height : "680px",
iframe : true,
resizable : false,
content : {
url: "access/lookup/Source.jsp",
failure: function(err) {
console.log(e.status);
console.log(e.xhr);
},
error: function(err) {
console.log(e.status);
console.log(e.xhr);
}
},
error: function(err) {
console.log(e.status);
console.log(e.xhr);
}
});

If you dig into the source code, you see:
if (!showIframe) {
// perform AJAX request
that._ajaxRequest(options);
} else {
iframe = element.find("." + KCONTENTFRAME)[0];
// Edited for clarity
iframe.src = url || iframe.src;
}
showIframe, if not set in options, is defined as:
showIframe = !isLocalUrl(url);
So only the code execution branch that does the ajax request uses your error handlers. The else branch just does an iframe and lets the browser handle it.
Adding iframe: false to the content options, as shown here, should help.

Related

Issue with ajax success function

Inside an iframe I have the following script:
$("a").on("click", function (e) {
e.preventDefault();
if (e.target.href) {
let link = e.target.href;
$.ajax({
url: "/newOrigin",
data: {
"link": link
},
type: "POST",
success: function (response) {
parent.document.getElementById("oframe").srcdoc = response.site;
parent.document.getElementById("oLink").href = link;
},
error: function (error) {
console.log(error);
}
});
}
});
Which does not work. The prevent default doesnt do it's job, meaning the event itself isnt being triggered. I believe the issue is with the second line in the ajax success function, since the code below works perfectly fine (srcdoc changes and console is logged).
$("a").on("click", function (e) {
e.preventDefault();
if (e.target.href) {
let link = e.target.href;
$.ajax({
url: "/newOrigin",
data: {
"link": link
},
type: "POST",
success: function (response) {
parent.document.getElementById("oframe").srcdoc = response.site;
console.log("Hello");
},
error: function (error) {
console.log(error);
}
});
}
});
oLink is the id of an a tag element (hyperlink) and oframe is the id of another iframe inside the parent of the iframe where this code is.
Does anyone know why this is happening?
EDIT: The site has two iframes and each have a title above them(with each title having an href of the page displayed in each iframe). When a link is clicked in the first iframe, an ajax request is sent with the link and the response has the html of that page which is sent to be displayed in the 2nd iframe (1st line in success function). I now want to change the href of the words above the 2nd iframe to be the link of the link clicked in the 1st iframe. So the two titles and two iframes are inside the same parent component (same level) and the script is inside the first iframe.
The html used is base.html + index.html from here (iframes and titles in index.html): https://github.com/MohamedMoustafaNUIG/AnnotatorVM/tree/master/app/templates
EDIT2: Apparently, the success function is isolated from the rest of the code, meaning it doesnt have access to the "link" variable. I solved this by returning the link in the response and accessing it from there. But the event is still not triggering :(

Allow infinitescroll.js to run X times, then load more posts

I'm using the infinitescroll.js script and it works really well. I've found out how to replace the default functionality with a load more button, using this code:
$(window).unbind('.infscr');
$('.js-next-reports').click(function() {
$grid.infinitescroll('retrieve');
return false;
});
$(document).ajaxError(function(e, xhr, opt) {
if (xhr.status == 404) $('.js-next-reports').remove();
});
However, what I'd like to do is allow infinite scroll to run 3/4 times and then show the .js-next-reports button. I'm not sure how to keep track of how many times infinite scroll has run though. I know there is a currPage var but using console.log I can't work out how I can reference it.
There is also a maxPage option for infinitescroll, which limits it to run only X times, so I could maybe tap into that somehow? I'm not sure how to get a console.log of the options though. Here is my init code if that helps ($grid is just a ref to a div)
$grid.infinitescroll({
// selector for the paged navigation (it will be hidden)
navSelector : ".pagination",
// selector for the NEXT link (to page 2)
nextSelector : ".pagination .next",
// selector for all items you'll retrieve
itemSelector : ".infinite-scroll-post",
contentSelector : "#infinite-scrollable",
debug: true,
// finished message
loading: {
img: "ajax-loader.gif",
msgText: "Loading more projects...",
finishedMsg: 'No more pages to load.',
}
},
});
Maybe something like: ?
if ( .currPage == "3" ) {
$(window).unbind('.infscr');
$('.js-next-reports').click(function() {
$grid.infinitescroll('retrieve');
return false;
});
$(document).ajaxError(function(e, xhr, opt) {
if (xhr.status == 404) $('.js-next-reports').remove();
});
}
But I don't know how to either count the scrolls or access currPage.
Thanks
A JSFiddle would help testing the code, but from what I've read on their documentation, there's a callback that allows you to access currPage inside the state object. Your code should look something like this:
$grid.infinitescroll({
// selector for the paged navigation (it will be hidden)
navSelector : ".pagination",
// selector for the NEXT link (to page 2)
nextSelector : ".pagination .next",
// selector for all items you'll retrieve
itemSelector : ".infinite-scroll-post",
contentSelector : "#infinite-scrollable",
debug: true,
// finished message
loading: {
img: "ajax-loader.gif",
msgText: "Loading more projects...",
finishedMsg: 'No more pages to load.',
},
appendCallback: false
}, function(newitems, opts) {
if(opts.state.currPage == 3) {
$(window).unbind('.infscr');
}
}
});

PJAX/DJAX- rerun scripts after pjax load

I'm using RequireJS to structure my JS and DJAX (basically PJAX) as a way to dynamically load content without a full page reload.
The issue I have is that after DJAX has finished loading the content I need to rerun my scripts (e.g. a script that adds multiple images into a carousel) so that the new page renders correctly. I thought the best way to do this would be to simply rerun the function I'm running on $(document).ready(); but I'm getting this output in the console:
Uncaught TypeError: Cannot read property 'djaxLoad' of undefined
which is referring to this line in load-posts.js
bootstrap.init();
I'm guessing I'm writing something incorrectly.
Here is bootstrap.js which is my main file which fires on document.ready and initialises all my modules
require(['base/responsive', 'base/main-menu', 'base/social-share', 'base/randomise-colours', 'base/infinite-scroll', 'base/load-posts', 'base/image-fade', 'base/carousel', 'base/misc'],
function(responsive, main_menu, social_share, randomise_colours, infinite_scroll, load_posts, image_fade, carousel, misc) {
var $ = jQuery;
function djaxLoad() {
//If page has JS (detected with Modernizr) then hide content until the
//doc is ready to avoid flash of unstyled content
$('#djax-container').css('display', 'block');
main_menu.init();
social_share.init();
randomise_colours.init();
load_posts.init();
image_fade.init();
infinite_scroll.init();
carousel.init();
misc.init();
responsive.init();
}
$(document).ready(djaxLoad);
}
);
And this is load-posts.js which handles DJAX for me. DJAX works, I just need to get the scripts to fire again.
define(['djax', 'base/bootstrap'], function(djax, bootstrap) {
var $ = jQuery,
$body = $('body');
return {
init: function() {
if($body.length >= 1) {
this.setUp();
} else {
return false;
}
},
setUp: function() {
this.pjaxLinks();
},
pjaxLinks: function() {
//Initialise DJAX, but stop it from running on pagination links (URL is /page...)
$('body').djax('.updateable', ['page']);
//When clicking a djax link
$(window).bind('djaxClick', $.proxy(function() {
this.addLoader();
},this));
//When the new content has loaded in
$(window).bind('djaxLoad', $.proxy(function() {
this.removeLoader();
},this));
},
addLoader: function() {
$body.addClass('loader-visible');
},
removeLoader: function() {
$body.removeClass('menu-visible');
$('html, body').scrollTop(0);
function removeLoaderDelay() {
$body.removeClass('loader-visible');
bootstrap.djaxLoad();
}
setTimeout(removeLoaderDelay, 1000);
}
};
});
The djaxClick function runs on a link click, and the djaxLoad function runs after the content has been loaded in. I'm adding a loader overlay to the page, then removing it after the content has loaded in.
A bit late but for future reference: In the documentation at https://github.com/beezee/djax you'll find the djaxLoad-event. This is specifically made for your usecase. You can use it as follows:
$(window).bind('djaxLoad', function(e, data) {
// your scripts to run on ajax-calls
});
The site further explains: "the data object passed with the event contains the requested url, the page title for the requested page, and the contents of the requested page as a string".
$(window).bind('djaxLoad', function(e, data) {
var responseObj = $('<div>'+data.response+'</div>');
//do stuff here
});

$.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

JQuery AJAX with dialog call

There are a couple of points I was hoping for assistance on. I have the following code, by which I make a ajax call on page load, and either retrieve data successfully or handle any resulting error.
I am running JQuery 2.0.0, with JQuery UI 1.10.2 (PHPStorm seems to have trouble recognising later versions).
Relevant HTML:
<script type="text/javascript" src="inc/JQuery-2.0.0.js"></script>
<script type="text/javascript" src="inc/JQuery-UI-1.10.2.js"></script>
<script type="text/javascript" src="inc/core.js"></script>
...
<div id="feedback-dialog">
<div id="dialog-inner"><!-- dynamic content --></div>
</div>
</body>
Javascript:
var engine = 'engine.php',
feedbackWrapper = $('#feedback-dialog'),
feedbackInner = $('#dialog-inner');
function ftShowErrorMessage(e)
{
var error = e.toString(),
errorWrapper = $('<p id="error-message"/>');
$(errorWrapper).text(error);
$(feedbackInner).empty();
$(feedbackInner).append(errorWrapper);
$(feedbackWrapper).dialog({
title: 'An Error Occurred',
dialogClass: 'feedback-error',
buttons: [
{
'OK' : function() {
//do stuff
$(this).dialog('close');
}
}
]
});
}
$(document).ready(function()
{
(function(){
var args = {};
args.Request = 'get country ids with county options';
$.ajax({
type: 'POST',
url: engine,
data: args
})
.done(function(data)
{
try
{
var obj = JSON.parse(data);
if(!obj.hasOwnProperty('error'))
{
//continue
}
else
{
ftShowErrorMessage(obj.error);
}
}
catch(e)
{
ftShowErrorMessage(e)
}
})
.error(function( xhr, ajaxOptions, thrownError )
{
ftShowErrorMessage(thrownError)
});
})();
});
My aim here is to catch when the AJAX call cannot make a successful call, or returns a non-parse-able string, or returns an error flag within a successful call (signalling an error from the PHP script).
My first problem is that the dialog call just won't fire - no error or warning given. This is the case even when I tie it to a simple click event. If anyone can point out where this is failing, I'd be grateful (the wrapping function is being called, and I can pass and echo content to and from it - it just fails at the dialog call).
Secondly, can someone clarify for me the difference between the ajax success, done, and complete functions, and between error and fail (fail does not seem to be recognised by the IDE, although it appears in the docs, but that's probably a separate problem).
I'm not sure why your dialog isn't displaying, maybe this will work:
$(feedbackWrapper).dialog({
title: 'An Error Occurred',
dialogClass: 'feedback-error',
buttons: [
{
'OK' : function() {
//do stuff
$(this).dialog('close');
}
}
]
}).dialog("open");
I'm not sure why this would be needed, since autoOpen: true is the default. But if you've already closed the dialog from a previous error, I think you need to open it explicitly the next time.

Categories