Ajax callback refresh div - javascript

I implemented a Ajax callback function to update a div (announcement) in my web page.
It works fine, but the current issue is that the Ajax call function update the announcement div, however, after rewrite the content, the Javascript functions in this content are not load it. Therefore, my toggle function in table does not work after update content.
My ajax call function
setInterval("_checkUpdate()", 2000); //2 seconds one call.
function _checkUpdate() {
var callback=new Object();
callback.success=this.checkUpdateonExternalSuccess;
callback.failure=this.checkUpdateonExternalFailure;
YAHOO.util.Connect.asyncRequest('GET' , '/ci/ajaxCustom/ajaxCheckUpdate',callback);
};
On success, it update the content to rewrite to my Div
function checkUpdateonExternalSuccess (o){
if(o.responseText!==undefined) {
var str=o.responseText;
if(str !== 'nocontent') {
document.getElementById('updateContent').innerHTML=str; (Write the new content to my div)
location.reload(); //Reload the whole page, i do not want that
}
}
};
It works, it write the new content with Javascript, but the Javascript functions are not load it.
Javascript:
$(document).ready(function() {
//First hide all the contects except the headcontent
$(".content").hide();
$(".headContent").show();
//If user click on the head title, it hide/show content
$(".headTitle").click(function () {
collapseHeadContent();//reset all
var aParentTD= $(this).closest("td");
var aHeadContent = aParentTD.find (".headContent");
aHeadContent.toggle();
});
// If uses click on the title, it has toggle event for the content
$(".title").click(function () {
collapseContent(); //First reset all
var aParentTD = $(this).closest("td");
var aContent = aParentTD.find(".content"); // Content in the same TD with Title
aContent.toggle();
});
});
function collapseContent() {
//find the Head content to hide and reset of content
$(".headContent").hide();
$(".content").hide();
}
function collapseHeadContent() {
$(".content").hide();
}
HTML:
<div id="annoucementTableDiv">
<table id="annoucementTable">
<tbody id="tdContent">
<tr>
<td><span id="tdtitle"><a class="headTitle"> Forbidden: Error 403</a></span> <br />
<span class="annfrom">PLC team - 19/08/2010 at 10:30<br /> </span>
<br />
<span class="headContent"><P>Due to scheduled maintenance, HOME showed the error 403:<br/>
This is now resolved and customers can update again as normal </P>
</span>
</td>
</tr>
</tbody>
<tbody id="tdContent">
<tr>
<td>
<span id="tdtitle">
<a class="title">Downloading maps</a>
</span> <img src="/euf/assets/themes/standard/images/layout/important.png" class="alert_icon" alt="alert"></img><br />
<span class="annfrom">Sent by 2nd line - 05/11/2009 at 15:30<br /> </span>
<span class="content">Since this morning it has been reported that multiple customers are again receiving this error message.<br /><br />This error has been escalated to the relevant teams with the highest priority and is currently being looked into.
An estimated time for a fix is not yet available but we will keep you updated.
</span>
<br />
</td>
</tr>
</tbody>
</table>
</div>
If I do location.reload, the Javascript functions work. But I do not want to refresh the page.
Any ideas?

Since you're also hiding/showing things, I recommend you change you're ready handler into a named function then call it on document.ready, like this:
function loadFunc() {
$(".content").hide();
$(".headContent").show();
}
$(function() {
loadFunc():
$(".headTitle").live('click', function () {
collapseHeadContent();
$(this).closest("td").find(".headContent").toggle();
});
$(".title").live('click', function () {
collapseContent();
$(this).closest("td").find(".content").toggle();
});
});
This also uses .live() to set your click functions up once. Then when you do your AJAX load, you can just call loadFunc again to do hiding/showing or any other work, like this:
function checkUpdateonExternalSuccess (o){
if(o.responseText!==undefined) {
var str=o.responseText;
if(str !== 'nocontent') {
document.getElementById('updateContent').innerHTML=str;
loadFunc();
}
}
};

Sounds like you need the live function. It is quite straight forward.
$('.title').live('click', function() {
collapseContent(); //First reset all
var aParentTD = $(this).closest("td");
var aContent = aParentTD.find(".content"); // Content in the same TD with Title
aContent.toggle();
});
Basically adds the click handler to all title elements. Even if another loads the event is still associated with it. You can use this for all elements that are loaded by AJAX during the life of the page. So you do the same for the head element and so on.

In a project I'm writing at the moment, I insert HTML and Javascript content separately. The HTML is inserted as usual into innerHTML. And I got the javascript in a JS file which I load into my document during runtime like this:
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = 'myJavascriptFile.js';
headID.appendChild(newScript);

Wrap your table related code into a function and call it once on document.ready and after you ajax-request. Avoid triggering document.ready as suggested by Uoli, because it can cause unpredictable side effects as all your $(document).ready(function() { blocks will be executed again.

Related

Set iFrame source and reload with jQuery

I have a unique issue that--while I've seen similar questions and answers--none quite address my challenge.
Currently, I provide a "print" button that loads the print dialog on a browser based on an embedded and hidden iframe. This works just fine, but I don't want to slow down page loading by pulling in the iframe for a large PDF.
So, I want to load an iframe without the source, then write the proper source url if the user clicks the print icon, then reload the iframe, and finally, show the dialog box.
Unfortunately, the print dialog pops up before I can reload the iframe so loads a blank page in the dialog box. On subsequent clicks, the PDF is loaded and ready for print.
<a href='#' id='load_pdf' ><i class='fa fa-2 fa-print'></i></a>
<iframe id="iFramePdf" src="" style="display:none;"></iframe>
<script type="text/javascript">
jQuery(document).ready(function() {
$("#load_pdf").click(loadPDF);
function loadPDF() {
$('#iFramePdf').attr('src', "my.pdf");
// Attempt to reload iframe
$('#iFramePdf').load("my.pdf");
sendPrint('iFramePdf')
}
function sendPrint(elementId) {
var iframe = $(element_id)[0];
iframe.contentWindow.focus();
iframe.contentWindow.print();
}
});
</script>
I've tried the following various methods to reload:
// Attempt 1
$('#iFramePdf').attr('src', function () { return
$(this).contents().get(0).location.href });
// Attempt 2
$('#iFramePdf').attr("src", $('#iFramePdf').attr("src"));
$('#iFramePdf').attr('src', function () { return $(this).contents().get(0).location.href });
// Attempt 3
$('#iFramePdf')[0].contentWindow.location.reload(true);
// Attempt 4
var getMyFrame = document.getElementById(elementId);
getMyFrame.contentWindow.location.reload(true);
I've even tried using jQuery's defer method, but had no luck with that (possibly because I'm lacking knowledge). If I could get any guidance, I'd appreciate it.
try to change this:
function loadPDF() {
$('#iFramePdf').attr('src', "my.pdf");
// Attempt to reload iframe
$('#iFramePdf').load("my.pdf");
sendPrint('iFramePdf')
}
to something like this:
function loadPDF() {
$('#iFramePdf').attr('src', "my.pdf");
}
$('#iFramePdf').load(function(){
sendPrint('iFramePdf')
})
it should work
You can try .promise(). For obvious reasons I can't test it out, but I think 3 seconds should be adequate for the iframe to load. Be aware that this is as syntactically correct as I can get it without testing it out. Adjust the fadeIn(1800) and the delay(1200) accordingly.
HTML
<a href='#' id='load_pdf' ><i class='fa fa-2 fa-print'></i></a>
<p id="msg" style="display: none;">Printing Document...</p>
<div id="printPort" style="opacity: 0; width: 1px; height: 1px;"></div>
jQuery
$(function() {
$("#load_pdf").on('click', loadPDF('my.pdf'));
// Create the iframe, and put it inside #printPort
// Change it's src to the file argument
// Animate the #msg for 3 seconds
var loadPDF = function(file) {
$('<iframe id="iFramePdf" src="blank.html"></iframe>').appendTo("#printPort");
$("#iFramePdf").att('src', file);
return $('#msg').fadeIn(1800).delay(1200).fadeOut();
}
var sendPrint = function(elementId) {
var iframe = $(element_id)[0];
iframe.contentWindow.focus();
iframe.contentWindow.print();
}
// Once the animation is done the promise will resolve and sendPrint will execute on callback.
$.when(loadPDF).done(sendPrint('iFramePdf'));
});

Do I need to create multiple functions for multiple actions or can they all be housed in the same function?

I'm working on a script to simulate a page change in a Questionnaire I'm building. I figured maybe I could use a bunch of "if" statements to house all the logic but it's not working right, before I go and create separate functions I'd like to know if it's possible to put them all in one single function.
So far this is the script
function pageChange(){
var chng1 = document.getElementById("p1next");
var chng2a = document.getElementById("p2back");
var chng2b = document.getElementById("p2next");
var chng3a = document.getElementById("p3back");
var chng3b = document.getElementById("p3next");
var pg1 = document.getElementById("page01");
var pg2 = document.getElementById("page02");
var pg3 = document.getElementById("page03");
if (chng1.click){
pg1.style.display="none";
pg2.style.display="block";
}
if (chng2a.click){
pg1.style.display="block";
pg2.style.display="none";
}
the "p1next, p2back, p2next etc." are IDs I gave the buttons on the pages, which I have in DIVs that I respectively named "page01, page02, page03 etc."
Without the 2nd if statement the script works exactly how I want it, it changes the display for "page01" to none and the div for "page02" to block. When I add the second if statement it doesn't work.
The reason I want to do it like this rather than making actual pages is because I don't want the data to get lost when they load another page. Am I on the right track or do I need to create a new function for each page?
Not exactly on the right track, you should use onclick events, instead of if (x.click) like this:
var chng1 = document.getElementById("p1next");
var pg1 = document.getElementById("page01");
var pg2 = document.getElementById("page02");
// Events
chng1.onclick = function(){
pg1.style.display="none";
pg2.style.display="block";
};
This will save your function until the element is clicked and then execute that function. In your case, it is executed on page load, and at that moment the user is not clicking anything.
Why not try something like this:
HTML:
<div class="page" data-pg="1">...</div>
<div class="page" data-pg="2">...</div>
<div class="page" data-pg="3">...</div>
<input id="btnPrev" type="button" value="Prev" />
<input id="btnNext" type="button" value="Next" />
jQuery:
var pageNum = 1;
$(document).ready(function () {
$("#btnPrev").on("click", function () { ChangePage(-1); });
$("#btnNext").on("click", function () { ChangePage(1); });
ChangePage(0);
});
function ChangePage(p) {
$(".page").hide();
pageNum += p;
$(".page[data-pg='" + p + "']").show();
$("#btnPrev").removeAttr("disabled");
$("#btnNext").removeAttr("disabled");
if (pageNum === 1) $("#btnPrev").attr("disabled", "disabled");
if (pageNum === $(".page").length) $("#btnNext").attr("disabled", "disabled");
}
That way you can easily grow your number of pages without changing the script. My apologies by the way for doing this in jQuery.
Update:
Have a lot of time on my hands today and have not coded for while using vanilla Javascript. Here's the version of the code using plain js: https://jsfiddle.net/hhnbz9p2/

Running javascript function conditionally - Razor, HTML

Right now I have a table that's created dynamically using user selection + data. Sometimes, there are errors with the data, and I'd like to let a user know in the table.
Razor (the link takes you to ~/ControllerName/givenID)
<tr id="#givenID">
<td>#Html.ActionLink(name, someMethod, "ControllerName", new { id = givenID }, new { title = "", id = givenID })</td>
#if (errorConditions)
{
<div id="#givenID" onload="addErrorMessage(this)" data-test="ErrorMessage" style="display: none"></div>
}
</tr>
Javascript
$(function () {
//adding custom tooltip to document
$(document).tooltip();
//adding error message to standard
function addErrorMessage(element) {
var theElemOfID = document.getElementById(element.id);
theElemOfID.title = element.attr("data-test");
theElemOfID.style.color = rgb(255, 0, 0);
} });
I'm trying to add a title to the ActionLink (so it can be used by the tooltip) and also change the color of the link, but only when the the errorConditions are true.
Right now when I run, nothing happens. The addErrorMessage never calls, but all the information is in the places I expect (as in the link has the right ID, etc).
Does anyone have an idea?
onload is only supported on the <body>, but it is highly recommended that you do not use inline event handlers!
Use an inline script, like this (using jQuery since you seem to be using it):
#if (errorConditions)
{
<div id="#givenID" data-test="ErrorMessage" style="display: none"></div>
<script>
$(function() {
addErrorMessage($('##givenID'));
});
</script>
}

Creating a way to navigate back when using jQuery for AJAX

I am dynamically loading content into part of a page using jQuery .load().
It is working well, but I am having trouble building a way for the user to navigate back to the original content after the new content has been loaded.
I have created a 'close' icon with css which exists on the new page which is loaded, but I am not sure how to set up the jQuery / JavaScript in order for it to navigate the user back to the original state of that part of the page.
This is the relevant js:
// pages to load
var loadLudwig = "lw.html";
$("#work a:first-child").click(function() {
$("#work").fadeTo('slow', 0, function() {
$("#work").load(loadLudwig, function(){
$("#work").fadeTo('slow', 1);
});
});
});
// (& this part is working fine)
The relevant HTML (on the original page) is like this (its a grid of images embedded within anchor tags):
<section id="work">
...img and svg stuff
</section>
I tried many variations of:
$("#close-button").click(function() {
$("#work").fadeTo('slow', 0, function () {
$("#work").load('home.html #work', function() {
$("#work").fadeTo('slow', 1);
});
});
});
but this loads the content very strangely / some of the original functionality of #work is lost.
How do I get my close button to navigate back to the original state of #work?
In the jquery documentation for .load() is stated that:
Script Execution
When calling .load() using a URL without a suffixed selector
expression, the content is passed to .html() prior to scripts being
removed. This executes the script blocks before they are discarded. If
.load() is called with a selector expression appended to the URL,
however, the scripts are stripped out prior to the DOM being updated,
and thus are not executed. An example of both cases can be seen below:
Here, any JavaScript loaded into #a as a part of the document will
successfully execute.
1. $( "#a" ).load( "article.html" );
However, in the following case, script blocks in the document being
loaded into #b are stripped out and not executed:
1. $( "#b" ).load( "article.html #target" );
This is a probable cause for lack of functionality.
I'd also look into event binding. In your code examples you're using .click but if you are loading content or you are creating elements on-the-fly you should be favoring .on(). This method delegates events instead of just binding them to a DOM node.
I'd recommend you reading the whole article.
EDIT:
Here is a quick n'dirty way of achieving the effect
// pages to load
var loadLudwig = "lw.html",
$ludwig,
$work = $('#work'),
$workContent = $work.children(),
$closeButton = $("#close-button");
$work.find('a:first-child').click(function() {
$work.fadeTo('slow', 0, function() {
//Here is the tricky part
//Detaching keeps all the jQuery data on the elements
$workContent.detach();
//The first time, load the content,
//if the content is already loaded
//append it to the container
if(!$ludwig){
$work.load(loadLudwig, function(){
//Save the content in a var
//so you can reuse it later
$ludwig = $work.children();
$work.fadeTo('slow', 1);
});
} else {
$ludwig.appendTo($work);
$work.fadeTo('slow', 1);
}
});
});
$closeButton.click(function() {
$work.fadeTo('slow', 0, function () {
//Remove the old content, don't worry
//because is stored in $ludwig
$work.children().detach();
//Instead of reloading the content, just
//attach the fragment again
$workContent.appentTo($work);
$work.fadeTo('slow', 1);
});
});
You probably need to save the html somewhere. For example:
// Top of file
var oldHTML = "";
// Lots of stuff...
$("#work a:first-child").click(function() {
$("#work").fadeTo('slow', 0, function() {
// Store the old html
oldHTML = $("#work").html();
$("#work").load(loadLudwig, function(){
$("#work").fadeTo('slow', 1);
});
});
});
// Code for the close button
$("#close-button").click(function() {
$("#work").fadeTo('slow', 0, function () {
$("#work").html(oldHTML).fadeIn("slow");
});
});
Alternatively, instead of replacing the html, you could create another child. Of course, you might have to slightly change your markup.
<section id="work">
<div id="oldHTML">
...img and svg stuff
</div>
<div id="newSection" style="display:none;">
</div>
</section>
Then replace $("#work") with $("#oldHTML") in your first piece of code like so:
$("#oldHTML a:first-child").click(function() {
$("#oldHTML").fadeTo('slow', 0, function() {
$("#oldHTML").hide();
$("#newSection").load(loadLudwig, function(){
$("#newSection").show().fadeTo('slow', 1);
});
});
});
// Code for the close button
$("#close-button").click(function() {
$("#newSection").fadeTo('slow', 0, function () {
$("#newSection").hide();
$("#work").fadeIn("slow");
});
});

change cursor to busy while page is loading

I understand how to use javascript to change the cursor to busy while the page is making and ajax call.
However I have a page that does not use ajax, it uses a postback to reload the page. However the load is rather data intensive and it takes a few seconds. During this time the user can still click on the page. I want to turn the cursor to "waiting" so the user does not try to click on the page.
For example I have a couple of dropdowns that cause postback. I make a selection and the page loads for 3 seconds. While it loads I would like the cursor to turn to waiting so the user does not try to make a selection on a second dropdown until the page reloads.
Is this possible?
Additional Info: (simplified version of my setup)
I have a masterpage:
<form id="form1" runat="server">
<table width = "100%" bgcolor="White">
<tr><td>
<h3><asp:ContentPlaceHolder id="MAIN" runat="server"></asp:ContentPlaceHolder></h3>
</tr></td>
</table>
</form>
<script type="text/javascript">
function cursorwait(e) {
document.body.style.cursor = 'wait';
}
var fm = document.getElementById('<% =form1.ClientID %>');
if (fm.addEventListener) {
fm.addEventListener('submit', cursorwait, false);
}
else {
fm.attachEvent('onsubmit', cursorwait);
}
</script>
and then a page that uses the master page:
<asp:Content ID="Content1" ContentPlaceHolderID="MAIN" Runat="Server">
<table runat=server id="tb_simple_search_table" cellpadding = 0 cellspacing = 0>
<tr><td>
<asp:DropDownList...
<asp:DropDownList...
</td></tr>
</table>
</asp:content>
I am not certain if this is the best or most efficient method but if you want to change the cursor to show the page is busy after the button click the following jQuery should do the trick:
$(document).ready(function() {
$(".button").click(function() {
$("*").css("cursor", "wait");
});
});
you can add a handler to the form's submit event.
CSS
.wait, .wait * { cursor: wait; }
JavaScript
function cursorwait(e) {
document.body.className = 'wait';
}
var fm = document.getElementById('<% =form1.ClientID %>');
var proxySubmit = fm.onsubmit;
fm.onsubmit = function () {
cursorwait();
if (proxySubmit) {
proxySubmit.call(fm);
}
}
here we're ensuring our method gets called if submit() is called in js like the drop down does when it causes a postback. this should also catch any other instances of the form submitting.
Just give each button a class, say "WaitOnClick", then just write it: $(".WaitOnClick").click(function() {

Categories

Resources