avoid reloading JavaScripts files in Partial Views - javascript

In my project I have a large JavaScript file (bigger than 1 MB) that I use in all pages, I put it in _Layout and every thing work correctly but when I want to update partial view that show a table I loose link between that partial view and JavaScript file and if I want to reload it in partial view users need to waste their time to changes. I use ajax to update partial views.
What can I do to solve that problem?
Java script that I use is:<script src="~/Content/js/vendor.min.js"></script>
Ajax that I use to update opartial view is:
<script>
function EditClick(id, pg) {
var model = {
CurrentPage: pg,
SortColumn: '#Model.SortColumn',
SortStatus: '#Model.SortStatus',
id: id,
};
var formDiv = $("#rplaceInsert");
$.ajax({
cache: false,
type: "Post",
url: "#Url.Action("EditSurgeryType", "SurgeryType")",
contentType: 'application/json',
data: JSON.stringify(model)
,
success: function (data) {
formDiv.html(data);
},
error: function (xhr, ajaxOptions, thrownError) {
}
});
}

This has nothing to do with reload. Once a file is loaded once in the browser, it will remain cached so telling it to load in multiple places will simply load it from the cache as long as it's all on the same domain.
That said, your issue is because JQuery doesn't automatically apply it's selectors to new elements added to the DOM. It isn't actively watching, so new elements won't get events or be processed unless you do so explicitly.
You can refactor your script so that the parts which apply to your partial view are in their own function. This way, when the partial view is changed, you can call that function to apply your jQuery selectors to them.
If all you're concerned with is hooking up events for in a table or list, you can "defer" those events by putting them on an element higher up in the DOM that doesn't change. Events in Javascript bubble so rather than listening for individual events on items in your table/list, you listen for them once on the list itself. That way, when the table changes, the new elements will still bubble up their events.

Related

Do a reload of mvc/razor partial view with javascript

In my project I have rows of modules loaded from Partial views.
So imagine a grid of small squares with information.
There is a popup dialog for all of them, that displays the data of the clicked module.
Currently when I submit a change in the dialog, the javascript reloads the entire page. BUT, this takes a long time, and I need to be able to refresh only the one dialog.
I can imagine to make a separate js function for each type of module, and then pass some data in, so jquery can find the specific module, and then make an ajax get, for the data. But this requires me to do all the data insertion from js always. instead of using razor and MVC's built in awesomeness.
Does anyone know of a way, to call a partial view inside a div?
Also in the future I will need to reload "some" but not all the modules in an interval refresh. So for future proofing purposes:
What im looking for is something like:
function reloadElement(row, column, id){
var target = $("#div1");
// todo find row and column
target.html.partial("url", model); //<----- looking for something like this. cross fingers.
}
Thanks to GregH for a few key words, that lead to some ideas.
I solved it myself, so if you land on this problem also, here is how i solved it:
Controller:
You want to make your controller return PartialView("somePartialViewUrl", new SomeModel()), apparently saving the model and relying on the data collection isn't good enough, i hadto make a new instance of the model.
Javascript
in the "click" that handles the event, put:
$.ajax({
url: "controllerName/actionName",
data: JSON.stringify({ row:1,column:2 .... }),
contentType: "application/json",
dataType: "html",
type: "POST",
success: function (partial) {
$("#div2").html(partial);
}
});
this will override the html in your "#div2".
im sure you can also use $("#div2").innerHTML = partial; or $("#div2").load("url",parameters); and probably many other ways.
done.

how to use jit spacetree and jqgrid on same page?

I have one page in which I want jit Spacetree and jqgrid. But it show either jqgrid or Spacetree correctly. I am loading Spacetree with json data by ajax request.
root node never comes, but all other nodes comes and it is fully functional. If I delete jqgrid includes then tree loads with root node.
I have used this example of spacetree
http://philogb.github.io/jit/static/v20/Jit/Examples/Spacetree/example2.html
I have replaced 3 lines of example2.js with this function
st.loadJSON(eval( $.parseJSON(json)));
st.compute();
st.onClick(st.root);
function to get json data
$.ajax({
type: "POST",
url: "../default.aspx",
data: {Mode: 'Tree'},
dataType: "text",
success: function(response) {
var response = $.parseJSON(response);
//load json data
st.loadJSON(response);
//compute node positions and layout
st.compute();
//optional: make a translation of the tree
// st.geom.translate(new $jit.Complex(-200, 0), "current");
//emulate a click on the root node.
st.onClick(st.root);
// NodeId=st.root;
},
error: function(rs, e) {
//alert(rs.responseText);
return false;
}
});
I have used this jqgrid
http://jsfiddle.net/amorris/yNw3C/
I have included following files in html
jqgrid-4.4.5-src/ui.jqgrid.css,
jqgrid-4.4.5-src/jquery.jqGrid.js,
jqgrid-4.4.5-src/jquery-ui.css,
jqgrid-4.4.5-src/grid.locale-en.js,
It was because of naming convention used by jqgrid and spacetree. Both were creating same id. jqgrid was creating a row with the id =1 and spacetree was also creating a div with id=1. Now while creating nodes of the tree, dom was fetching the div by id. As jqgrid was loading first so dom was getting the id of the jqgrid row instead of div. I changed the jqgrid id-creation process by adding prefix to it. And now it is working.

Will reinitializing a JavaScript object at global scope cause a memory leak?

I have links in a JQuery DataTable that use JQuery UI's tooltip feature. Each link has a tooltip that is populated by an Ajax call. I would like to limit the number of Ajax calls to as few as possible. The DataTable uses server-side processing, and the results are paginated, so there will never be more than ten links on the page at any one time.
The data that is returned by the Ajax call will never change and thus can be safely cached. In my testing, I have seen that the browser does cache the result of each Ajax call, so that it only makes one call per link, and then uses the cache thereafter. My concern is that some user might have their browser configured in such a way that it doesn't use the cache for some reason, and they will be firing off one Ajax call after another, every time they mouse over a link.
Here is the JavaScript for the tooltip:
$('.jobId').tooltip({
content: function(callback) {
var jobId = $(this).text();
$.ajax({
url: 'myUrl',
data: {jobId: jobId},
dataType: 'json',
success: function(data) {
var html = formatResults(data);
callback(html);
},
error: function() {
callback('An error has occurred.');
}
});
}
});
I considered storing the result of each Ajax call in a JavaScript object declared at global scope, and then checking that before making the Ajax call, but I have the vague sense that this might cause a memory leak somehow.
var gJobs = new Object();
$('.jobId').tooltip({
content: function(callback) {
var jobId = $(this).text();
if (gJobs[jobId]) {
callback(gJobs[jobId]);
} else {
$.ajax({
url: 'myUrl',
data: {jobId: jobId},
dataType: 'json',
success: function(data) {
var html = formatResults(data);
gJobs[jobId] = html;
callback(html);
},
error: function() {
callback('An error has occurred.');
}
});
}
}
});
I am also concerned that if the table has a large number of rows, the gJobs object could end up using a lot of memory. To prevent the gJobs object from growing indefinitely, every time the user goes to the next or previous page of results in the DataTable, I use the fnDrawCallback function to reinitialize gJobs:
$('#jobsTable').dataTable({
...
"fnDrawCallback": function() {
gJobs = new Object();
}
});
I should mention that since the data returned by each Ajax call doesn't change, I could also just store the data in the JSP as static text, and populate the tooltips that way instead of using Ajax. However, I have to make a separate web service call to get the data for each link, and rather than make ten web service calls every time the user pages forward or back, I would rather load the data on demand via Ajax.
Is there anything wrong with this approach? Is there any way this can cause a memory leak? Should I explicitly delete all the properties of gJobs before reinitializing it? Thanks for your help.

JQuery FullCalendar trouble with invoking rerenderEvents from ajax success

For some reason, I cannot get the calendar to rerender after a POST. All goes well up to that point:
$('#calendar').fullCalendar({
...
select: function (startDate, endDate) {
$.ajax({
url: 'data.php',
type: "POST",
data: {
'start':startDate,
'end':endDate,
}
success: $('#calendar').fullCalendar('rerenderEvents')
}
...
});
The data posts successfully, my php script adds the new event to the database just fine. The only problem is that the calendar is not being rerendered with the new data in the database.
If I refresh the page (F5 in Firefox) the new event is rendered. Obviously, I need the event to show up as soon as it has been committed to the database. I can't expect my user to refresh the page.
I have done many permutations of this success statment, eg:
function () {
$('#calendar').fullCalendar('rerenderEvents');
}
and (with my php returning 'success'),
function (data) {
if (data === 'success') $('#calendar').fullCalendar('renderEvents');
}
However, no matter what, the new event added to the database only shows up if I refresh the screen. Can anyone suggest what I might be doing wrong?
Try:
$('#calendar').fullCalendar("refetchEvents");
Update 2013-01-31.
That works because you are forcing FC to reread the event source and render the calendar again.
However, if that is sometimes a brute force solution, another way to achieve the same (when possible) is to do this, say in dayClick when creating a new event:
update event-DB using $.ajax
create the corresponding new event:
yourcal.fullCalendar('renderEvent', {id:x,start:timest,end:timend,title:txt}, true);

How do I trigger events after event handlers are bound in ajax calls when the page loads?

Problem:
I've got 2 drop downs, both populated by information from a database and dependent on some initial information (a json array created in php). The second drop down is also dependent on what was selected in the first dropdown. Once the second dropdown has been selected, the users selections are saved in another database table. If the user leaves and then comes back, I want to be able to reset the drop downs to what they previously selected (but still let them change their selections).
Context:
I have some code that looks like the following:
function eventHandler2(event) {
$.ajax({
url: "someotherurl.php",
data: event.data["context"],
success: function(data) {
// Do some stuff
}
});
}
function eventHandler1(event) {
event.data["context"][$(event.target).id()] = $(event.target).val();
$.ajax({
url: "someurl.php",
data: event.data["context"],
success: function(data) {
$("#element").append(build_input("input2", data));
$("#element input2").change({"context": event.data["context"]}, eventHandler2);
}
});
}
$(document).ready(function() {
var context = // php generated json array.
$("#element").append(build_input("input1", context));
$("#element input1").change({"context": context}, eventHandler1);
});
context includes some data that has to be initialized outside of the event handler and is added to durring events, and build_input just returns an html string of a form input element built with options determined by data or someData. At times the entire html element that includes eventHandler1 (and eventHandler2) will be removed and reinitialized.
My issue is that I want to initialize the two form inputs (built using build_input) with some default values pulled from a database, but once those values have been set I don't want any reinitialization or event handling to use those initial values (which makes adding them to the context object difficult since that object will be used when binding the event handlers).
I would like to set the value for the inputs and then call a change event to simulate a user selecting those values, but because the input elements are built using ajax data, those change events are being getting called before the ajax request have returned and built the input elements.
I could solve this with timeouts, but because the the javascript might run slower on different machines and the ajax calls could take longer than normal, I don't plan on doing it that way. Still, ideally I would like something like this:
$("#element .input1 option[value='" + initial_value + "']").attr('selected', true);
$("#element .input1").change();
to be called when the page loads but only after the elements have been built and bound.
Question:
Is there any way to trigger change events (simulating the user selecting options) only when the page is first loaded and only after the ajax request to build the html input elements have returned?
Is there any way to trigger change events (simulating the user selecting options) only when the
page is first loaded
and only
after the ajax request
to build the html input elements have returned?
These are two separate events. If you need to ensure both events have ocurred use <body onload="loadedBody=true"> and take advantage of the success: attribute of the $.ajax function like this:
function eventHandler1(event) {
event.data["context"][$(event.target).id()] = $(event.target).val();
$.ajax({
url: "someurl.php",
data: event.data["context"],
success: function(data) {
$("#element").append(build_input("input2", data));
$("#element input2").change({"context": event.data["context"]}, eventHandler2);
ajaxComplete();
}
});
}
var ajaxCompleted;
function ajaxComplete() {
if((loadedBody == true) && (ajaxCompleted == false)) {
$("#element .input1 option[value='" + initial_value + "']").attr('selected', true);
$("#element .input1").change();
} else {
setTimeout('ajaxComplete()', 100);
}
}
Don't worry about the setTimeout. It will rarely be used because the page will likely have loaded before the AJAX result arrives.

Categories

Resources