Added jquery.unobtrusive-ajax for Ajax Helpers, much cleaner HTML and no jQuery work-around required.

Fix: Ajax Links are working again.
This commit is contained in:
Mark McDowall 2012-02-26 01:32:39 -08:00
parent 4a55d08130
commit 8b9cb7b8ff
22 changed files with 381 additions and 48 deletions

View File

@ -11,6 +11,21 @@ namespace NzbDrone.Web.Helpers
{ {
public static class LinkHelper public static class LinkHelper
{ {
public static MvcHtmlString ImageActionLink(this AjaxHelper helper, string imageUrl, object imgAttributes, string actionName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes)
{
return ImageActionLink(helper, imageUrl, imgAttributes, actionName, null, routeValues, ajaxOptions, htmlAttributes);
}
public static MvcHtmlString ImageActionLink(this AjaxHelper helper, string imageUrl, object imgAttributes, string actionName, string controllerName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes)
{
var builder = new TagBuilder("img");
builder.MergeAttribute("src", imageUrl);
var imgAttributesDictionary = new RouteValueDictionary(imgAttributes);
builder.MergeAttributes(imgAttributesDictionary);
var link = helper.ActionLink("[replaceme]", actionName, controllerName, routeValues, ajaxOptions, htmlAttributes).ToHtmlString();
return new MvcHtmlString(link.Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)));
}
public static MvcHtmlString ImageActionLink(this HtmlHelper helper, string imageUrl, object imgAttributes, string actionName, object routeValues, object htmlAttributes) public static MvcHtmlString ImageActionLink(this HtmlHelper helper, string imageUrl, object imgAttributes, string actionName, object routeValues, object htmlAttributes)
{ {
return ImageActionLink(helper, imageUrl, imgAttributes, actionName, null, routeValues, htmlAttributes); return ImageActionLink(helper, imageUrl, imgAttributes, actionName, null, routeValues, htmlAttributes);

View File

@ -348,6 +348,8 @@
<Content Include="Scripts\jquery.livequery.js" /> <Content Include="Scripts\jquery.livequery.js" />
<Content Include="Scripts\jquery.signalR.js" /> <Content Include="Scripts\jquery.signalR.js" />
<Content Include="Scripts\jquery.signalR.min.js" /> <Content Include="Scripts\jquery.signalR.min.js" />
<Content Include="Scripts\jquery.unobtrusive-ajax.js" />
<Content Include="Scripts\jquery.unobtrusive-ajax.min.js" />
<Content Include="Scripts\jquery.validate-vsdoc.js" /> <Content Include="Scripts\jquery.validate-vsdoc.js" />
<Content Include="Scripts\jquery.validate.js" /> <Content Include="Scripts\jquery.validate.js" />
<Content Include="Scripts\jquery.validate.min.js" /> <Content Include="Scripts\jquery.validate.min.js" />

View File

@ -43,20 +43,3 @@
}); });
}); });
}); });
//Make .ajaxLink use jQuery Ajax for the request
$(document).on('click', '.ajaxLink', function (event) {
event.preventDefault();
var onSuccess = $(this).attr('onsuccess');
$.ajax({
url: this.href,
cache: false,
success: function () {
if (onSuccess) {
window[onSuccess]();
}
}
});
return false;
});

View File

@ -1,6 +1,6 @@
/* Click on row, show details */ /* Click on row, show details */
$(document).on('click', '.seriesTable a, .dataTable a', function (event) { $(document).on('click', '.seriesTable a, .dataTable a', function (event) {
if ($(this).hasClass('ajaxLink') || $(this).attr('onclick')) if ($(this).attr('data-ajax') === "true")
return; return;
event.preventDefault(); event.preventDefault();
@ -46,14 +46,6 @@ function fnFormatDetails(nTr) {
return aData["Details"]; return aData["Details"];
} }
//Create Image
function createImageAjaxLink(url, image, alt, title, classes) {
var html = '<a href="' + url + '" class="ajaxLink">' +
'<img class="' + classes + '" src="' + image + '" title="' + title + '" alt="' + alt + '" /></a>';
return html;
}
//Reload/Redraw the grid from the server (bServerSide == true) //Reload/Redraw the grid from the server (bServerSide == true)
function redrawGrid() { function redrawGrid() {
oTable.fnDraw(); oTable.fnDraw();

View File

@ -0,0 +1,163 @@
/*!
** Unobtrusive Ajax support library for jQuery
** Copyright (C) Microsoft Corporation. All rights reserved.
*/
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
/*global window: false, jQuery: false */
(function ($) {
var data_click = "unobtrusiveAjaxClick",
data_validation = "unobtrusiveValidation";
function getFunction(code, argNames) {
var fn = window, parts = (code || "").split(".");
while (fn && parts.length) {
fn = fn[parts.shift()];
}
if (typeof (fn) === "function") {
return fn;
}
argNames.push(code);
return Function.constructor.apply(null, argNames);
}
function isMethodProxySafe(method) {
return method === "GET" || method === "POST";
}
function asyncOnBeforeSend(xhr, method) {
if (!isMethodProxySafe(method)) {
xhr.setRequestHeader("X-HTTP-Method-Override", method);
}
}
function asyncOnSuccess(element, data, contentType) {
var mode;
if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us
return;
}
mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
$(element.getAttribute("data-ajax-update")).each(function (i, update) {
var top;
switch (mode) {
case "BEFORE":
top = update.firstChild;
$("<div />").html(data).contents().each(function () {
update.insertBefore(this, top);
});
break;
case "AFTER":
$("<div />").html(data).contents().each(function () {
update.appendChild(this);
});
break;
default:
$(update).html(data);
break;
}
});
}
function asyncRequest(element, options) {
var confirm, loading, method, duration;
confirm = element.getAttribute("data-ajax-confirm");
if (confirm && !window.confirm(confirm)) {
return;
}
loading = $(element.getAttribute("data-ajax-loading"));
duration = element.getAttribute("data-ajax-loading-duration") || 0;
$.extend(options, {
type: element.getAttribute("data-ajax-method") || undefined,
url: element.getAttribute("data-ajax-url") || undefined,
beforeSend: function (xhr) {
var result;
asyncOnBeforeSend(xhr, method);
result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments);
if (result !== false) {
loading.show(duration);
}
return result;
},
complete: function () {
loading.hide(duration);
getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments);
},
success: function (data, status, xhr) {
asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments);
},
error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"])
});
options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
method = options.type.toUpperCase();
if (!isMethodProxySafe(method)) {
options.type = "POST";
options.data.push({ name: "X-HTTP-Method-Override", value: method });
}
$.ajax(options);
}
function validate(form) {
var validationInfo = $(form).data(data_validation);
return !validationInfo || !validationInfo.validate || validationInfo.validate();
}
$("a[data-ajax=true]").live("click", function (evt) {
evt.preventDefault();
asyncRequest(this, {
url: this.href,
type: "GET",
data: []
});
});
$("form[data-ajax=true] input[type=image]").live("click", function (evt) {
var name = evt.target.name,
$target = $(evt.target),
form = $target.parents("form")[0],
offset = $target.offset();
$(form).data(data_click, [
{ name: name + ".x", value: Math.round(evt.pageX - offset.left) },
{ name: name + ".y", value: Math.round(evt.pageY - offset.top) }
]);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$("form[data-ajax=true] :submit").live("click", function (evt) {
var name = evt.target.name,
form = $(evt.target).parents("form")[0];
$(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$("form[data-ajax=true]").live("submit", function (evt) {
var clickInfo = $(this).data(data_click) || [];
evt.preventDefault();
if (!validate(this)) {
return;
}
asyncRequest(this, {
url: this.action,
type: this.method || "GET",
data: clickInfo.concat($(this).serializeArray())
});
});
}(jQuery));

View File

@ -0,0 +1,5 @@
/*
** Unobtrusive Ajax support library for jQuery
** Copyright (C) Microsoft Corporation. All rights reserved.
*/
(function(a){var b="unobtrusiveAjaxClick",g="unobtrusiveValidation";function c(d,b){var a=window,c=(d||"").split(".");while(a&&c.length)a=a[c.shift()];if(typeof a==="function")return a;b.push(d);return Function.constructor.apply(null,b)}function d(a){return a==="GET"||a==="POST"}function f(b,a){!d(a)&&b.setRequestHeader("X-HTTP-Method-Override",a)}function h(c,b,e){var d;if(e.indexOf("application/x-javascript")!==-1)return;d=(c.getAttribute("data-ajax-mode")||"").toUpperCase();a(c.getAttribute("data-ajax-update")).each(function(f,c){var e;switch(d){case"BEFORE":e=c.firstChild;a("<div />").html(b).contents().each(function(){c.insertBefore(this,e)});break;case"AFTER":a("<div />").html(b).contents().each(function(){c.appendChild(this)});break;default:a(c).html(b)}})}function e(b,e){var j,k,g,i;j=b.getAttribute("data-ajax-confirm");if(j&&!window.confirm(j))return;k=a(b.getAttribute("data-ajax-loading"));i=b.getAttribute("data-ajax-loading-duration")||0;a.extend(e,{type:b.getAttribute("data-ajax-method")||undefined,url:b.getAttribute("data-ajax-url")||undefined,beforeSend:function(d){var a;f(d,g);a=c(b.getAttribute("data-ajax-begin"),["xhr"]).apply(this,arguments);a!==false&&k.show(i);return a},complete:function(){k.hide(i);c(b.getAttribute("data-ajax-complete"),["xhr","status"]).apply(this,arguments)},success:function(a,e,d){h(b,a,d.getResponseHeader("Content-Type")||"text/html");c(b.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(this,arguments)},error:c(b.getAttribute("data-ajax-failure"),["xhr","status","error"])});e.data.push({name:"X-Requested-With",value:"XMLHttpRequest"});g=e.type.toUpperCase();if(!d(g)){e.type="POST";e.data.push({name:"X-HTTP-Method-Override",value:g})}a.ajax(e)}function i(c){var b=a(c).data(g);return!b||!b.validate||b.validate()}a("a[data-ajax=true]").live("click",function(a){a.preventDefault();e(this,{url:this.href,type:"GET",data:[]})});a("form[data-ajax=true] input[type=image]").live("click",function(c){var g=c.target.name,d=a(c.target),f=d.parents("form")[0],e=d.offset();a(f).data(b,[{name:g+".x",value:Math.round(c.pageX-e.left)},{name:g+".y",value:Math.round(c.pageY-e.top)}]);setTimeout(function(){a(f).removeData(b)},0)});a("form[data-ajax=true] :submit").live("click",function(c){var e=c.target.name,d=a(c.target).parents("form")[0];a(d).data(b,e?[{name:e,value:c.target.value}]:[]);setTimeout(function(){a(d).removeData(b)},0)});a("form[data-ajax=true]").live("submit",function(d){var c=a(this).data(b)||[];d.preventDefault();if(!i(this))return;e(this,{url:this.action,type:this.method||"GET",data:c.concat(a(this).serializeArray())})})})(jQuery);

View File

@ -3,8 +3,8 @@
@{ViewBag.Title = "History";} @{ViewBag.Title = "History";}
@section ActionMenu{ @section ActionMenu{
<ul class="sub-menu"> <ul class="sub-menu">
<li>@Html.ActionLink("Trim History", "Trim", "History", null, new { @class = "ajaxLink", onSuccess = "reloadGrid" })</li> <li>@Ajax.ActionLink("Trim History", "Trim", "History", null, new AjaxOptions{ OnSuccess = "reloadGrid" })</li>
<li>@Html.ActionLink("Purge History", "Purge", "History", null, new { @class = "ajaxLink", onSuccess = "reloadGrid" })</li> <li>@Ajax.ActionLink("Purge History", "Purge", "History", null, new AjaxOptions{ OnSuccess = "reloadGrid" })</li>
</ul> </ul>
} }
@section HeaderContent @section HeaderContent

View File

@ -3,7 +3,7 @@
@{ ViewBag.Title = "Logs";} @{ ViewBag.Title = "Logs";}
@section ActionMenu{ @section ActionMenu{
<ul class="sub-menu"> <ul class="sub-menu">
<li>@Html.ActionLink("Clear Logs", "Clear", "Log", null, new { @class = "ajaxLink", onSuccess = "redrawGrid" })</li> <li>@Ajax.ActionLink("Clear Logs", "Clear", "Log", null, new AjaxOptions{ OnSuccess = "redrawGrid" })</li>
<li>@Html.ActionLink("File", "File", "Log")</li> <li>@Html.ActionLink("File", "File", "Log")</li>
</ul> </ul>
} }

View File

@ -9,9 +9,9 @@
} }
@section ActionMenu{ @section ActionMenu{
<ul class="sub-menu"> <ul class="sub-menu">
<li>@Html.ActionLink("Start RSS Sync", "RssSync", "Command", null, new { @class = "ajaxLink" })</li> <li>@Ajax.ActionLink("Start RSS Sync", "RssSync", "Command", null, null)</li>
<li>@Html.ActionLink("Start Backlog Search", "BacklogSearch", "Command", null, new { title = "Backlog search for ALL missing episodes", @class = "ajaxLink" })</li> <li>@Ajax.ActionLink("Start Backlog Search", "BacklogSearch", "Command",null, null, new { title = "Backlog search for ALL missing episodes"})</li>
<li>@Html.ActionLink("Start Recent Backlog Search", "RecentBacklogSearch", "Command", null, new { title = "Backlog search for missing episodes that aired in the last 30 days only", @class = "ajaxLink" })</li> <li>@Ajax.ActionLink("Start Recent Backlog Search", "RecentBacklogSearch", "Command", null, null, new { title = "Backlog search for missing episodes that aired in the last 30 days only" })</li>
</ul> </ul>
} }
<div class="grid-container"> <div class="grid-container">
@ -81,7 +81,9 @@
} }
}, //Grabbed On }, //Grabbed On
{ sWidth: '40px', "mDataProp": "EpisodeId", "bSortable": false, "fnRender": function (row) { { sWidth: '40px', "mDataProp": "EpisodeId", "bSortable": false, "fnRender": function (row) {
return createImageAjaxLink('/Episode/Search?episodeId=' + row.aData["EpisodeId"], '../../Content/Images/Search.png', 'Search', 'Search for Episode', 'gridAction'); var link = '@Ajax.ImageActionLink("../../Content/Images/Search.png", new { title = "Search for Episode", alt = "Search", @class = "gridAction" }, "Search", "Episode", new { episodeId = "REPLACE" }, null, null)';
link = link.replace("REPLACE", row.aData["EpisodeId"]);
return link;
} }
}, //Actions }, //Actions
{ sWidth: 'auto', "mDataProp": "Details", "bSortable": false, "bVisible": false, "fnRender": function (row) { { sWidth: 'auto', "mDataProp": "Details", "bSortable": false, "bVisible": false, "fnRender": function (row) {

View File

@ -68,9 +68,9 @@
{ {
<ul class="sub-menu"> <ul class="sub-menu">
<li><a class="editButton" value="@Model.SeriesId" rel="@Model.Title">Edit</a></li> <li><a class="editButton" value="@Model.SeriesId" rel="@Model.Title">Edit</a></li>
<li>@Html.ActionLink("Force Refresh", "ForceRefresh", "Command", new { seriesId = Model.SeriesId }, new { @class = "ajaxLink" })</li> <li>@Ajax.ActionLink("Force Refresh", "ForceRefresh", "Command", new { seriesId = Model.SeriesId }, null)</li>
<li>@Html.ActionLink("Search for missing episodes", "BacklogSeries", "Episode", new { seriesId = Model.SeriesId }, new { @class = "ajaxLink" })</li> <li>@Ajax.ActionLink("Search for missing episodes", "BacklogSeries", "Episode", new { seriesId = Model.SeriesId }, null)</li>
<li>@Html.ActionLink("Rename Episode Files", "RenameEpisodes", "Episode", new { seriesId = Model.SeriesId }, new { @class = "ajaxLink" })</li> <li>@Ajax.ActionLink("Rename Episode Files", "RenameEpisodes", "Episode", new { seriesId = Model.SeriesId }, null)</li>
</ul> </ul>
} }

View File

@ -25,7 +25,7 @@
@*Commands Column*@ @*Commands Column*@
<td class="@cellColourClass"> <td class="@cellColourClass">
<img src='../../Content/Images/@(Model.Ignored ? "ignored" : "notIgnored").png' class='ignoreEpisode ignoreEpisode_@(Model.SeasonNumber)@(Model.Ignored ? " ignored" : " ") gridAction' id='@Model.EpisodeId' title='Click to toggle episode ignore status' /> <img src='../../Content/Images/@(Model.Ignored ? "ignored" : "notIgnored").png' class='ignoreEpisode ignoreEpisode_@(Model.SeasonNumber)@(Model.Ignored ? " ignored" : " ") gridAction' id='@Model.EpisodeId' title='Click to toggle episode ignore status' />
@Html.ImageActionLink("../../Content/Images/Search.png", new { Alt = "Search", Title = "Search for episode", @class = "gridAction" }, "Search", "Episode", new { episodeId = Model.EpisodeId }, new { @class = "ajaxLink" }) @Ajax.ImageActionLink("../../Content/Images/Search.png", new { Alt = "Search", Title = "Search for episode", @class = "gridAction" }, "Search", "Episode", new { episodeId = Model.EpisodeId }, null, null)
<img src='../../Content/Images/@(Model.Status).png' alt='@Model.Status' title='@Model.Status' class='gridImage status-@Model.Status statusImage' /> <img src='../../Content/Images/@(Model.Status).png' alt='@Model.Status' title='@Model.Status' class='gridImage status-@Model.Status statusImage' />
</td> </td>
</tr> </tr>

View File

@ -75,7 +75,7 @@
@section ActionMenu{ @section ActionMenu{
<ul class="sub-menu"> <ul class="sub-menu">
<li>@Html.ActionLink("Add Series", "Index", "AddSeries")</li> <li>@Html.ActionLink("Add Series", "Index", "AddSeries")</li>
<li>@Html.ActionLink("Start RSS Sync", "RssSync", "Command", null, new { @class = "ajaxLink" })</li> <li>@Ajax.ActionLink("Start RSS Sync", "RssSync", "Command", null)</li>
<li>@Html.ActionLink("Series Editor", "SeriesEditor", "Series")</li> <li>@Html.ActionLink("Series Editor", "SeriesEditor", "Series")</li>
</ul> </ul>
} }

View File

@ -23,8 +23,8 @@
@*Commands Column*@ @*Commands Column*@
<th> <th>
<img src='../../Content/Images/@(Model.Ignored ? "ignored" : "notIgnored").png' class='ignoredEpisodesMaster ignoreEpisode ignoreSeason_@(Model.SeasonNumber)@(Model.Ignored ? " ignored" : " ") gridAction' title='Click to toggle season ignore status' /> <img src='../../Content/Images/@(Model.Ignored ? "ignored" : "notIgnored").png' class='ignoredEpisodesMaster ignoreEpisode ignoreSeason_@(Model.SeasonNumber)@(Model.Ignored ? " ignored" : " ") gridAction' title='Click to toggle season ignore status' />
@Html.ImageActionLink("../../Content/Images/Search.png", new { Alt = "Search", Title = "Search for all episodes in this season", @class = "gridAction" }, "SearchSeason", "Episode", new { SeriesId = Model.SeriesId, SeasonNumber = Model.SeasonNumber }, new { @class = "ajaxLink" }) @Ajax.ImageActionLink("../../Content/Images/Search.png", new { Alt = "Search", Title = "Search for all episodes in this season", @class = "gridAction" }, "SearchSeason", "Episode", new { SeriesId = Model.SeriesId, SeasonNumber = Model.SeasonNumber }, null, null)
@Html.ImageActionLink("../../Content/Images/Rename.png", new { Alt = "Rename", Title = "Rename all episodes in this season", @class = "gridAction" }, "RenameSeason", "Episode", new { SeriesId = Model.SeriesId, SeasonNumber = Model.SeasonNumber }, new { @class = "ajaxLink" }) @Ajax.ImageActionLink("../../Content/Images/Rename.png", new { Alt = "Rename", Title = "Rename all episodes in this season", @class = "gridAction" }, "RenameSeason", "Episode", new { SeriesId = Model.SeriesId, SeasonNumber = Model.SeasonNumber }, null, null)
</th> </th>
</tr> </tr>
</thead> </thead>

View File

@ -29,6 +29,7 @@
@Html.IncludeScript("jquery.signalR.min.js") @Html.IncludeScript("jquery.signalR.min.js")
@Html.IncludeScript("jquery.validate.js") @Html.IncludeScript("jquery.validate.js")
@Html.IncludeScript("jquery.validate.unobtrusive.js") @Html.IncludeScript("jquery.validate.unobtrusive.js")
@Html.IncludeScript("jquery.unobtrusive-ajax.min.js")
@Html.IncludeScript("jquery.cookie.js") @Html.IncludeScript("jquery.cookie.js")
@Html.IncludeScript("doTimeout.js") @Html.IncludeScript("doTimeout.js")
@Html.IncludeScript("conditional-validation.js") @Html.IncludeScript("conditional-validation.js")

View File

@ -73,8 +73,9 @@
if (!row.aData["Enable"]) if (!row.aData["Enable"])
return ""; return "";
return createImageAjaxLink('/System/RunJob?typeName=' + row.aData["TypeName"], '../../Content/Images/Gear.png', 'Run', 'Run Job', 'gridAction'); var link = '@Ajax.ImageActionLink("../../Content/Images/Gear.png", new { title = "Run Job", alt = "Job", @class = "gridAction" }, "RunJob", "System", new { typeName = "REPLACE" }, null, null)';
//return createImageAjaxLink('/History/Delete?historyId=' + row.aData["HistoryId"], '../../Content/Images/X.png', 'Delete', 'Delete from History', 'searchImage'); link = link.replace("REPLACE", row.aData["TypeName"]);
return link;
} }
} //Actions } //Actions
], ],

View File

@ -20,7 +20,7 @@
} }
@section ActionMenu{ @section ActionMenu{
<ul class="sub-menu"> <ul class="sub-menu">
<li>@Html.ActionLink("Start RSS Sync", "RssSync", "Command", null, new { @class = "ajaxLink" })</li> <li>@Ajax.ActionLink("Start RSS Sync", "RssSync", "Command", null)</li>
</ul> </ul>
} }
<div class="gridControls"> <div class="gridControls">

View File

@ -36,7 +36,7 @@
@*Commands Column*@ @*Commands Column*@
<td class="@cellColourClass"> <td class="@cellColourClass">
<img src='../../Content/Images/@(Model.Status).png' alt='@Model.Status' title='@Model.Status' class='gridImage statusImage' /> <img src='../../Content/Images/@(Model.Status).png' alt='@Model.Status' title='@Model.Status' class='gridImage statusImage' />
@Html.ImageActionLink("../../Content/Images/Search.png", new { Alt = "Search", Title = "Search for episode", @class = "gridAction" }, "Search", "Episode", new { episodeId = Model.EpisodeId }, new { @class = "ajaxLink" }) @Ajax.ImageActionLink("../../Content/Images/Search.png", new { Alt = "Search", Title = "Search for episode", @class = "gridAction" }, "Search", "Episode", new { episodeId = Model.EpisodeId }, null, null)
</td> </td>
</tr> </tr>

View File

@ -9,7 +9,7 @@ else
{ {
<h2> <h2>
Available Update: @Model.UpdatePackage.Version Available Update: @Model.UpdatePackage.Version
@Html.ActionLink("Update", "StartUpdate", "Update", null, new { @class = "ajaxLink" }) @Ajax.ActionLink("Update", "StartUpdate", "Update", null)
</h2> </h2>
} }
@if (Model.LogFiles.Count != 0) @if (Model.LogFiles.Count != 0)

View File

@ -5,6 +5,7 @@
<package id="EntityFramework.SqlServerCompact" version="4.1.8482.2" /> <package id="EntityFramework.SqlServerCompact" version="4.1.8482.2" />
<package id="jQuery" version="1.6.1" /> <package id="jQuery" version="1.6.1" />
<package id="jQuery" version="1.7.1" /> <package id="jQuery" version="1.7.1" />
<package id="jQuery.Ajax.Unobtrusive" version="2.0.20126.16343" />
<package id="jquery.cookie" version="1.0" /> <package id="jquery.cookie" version="1.0" />
<package id="jquery.datatables" version="1.9.0" /> <package id="jquery.datatables" version="1.9.0" />
<package id="jQuery.UI.Combined" version="1.8.17" /> <package id="jQuery.UI.Combined" version="1.8.17" />

View File

@ -0,0 +1,163 @@
/*!
** Unobtrusive Ajax support library for jQuery
** Copyright (C) Microsoft Corporation. All rights reserved.
*/
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
/*global window: false, jQuery: false */
(function ($) {
var data_click = "unobtrusiveAjaxClick",
data_validation = "unobtrusiveValidation";
function getFunction(code, argNames) {
var fn = window, parts = (code || "").split(".");
while (fn && parts.length) {
fn = fn[parts.shift()];
}
if (typeof (fn) === "function") {
return fn;
}
argNames.push(code);
return Function.constructor.apply(null, argNames);
}
function isMethodProxySafe(method) {
return method === "GET" || method === "POST";
}
function asyncOnBeforeSend(xhr, method) {
if (!isMethodProxySafe(method)) {
xhr.setRequestHeader("X-HTTP-Method-Override", method);
}
}
function asyncOnSuccess(element, data, contentType) {
var mode;
if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us
return;
}
mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
$(element.getAttribute("data-ajax-update")).each(function (i, update) {
var top;
switch (mode) {
case "BEFORE":
top = update.firstChild;
$("<div />").html(data).contents().each(function () {
update.insertBefore(this, top);
});
break;
case "AFTER":
$("<div />").html(data).contents().each(function () {
update.appendChild(this);
});
break;
default:
$(update).html(data);
break;
}
});
}
function asyncRequest(element, options) {
var confirm, loading, method, duration;
confirm = element.getAttribute("data-ajax-confirm");
if (confirm && !window.confirm(confirm)) {
return;
}
loading = $(element.getAttribute("data-ajax-loading"));
duration = element.getAttribute("data-ajax-loading-duration") || 0;
$.extend(options, {
type: element.getAttribute("data-ajax-method") || undefined,
url: element.getAttribute("data-ajax-url") || undefined,
beforeSend: function (xhr) {
var result;
asyncOnBeforeSend(xhr, method);
result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments);
if (result !== false) {
loading.show(duration);
}
return result;
},
complete: function () {
loading.hide(duration);
getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments);
},
success: function (data, status, xhr) {
asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments);
},
error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"])
});
options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
method = options.type.toUpperCase();
if (!isMethodProxySafe(method)) {
options.type = "POST";
options.data.push({ name: "X-HTTP-Method-Override", value: method });
}
$.ajax(options);
}
function validate(form) {
var validationInfo = $(form).data(data_validation);
return !validationInfo || !validationInfo.validate || validationInfo.validate();
}
$("a[data-ajax=true]").live("click", function (evt) {
evt.preventDefault();
asyncRequest(this, {
url: this.href,
type: "GET",
data: []
});
});
$("form[data-ajax=true] input[type=image]").live("click", function (evt) {
var name = evt.target.name,
$target = $(evt.target),
form = $target.parents("form")[0],
offset = $target.offset();
$(form).data(data_click, [
{ name: name + ".x", value: Math.round(evt.pageX - offset.left) },
{ name: name + ".y", value: Math.round(evt.pageY - offset.top) }
]);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$("form[data-ajax=true] :submit").live("click", function (evt) {
var name = evt.target.name,
form = $(evt.target).parents("form")[0];
$(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$("form[data-ajax=true]").live("submit", function (evt) {
var clickInfo = $(this).data(data_click) || [];
evt.preventDefault();
if (!validate(this)) {
return;
}
asyncRequest(this, {
url: this.action,
type: this.method || "GET",
data: clickInfo.concat($(this).serializeArray())
});
});
}(jQuery));

View File

@ -0,0 +1,5 @@
/*
** Unobtrusive Ajax support library for jQuery
** Copyright (C) Microsoft Corporation. All rights reserved.
*/
(function(a){var b="unobtrusiveAjaxClick",g="unobtrusiveValidation";function c(d,b){var a=window,c=(d||"").split(".");while(a&&c.length)a=a[c.shift()];if(typeof a==="function")return a;b.push(d);return Function.constructor.apply(null,b)}function d(a){return a==="GET"||a==="POST"}function f(b,a){!d(a)&&b.setRequestHeader("X-HTTP-Method-Override",a)}function h(c,b,e){var d;if(e.indexOf("application/x-javascript")!==-1)return;d=(c.getAttribute("data-ajax-mode")||"").toUpperCase();a(c.getAttribute("data-ajax-update")).each(function(f,c){var e;switch(d){case"BEFORE":e=c.firstChild;a("<div />").html(b).contents().each(function(){c.insertBefore(this,e)});break;case"AFTER":a("<div />").html(b).contents().each(function(){c.appendChild(this)});break;default:a(c).html(b)}})}function e(b,e){var j,k,g,i;j=b.getAttribute("data-ajax-confirm");if(j&&!window.confirm(j))return;k=a(b.getAttribute("data-ajax-loading"));i=b.getAttribute("data-ajax-loading-duration")||0;a.extend(e,{type:b.getAttribute("data-ajax-method")||undefined,url:b.getAttribute("data-ajax-url")||undefined,beforeSend:function(d){var a;f(d,g);a=c(b.getAttribute("data-ajax-begin"),["xhr"]).apply(this,arguments);a!==false&&k.show(i);return a},complete:function(){k.hide(i);c(b.getAttribute("data-ajax-complete"),["xhr","status"]).apply(this,arguments)},success:function(a,e,d){h(b,a,d.getResponseHeader("Content-Type")||"text/html");c(b.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(this,arguments)},error:c(b.getAttribute("data-ajax-failure"),["xhr","status","error"])});e.data.push({name:"X-Requested-With",value:"XMLHttpRequest"});g=e.type.toUpperCase();if(!d(g)){e.type="POST";e.data.push({name:"X-HTTP-Method-Override",value:g})}a.ajax(e)}function i(c){var b=a(c).data(g);return!b||!b.validate||b.validate()}a("a[data-ajax=true]").live("click",function(a){a.preventDefault();e(this,{url:this.href,type:"GET",data:[]})});a("form[data-ajax=true] input[type=image]").live("click",function(c){var g=c.target.name,d=a(c.target),f=d.parents("form")[0],e=d.offset();a(f).data(b,[{name:g+".x",value:Math.round(c.pageX-e.left)},{name:g+".y",value:Math.round(c.pageY-e.top)}]);setTimeout(function(){a(f).removeData(b)},0)});a("form[data-ajax=true] :submit").live("click",function(c){var e=c.target.name,d=a(c.target).parents("form")[0];a(d).data(b,e?[{name:e,value:c.target.value}]:[]);setTimeout(function(){a(d).removeData(b)},0)});a("form[data-ajax=true]").live("submit",function(d){var c=a(this).data(b)||[];d.preventDefault();if(!i(this))return;e(this,{url:this.action,type:this.method||"GET",data:c.concat(a(this).serializeArray())})})})(jQuery);